らくだ🐫にもできるRailsチュートリアル|8.2

8.2 ログイン

有効な値の送信があった場合にログインできるようにする!
→cookieを使った一時セッションでログイン
→ブラウザを閉じると自動的に期限切れになるようにする

セッションを実装するには、様々なコントローラやビューでおびただしい数のメソッドを定義する必要があります。(中略)Sessionsコントローラ (8.1.1) を生成した時点で既にセッション用ヘルパーモジュールも (密かに) 自動生成されています。さらに、Railsのセッション用ヘルパーはビューにも自動的に読み込まれます。

ApplicationコントローラにSessionヘルパーモジュールを読み込ませてどのコントローラからでも使えるようにする

8.2.1 log_inメソッド

Railsで元から定義されているsessionメソッドを使って単純なログインを行えるようにする
8.1.1で生成したSessionsコントローラとは無関係なので注意!!

上のコードを実行すると、ユーザーのブラウザ内の一時cookiesに暗号化済みのユーザーIDが自動で作成されます。この後のページで、session[:user_id]を使ってユーザーIDを元通りに取り出すことができます。一方、cookiesメソッド (9.1) とは対照的に、sessionメソッドで作成された一時cookiesは、ブラウザを閉じた瞬間に有効期限が終了します。

Sessionsヘルパーにlog_inという名前のメソッドを定義して、同じログイン手法を使い回せるようにする

一時cookieと永続的なcookies

sessionメソッドで作成した一時cookiesは自動的に暗号化されるので
cookieから情報を盗み出されても、それを使って本物のユーザーとしてログインすることは出来ない
→一時的なセッションでブラウザを閉じると有効期限が終了する為
永続的なcookieに関してはセッションハイジャックという攻撃を受ける可能性が常につきまとう!
→9章に続く

createアクションの完了

作成したヘルパーメソッドを使ってユーザーとしてログインできる様に
sessionsコントローラーのcreateアクションを完成させる

ログインフォームが作動するようになっている!

演習

  1. 有効なユーザーで実際にログインし、ブラウザからcookiesの情報を調べてみてください。このとき、sessionの値はどうなっているでしょうか? ヒント: ブラウザでcookiesを調べる方法が分からない? 今こそググってみるときです!
  2. 先ほどの演習課題と同様に、Expiresの値について調べてみてください。

1.ブラウザ(chrome)の設定→詳細設定→プライバシーとセキュリティ→サイトの設定
→Cookie とサイトデータ→すべての Cookie とサイトデータを表示→


2.Expires→有効期限(ブラウザ セッションの終了時)

8.2.2 現在のユーザー

ユーザーIDを安全に一時セッションの中に置けるようになった!
なので、そのユーザーIDを別のページで取り出せるようにする
→current_userメソッドを定義する

「ユーザーがログインしていない」などの状況が考えられる今回のケースでは、session[:user_id]の値はnilになりえます。

なのでfind_byメソッドを使ってcurrent_userを定義していく

演習

  1. Railsコンソールを使って、User.find_by(id: …)で対応するユーザーが検索に引っかからなかったとき、nilを返すことを確認してみましょう。
  2. 先ほどと同様に、今度は:user_idキーを持つsessionハッシュを作成してみましょう。リスト 8.17に記したステップに従って、||=演算子がうまく動くことも確認してみましょう。

上下(25行目と29行目)の@current_user ||= User.find_by(id: session[:user_id])
の違い

式は条件を満たしたら処理を行って終了する
上の@current_user ||= User.find_by(id: session[:user_id])は
@current_userに何も代入されていないので、次のUser.find_by(id: session[:user_id])に進む
下の@current_user ||= User.find_by(id: session[:user_id])は
@current_userにidが1のユーザーが代入されているので@current_userを返して終了
(Userモデルにデータを探しに行かない)

8.2.3 レイアウトリンクを変更する

ユーザーがログインしている時とそうでない時でレイアウトを変更する
RoRT 本文 8.2.3 図8.7参照
ログインが成功している時はアカウントメニューとして下記を表示

  • 「ログアウト」リンク
  • 「ユーザー設定」リンク
  • 「ユーザー一覧」リンク
  • 「プロフィール表示」リンク

→テスト駆動開発の流れとしてはここで統合テストを書くところだけど後でとこのと

logged_in?メソッドを定義

このために必要な論理値を返すlogged_in?メソッドを定義していく
ユーザーがログイン中の状態とは「sessionにユーザーidが存在している」こと、つまりcurrent_userがnilではないという状態を指します。これをチェックするには否定演算子 (4.2.3) が必要なので、! を使っていきます

logged_in?ヘルパーメソッドを利用して
ログインの有無によってlayoutが変わるようにヘッダー部分を書き換える

ドロップダウン機能を有効にするため、Railsのapplication.jsファイルを通して、Bootstrapに同梱されているJavaScriptライブラリとjQueryを読み込むようアセットパイプラインに指示します

ログインパスにアクセスして有効なユーザー (ユーザー名がexample@railstutorial.org、パスワードがfoobar) としてログインできるようになっているので、これまでの3つのセクションのコードを効率よくテストできるようになります

