<Rails> user_signed_in?って本当に必要なの?

 

f:id:b1840943:20180531190214p:plain

 

素朴な疑問かもしれませんが、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の組み合わせが必要です。

 

終わり

僕が疑問に思ったかのように書いてますが、スクールの友人がペアプログラミング中に言ってくれたんですけどね。

 

いやーペアプログラミング面白いっすね。めちゃくちゃ勉強になります。