<Rails> user_signed_in?って本当に必要なの?
素朴な疑問かもしれませんが、Railsでツイッターのようなアプリのコードを眺めていた時にこの疑問にぶち当たりました。
ツイートの一覧を表示するビューの中で、もし表示されているツイートと現在ログインしているユーザーが同じであればツイートの編集リンクと削除リンクを表示させる、というロジックですね。
以下のコードです。
<% if user_signed_in? && current_user.id == tweet.user_id %> <li> <%= link_to '編集', "/tweets/#{tweet.id}/edit", method: :get %> </li> <li> <%= link_to '削除', "/tweets/#{tweet.id}", method: :delete %> </li> <% end %>
deviseを使っているのでuser_signed_in?とcurrent_userメソッドが使えます。
あと@tweetsがcollectionでコントローラーから渡されてます。
なぜuser_signed_in?が不必要ではないかと疑問を持ったかというと、current_userメソッドはユーザーがログインしているからcurrent_user.idでそのユーザーのIDを取ってこれるわけで、であればログインしているかどうか条件分岐してくれるuser_signed_in?メソッドはいらないのではないかと、そう思ったわけです。
つまり以下のようなコードでいいんじゃないかと考えました。
<% if current_user.id == tweet.user_id %> <li> <%= link_to '編集', "/tweets/#{tweet.id}/edit", method: :get %> </li> <li> <%= link_to '削除', "/tweets/#{tweet.id}", method: :delete %> </li> <% end %>
ですがこれだとうまくいきません。
ユーザーがログインしていない場合、このコードだとcurrent_userがnilになり、current_user.idを取りに行けないのでエラーでアプリが止まります。ユーザーにいつも我々が見てるあの紅のエラー画面を見せることになります。
あれ?でもuser_signed_in?も同じような挙動じゃないの?と思ったんですが、user_signed_in?の場合はユーザーがログインしてなかったらこのif文自体全部スキップさせるようです。なのでcurrent_user.idを参照することなく、end以降にジャンプします。なのでユーザーがログインしてなくてもあのエラー画面には遷移しないようです。
というわけで、ユーザーがログインしていて、かつそのユーザーが投稿している場合、といったロジックはuser_signed_in?とcurrent_user.id == hoge.idの組み合わせが必要です。
終わり
僕が疑問に思ったかのように書いてますが、スクールの友人がペアプログラミング中に言ってくれたんですけどね。
いやーペアプログラミング面白いっすね。めちゃくちゃ勉強になります。