Railsチュートリアル第8章と第9章でログイン機能を学ぶ 復習(前編) Day15-18/30
こんにちは、たわらです。
体調を崩して風邪気味になった日もありましたが、どんどん学習しています。難しくなってきていますね。
いま何をしているのかがまったくわからないときがあります。なので、10章に入る前に8章と9章の復習をします。今回は8章です。
細かいところには立ち入らず、開発の流れをざっくり把握したいと思います。
学んだこと
ログイン機能を実装するのが、8章と9章の目的です。
ログインの基本的な仕組みは、ブラウザがログイン状態を保持し、ユーザーがブラウザを閉じると、ログイン状態を破棄する仕組みのこと。認証システムという。
認証システムができれば、ログイン済みのユーザーだけがアクセスできるページなどの仕組みを実装します。認可モデルという。
第8章と第9章で、次の3つの一般的なログイン機能を実装します。
1 ブラウザを閉じるとログインを破棄する。一時セッション(Session)
2 ユーザーのログイン状態の自動的な保存(Cookie)
3 ユーザーのログイン状態の任意の保存(Remember me)
1 セッションの実装
HTTPはステートレスなプロトコルです。HTTPのリクエストはそれより前のリクエストの情報をまったく利用できない。眠るとすべての記憶がなくなってしまう人物みたいです。
なので、ブラウザにログイン状態を保持させるために、cookiesを利用する。
cookiesは、ユーザーのブラウザに保存されるテキストデータのこと。このテキストデータにユーザーIDを保存することで、ログイン状態を実現することができます。その保存されたデータを使って、データベースから異なるデータを取り出すことができます。ログイン状態かどうかで表示を変えたりできる、ということです。
セッションはRESTfulなリソースとして仕組みを構築します。つまり、newとかcreateとかユーザー登録のときに活用した枠組みを用いる、ということです。
具体的には、ログインページでemailとパスワードを出力し、ログインボタンを押すとcreateでセッションを実際に作成して保存し、ログアウトするとdestroyでセッションを破棄する」という仕組みをつくることになります。
まずログインページを作成します。このログインフォームでは、入力されたデータを、login_pathというURLにPOSTリクエストとして送信し、createアクションを実行する必要があります。
form_forヘルパーを使います。セッションにはモデルがないので、リソースの名前とURLを具体的に指定する必要があります。したがって、:session(リソース)とlogin_path(URL)を記述します。
※なぜここで唐突にリソースというシンボル(?)が出てくるのかが理解できていません。
ここで入力した情報は、paramsというデータのやり取りに使われるハッシュに格納されます。params[:session][:email]などのようにです。
「要するにcreateアクションの中では、ユーザーの認証に必要なあらゆる情報をparamsハッシュから簡単に取り出せるということです」
createアクションのなかでは、params[:session][:email]を手掛かりに、データベースのなかから該当するユーザーをuser変数に格納します。
そして、ログインページで入力されたパスワードと、データベースのパスワードを比較して、マッチするかを確認します。「ユーザーがデータベースにあり、かつ、認証に成功した場合にのみ」ログインできるようにすることはRailsでは定番みたいです。
createアクションのなかでも、さまざまなメソッドを使用するので、その定義は別のところで行います。つまりモジュールを活用するということ。そのモジュールで定義したメソッドはどこでも使えるように、Applicationコントローラーにincludeしておく。
まず、log_inメソッドを定義する。session[:任意の名前]=値 とすればOK。session[:user_id]=user.idとする。
これでデータベースに格納されているuser.idを一時cookiesに暗号化して保存することができます。このメソッドで作成された一時cookiesは、ブラウザを閉じると消去される。
新たに定義したlog_inメソッドでcreateアクションを完成させる。つまり、
1 paramsに格納されたparams[:session][:email]を手掛かりにDBからuserを抽出する。
2 「ユーザーがデータベースにあり、かつ、認証に成功した場合にのみ」
3 log_inメソッドを適用して、ログイン状態を保存する
4 user詳細ページに遷移する
ことができるようになる。なお、2で認証されない場合は、フラッシュメッセージが出る新規登録画面に飛ばされるようにコードを書く。
2 現在のユーザーというインスタンス変数の作成
ユーザーのidが一時セッションに保存されているので、これを利用して、別のページで「現在のユーザー」というインスタンス変数を作成します。この変数を作成しておけば、「現在のユーザーの名前」を表示したりするのに便利だからです。ユーザーがログインしているかどうかに応じてアプリケーションの動作を変更できるようになるのです。
次のようなコードになります。
# 現在ログイン中のユーザーを返す
def current_user
if session[:user_id]
@current_user ||= User.find_by(id: session[:user_id])
end
end
セッションにuser_idが存在している場合、インスタンス変数は、現行の
@current_userを返し、存在しない場合はDBから一時セッションに保存されているデータを使って取り出したuserを格納する、という意味です。
3 ログアウトの実施
log_inメソッドの実行結果を取り消し、一時セッションからユーザーidを削除します。
SessionHelperというモジュールに、log_outメソッドを定義します。
そしてこのlog_outメソッドをdestroyアクションに加えることで、実装できます。
困難なこと、とその対策方法
・メソッドをつくる必要があるかどうかの判断ができない
・どのファイルにメソッドを記述したらよいか判断できない
・テストの記述方法が簡単に浮かばない
これは実際に開発する経験をする過程でしか身につかないのではないか、と思うので、いまはもやもやしたまま前に進みます。
うれしかったこと
開発の流れを意識することで、どんな目的のために何を開発しているのかがわかる。頭のなかに地図があれば、効率的に知識を吸収することができます。
読んでくださったかた、ありがとうございます。
たわら
この記事が気に入ったらサポートをしてみませんか?