セキュリティ系の勉強、その他開発メモとか雑談. GithubはUnity触っていた頃ものがメイン Twitterフォローもよろしくです

【Ruby On Rails】ネストとガード節

ネストがひどい

下のコードがスマートじゃない。(リダイレクトのパスとかは適当です)

# hoge_controller.rb
  def destroy
    if target = User.find_by(id: params["id"])
      if current_user.unfollow(target) #フォローを外すみたいな動作
        flash[:info] = I18n.t("hoge.destroy.success")
      else
        flash[:danger] = I18n.t("hoge.destroy.failure")
      end
    else
      flash[:danger] = I18n.t("hoge.destroy.user_not_found")
    end  
    redirect_to(root_path)
  end


RuboCop先生曰く、制御構文で条件式のネストは避けましょう。とのこと。ガード節を使います。

ガード節

不正なデータを弾きたいときはガード節を使いましょう。 ガード節とは、できるだけ素早く関数から抜けられるようにと 関数の先頭に置かれている条件文のことです。
https://github.com/fortissimo1997/ruby-style-guide/blob/japanese/README.ja.md#no-nested-conditionals

return ~ unlessを使用して、予期しない条件の場合はこれ以降関係ないっすよ。ってしてあげることで、見た目的にも読みやすくなる気がします。if~elseが適しているものとして、条件分岐に相対性があるものとの噂もあったので、

# hoge_controller.rb
  def destroy
    target = User.find_by(id: params["id"])
    return redirect_to(root_path, flash: { danger: I18n.t("hoge.destroy.user_not_found") }) unless target

    if current_user.unfollow(target)
      flash[:info] = I18n.t("hoge.destroy.success")
    else
      flash[:danger] = I18n.t("hoge.destroy.failure")
    end
    redirect_to(root_path)
  end

余談

上のコードのガード節でfind_by行までまとめて1行で書く場合、

return redirect_to(root_path, flash: { danger: I18n.t("hoge.destroy.user_not_found") }) unless (target = User.find_by(id: params["id"]))

とかけますが、target変数の出どころがわかりにくいので、2行にしてます。また、上記の場合、unlessの条件に()つけないと、RuboCop先生に注意されますが、コード自体は走ります。(==のタイポと思われる)