また、ブラウザを閉じるとcookieが消去され、再度ログインを要求されるようになっている
→クラウドIDE利用の場合はそうならないっぽい(他のブラウザを使って試しましょうとの事)

演習

  1. ブラウザのcookieインスペクタ機能を使って (8.2.1.1)、セッション用のcookieを削除してみてください。ヘッダー部分にあるリンクは非ログイン状態のものになっているでしょうか? 確認してみましょう。
  2. もう一度ログインしてみて、ヘッダーのレイアウトが変わったことを確認してみましょう。その後、ブラウザを再起動させ、再び非ログイン状態に戻ったことも確認してみてください。注意: もしブラウザの [閉じたときの状態に戻す] 機能をオンにしていると、セッション情報も復元される可能性があります。もしその機能をオンにしている場合、忘れずにオフにしておきましょう

動作確認のみにて省略

8.2.4 レイアウトの変更をテストする

ログインの統合テスト

  1. ログイン用のパスを開く
  2. セッション用パスに有効な情報をpostする
  3. ログイン用リンクが表示されなくなったことを確認する
  4. ログアウト用リンクが表示されていることを確認する
  5. プロフィール用リンクが表示されていることを確認する

fixture

テスト用の初期データ(ざっくり)

自分でfixtureファイルを作成してデータを追加する

有効な名前とメールアドレス、パスワードを用意する
Sessionsコントローラのcreateアクションに送信されたパスワードと比較できるようにする必要もある
→password_digest属性をユーザーのfixtureに追加

digestメソッドを独自に定義する

has_secure_passwordでbcryptパスワードが作成されるので、同じ方法でfixture用のパスワードを作成します。

上記を利用したfixture向けのdigestメソッドをUserモデルに追加

digestメソッドを定義したので有効なユーザーを表すfixtureが作成できるようになる

has_secure_passwordで必要となるpassword_digest属性はこれで準備できましたが、ハッシュ化されていない生のパスワードも参照できると便利です。しかし残念なことに、fixtureではこのようなことはできません。

また、上記のusers.ymlにpassword属性を追加するとエラーが発生する(DBに「password」というカラムが存在しないため)
なので、よく使う手法としてテスト用のfixtureでは全員同じパスワード「password」とする

ログインのテスト

アクセス可能なユーザーデータが出来たのでレイアウトのリンクのテストを定義する
(前述の手順をコードに落とし込む)

演習

  1. 試しにSessionヘルパーのlogged_in?メソッドから!を削除してみて、リスト 8.23が redになることを確認してみましょう。
  2. 先ほど削除した部分 (!) を元に戻して、テストが greenに戻ることを確認してみましょう。

1.!を取るとユーザーがnilの時trueになるためRED
2.戻せば戻る

8.2.5 ユーザー登録時にログイン

以上で認証システムが動作するようになりましたが、今のままでは、登録の終わったユーザーがデフォルトではログインしていないので、ユーザーがとまどう可能性があります。

ユーザー登録時にログインする設定

ユーザー登録時にログインする動作のテスト

logged_in?ヘルパーメソッドとは別に、is_logged_in?ヘルパーメソッドを定義する
→取り違えやら何やら何やらを防ぐために名前をかぶらせないように気を付ける!

残念ながらヘルパーメソッドはテストから呼び出せないので、リスト 8.18のようにcurrent_userを呼び出せません。sessionメソッドはテストでも利用できるので、これを代わりに使います。

is_logged_in?ヘルパーメソッドを使って
ユーザー登録後にログイン状態になっているかをテストする

演習

  1. リスト 8.25のlog_inの行をコメントアウトすると、テストスイートは red になるでしょうか? それとも green になるでしょうか? 確認してみましょう。
  2. 現在使っているテキストエディタの機能を使って、リスト 8.25をまとめてコメントアウトできないか調べてみましょう。また、コメントアウトの前後でテストスイートを実行し、コメントアウトすると red に、コメントアウトを元に戻すと green になることを確認してみましょう。ヒント: コメントアウト後にファイルを保存することを忘れないようにしましょう。また、テキストエディタのコメントアウト機能については Test Editor Tutorial の Commenting Out (英語) などを参照してみてください。

1.log_inの行→コメントアウトするとユーザー登録直後にログイン状態にならないのでRED
2.[ctrl+A]で全選択→[ctrl+/]でまとめてコメントアウト(Win)→保存→RED→戻す→GREEN

まとめとか感想

ログインの仕組みを作る
ユーザー登録時にそのままログイン状態になるって言うのは大事!と、思いました🐫

ちゃんと頭でわかりながら進められているか不安だけど
分からない所はメモってるし、後で気づいたら書き足せばいいから良し!とする!!

らくだ🐫にもできるRailsチュートリアルとは

「ド」が付く素人のらくだ🐫が勉強するRailsチュートリアルの学習記録です。
自分用に記録していますが、お役に立つことがあれば幸いです。

調べたとはいえらくだ🐫なりの解釈や説明が含まれます。間違っている部分もあるかと思います。そんな所は教えて頂けますと幸いなのですが、このブログにはコメント機能がありません💧お手数おかけしますがTwitterなどでご連絡いただければ幸いです