【エラーメモ】画面遷移の条件分岐

条件分岐はプログラミングの基礎の大事さを痛感する。

比較演算子とか論理演算子とか、言葉はぱっと見難しそうだけど、数学の知識としてはそんなに難しいものではない。ただ、条件を式に落とし込むのがまだ少し難しい....。

今回はアプリケーション作成中に、ユーザーによって画面遷移の条件を分岐するというところで躓いたので、メモしていきます。

実装したいこと

ユーザーがログイン状態、かつ本人のみ投稿画面に遷移できる。

(未ログインかつ、投稿者本人以外のユーザーは、URLを直接入力して投稿画面に遷移しようとすると、トップページへ送られる)

やったこと

これまでにもこういった条件分岐はしてきたからそんなに難しくはないなと思ってたら、少し手こずってしまった。

postコントローラーのnewアクションに入ってくる前に振り分けたいので、postコントローラーにおいてbefore_actionを設定していく。

class PostsController < ApplicationController
  before_action :move_to_top, only: :new
#省略
  private
  def move_to_top
    post = Post.new
    unless  user_signed_in? && current_user.id == post.book.user.id
      redirect_to root_path
    end
  end
end

って記述してました。

NoMethodError!!
エラーの内容は、"user" ってなに?ってことで、bookが定義されてないよということ。

なるほど、じゃあbookを定義してあげればいいのか。

class PostsController < ApplicationController
  before_action :move_to_top, only: :new
#省略
  private
  def move_to_top
    post = Post.new
    book = Book.find(params[:id]) #←これを追加
    unless  user_signed_in? && current_user.id == post.book.user.id
      redirect_to root_path
    end
  end
end

bookを定義してあげたからいけるかと思ったんですが、また同じエラーでした。 ん?なんで?

一応、paramsの中身見てみる。 Image from Gyazo

※この画像は解決後に撮りました

言いたいことは、book_idはちゃんとparamsで送られてきてる。 これを使ってユーザーidと結びつけたいんだけど、これじゃ違うの?って感じでした。 そこであれこれ記述を試してみたけどなかなかエラー画面が消えてくれない。 もういちど冷静になって考えてみると、言葉通りでした。 book_idはparamsで送られてきてる。 それ取得したらいい話やん。

そんで、メソッド内でbookを定義してあげたから、postは不要。

てことで、

class PostsController < ApplicationController
  before_action :move_to_top, only: :new
#省略
  private
  def move_to_top
    post = Post.new
    book = Book.find(params[:book_id])
    unless  user_signed_in? && current_user.id == book.user.id
      redirect_to root_path
    end
  end
end

とすると、解決できました。

余談

細かいところかもしれないけど、

if user_signed_in? && current_user.id == post.user.id

っていう定番の形はuser_signed_in?が先にきて、current_user.idが後にくるってところがポイント。
式は左から読みこ込まれて、trueで通過したら右に読み込みが流れてくる。だから、ユーザーがログインしてるかどうかが前提条件の場合、先に判定しておく必要があるため、この順番が逆だったり、user_signed_in?が抜けていたりするとエラーになる。
また、左辺は”ユーザーのid”を表していて、それを比較するんだから当然、右辺も”ユーザーのid”を表してないといけない。うっかり右辺がpost.idとかになってるとそりゃ条件式合わなくてエラーなるよねってこともミスパターンとしてはありそうかなと。

終わりに

エラーがでると解決に向けていろいろ試したり、がむしゃらに向き合う姿勢になってしまって、なかなか仮説検証から「やはりそうか」みたいなスマートな解決ができていない。これを試したらこんなエラー文が出たとかも記録しておく余裕がない。エラーメモという形でアウトプットに残していけるように、焦らず丁寧にエラーと向き合っていけるようにしていきたい。