ログイン機能を実装していきます。
MVCモデルをしっかり意識してないと詰むようになってきます。
- 1. 8.1.1 Sessionsコントローラ
- 1.1. 1.GET login_pathとPOST login_pathとの違いを説明できますか? 少し考えてみましょう。
- 1.2. 2.ターミナルのパイプ機能を使ってrails routesの実行結果とgrepコマンドを繋ぐことで、Usersリソースに関するルーティングだけを表示させることができます。同様にして、Sessionsリソースに関する結果だけを表示させてみましょう。現在、いくつのSessionsリソースがあるでしょうか? ヒント: パイプやgrepの使い方が分からない場合は Learn Enough Command Line to Be Dangerousの Section on Grep (英語) を参考にしてみてください。
- 2. 8.1.2 ログインフォーム
- 3. 8.1.3 ユーザーの検索と認証
- 4. 8.1.5 フラッシュのテスト
- 5. 8.2.1 log_inメソッド
- 6. 8.2.2 現在のユーザー
- 7. 8.2.3 レイアウトリンクを変更する
- 7.1. 1.ブラウザのcookieインスペクタ機能を使って (8.2.1.1)、セッション用のcookieを削除してみてください。ヘッダー部分にあるリンクは非ログイン状態のものになっているでしょうか? 確認してみましょう。
- 7.2. 2.もう一度ログインしてみて、ヘッダーのレイアウトが変わったことを確認してみましょう。その後、ブラウザを再起動させ、再び非ログイン状態に戻ったことも確認してみてください。注意: もしブラウザの [閉じたときの状態に戻す] 機能をオンにしていると、セッション情報も復元される可能性があります。もしその機能をオンにしている場合、忘れずにオフにしておきましょう (コラム 1.1)。
- 8. 8.2.4 レイアウトの変更をテストする
- 9. 8.2.5 ユーザー登録時にログイン
- 9.1. 1.リスト 8.25のlog_inの行をコメントアウトすると、テストスイートは red になるでしょうか? それとも green になるでしょうか? 確認してみましょう。
- 9.2. 2.現在使っているテキストエディタの機能を使って、リスト 8.25をまとめてコメントアウトできないか調べてみましょう。また、コメントアウトの前後でテストスイートを実行し、コメントアウトすると red に、コメントアウトを元に戻すと green になることを確認してみましょう。ヒント: コメントアウト後にファイルを保存することを忘れないようにしましょう。また、テキストエディタのコメントアウト機能については Test Editor Tutorial の Commenting Out (英語) などを参照してみてください。
- 10. 8.3 ログアウト
8.1.1 Sessionsコントローラ
1.GET login_pathとPOST login_pathとの違いを説明できますか? 少し考えてみましょう。
解答
参考サイトを載せておこうと思います。
GETとPOSTの違いについて
GETは何かを取得するとき、POSTはなにかを登録する時に使います。
login_pathを表示したい時はGET,login_pathからデータの登録を行う場合はPOSTですね。
2.ターミナルのパイプ機能を使ってrails routesの実行結果とgrepコマンドを繋ぐことで、Usersリソースに関するルーティングだけを表示させることができます。同様にして、Sessionsリソースに関する結果だけを表示させてみましょう。現在、いくつのSessionsリソースがあるでしょうか? ヒント: パイプやgrepの使い方が分からない場合は Learn Enough Command Line to Be Dangerousの Section on Grep (英語) を参考にしてみてください。
解答
sessionsでgrepすればいいですね。
$ rails routes | grep sessions sessions_new GET /sessions/new(.:format) sessions#new login GET /login(.:format) sessions#new POST /login(.:format) sessions#create logout DELETE /logout(.:format) sessions#delete
8.1.2 ログインフォーム
1.リスト 8.4で定義したフォームで送信すると、Sessionsコントローラのcreateアクションに到達します。Railsはこれをどうやって実現しているでしょうか? 考えてみてください。ヒント:表 8.1とリスト 8.5の1行目に注目してください。
解答
railsdoc見ても分かるのですが、
1:form_forヘルパーはpostメソッドを生成します。
http://railsdoc.com/references/form_for
2:sessionコントローラとlogin_pathを引数に指定しています。
1、2を合わせるとsessionコントローラのcreateアクションがリスト8.4のform_forで指定されていることがわかります。
8.1.3 ユーザーの検索と認証
1.Railsコンソールを使って、表 8.2のそれぞれの式が合っているか確かめてみましょう. まずはuser = nilの場合を、次にuser = User.firstとした場合を確かめてみてください。ヒント: 必ず論理値オブジェクトとなるように、4.2.3で紹介した!!のテクニックを使ってみましょう。例: !!(user && user.authenticate(’foobar’))
解答
以下のようになります。
$ rails c Running via Spring preloader in process 9364 Loading development environment (Rails 5.1.4) irb(main):001:0> user = nil => nil #user = nil,passwordなんでも irb(main):002:0> !!(user && user.authenticate('foobar')) => false irb(main):003:0> user = User.first User Load (0.3ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]] => #<User id: 1, name: "kojimanotech", email: "kojimanotech@email.com", created_at: "2018-07-05 13:56:06", updated_at: "2018-07-05 13:56:06", password_digest: "$2a$10$rqZ1irlA2uVbSBFJF0jWrOUPKPqbowfdrWG3hmiKxWt..."> # user = User.first,password正しい irb(main):004:0> !!(user && user.authenticate('kojima')) # user = User.first,password誤り => true irb(main):005:0> !!(user && user.authenticate('hogehoge')) => false
8.1.5 フラッシュのテスト
1. 8.1.4の処理の流れが正しく動いているかどうか、ブラウザで確認してみてください。特に、flashがうまく機能しているかどうか、フラッシュメッセージの表示後に違うページに移動することを忘れないでください。
解答
8.1.4ではログインエラーのflashメッセージが表示されている時に「Home」をクリックして画面移動しても
flashメッセージが残ってしまうというものでした。
同じ手順を踏んでいき、「Home」をクリックしてからflashメッセージが表示されなくなることを確認してください。
8.2.1 log_inメソッド
1.有効なユーザーで実際にログインし、ブラウザからcookiesの情報を調べてみてください。このとき、sessionの値はどうなっているでしょうか? ヒント: ブラウザでcookiesを調べる方法が分からない? 今こそググってみるときです! (コラム 1.1)
解答
Chromeでcookieを確認する方法
上記サイトを参考にすればできます。
2.先ほどの演習課題と同様に、Expiresの値について調べてみてください。
解答
chromeから参照するとExpiresでなく、有効期限という表示になってますが同意です。
ブラウザセッションの終了時と表示されているはずです。
8.2.2 現在のユーザー
1.Railsコンソールを使って、User.find_by(id: …)で対応するユーザーが検索に引っかからなかったとき、nilを返すことを確認してみましょう。
解答
2.にまとめて記載。ここでは省略。
2.先ほどと同様に、今度は:user_idキーを持つsessionハッシュを作成してみましょう。リスト 8.17に記したステップに従って、||=演算子がうまく動くことも確認してみましょう。
解答
リスト8.17に沿ってやればOKです。
以下のようになることを確認してください。
$ rails c Running via Spring preloader in process 29180 Loading development environment (Rails 5.1.4) irb(main):001:0> session ={} => {} irb(main):002:0> session[:user_id] = nil => nil irb(main):003:0> # 8.2.2.1 irb(main):004:0* @current_user ||= User.find_by(id: session[:user_id]) User Load (1.5ms) SELECT "users".* FROM "users" WHERE "users"."id" IS NULL LIMIT ? [["LIMIT", 1]] => nil irb(main):005:0> session[:user_id] = User.first.id User Load (0.4ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]] => 1 irb(main):006:0> # 8.2.2.2 irb(main):007:0* @current_user ||= User.find_by(id: session[:user_id]) User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] => #<User id: 1, name: "kojimanotech", email: "kojimanotech@email.com", created_at: "2018-07-05 13:56:06", updated_at: "2018-07-05 13:56:06", password_digest: "$2a$10$rqZ1irlA2uVbSBFJF0jWrOUPKPqbowfdrWG3hmiKxWt..."> irb(main):008:0> @current_user ||= User.find_by(id: session[:user_id]) => #<User id: 1, name: "kojimanotech", email: "kojimanotech@email.com", created_at: "2018-07-05 13:56:06", updated_at: "2018-07-05 13:56:06", password_digest: "$2a$10$rqZ1irlA2uVbSBFJF0jWrOUPKPqbowfdrWG3hmiKxWt...">
8.2.3 レイアウトリンクを変更する
1.ブラウザのcookieインスペクタ機能を使って (8.2.1.1)、セッション用のcookieを削除してみてください。ヘッダー部分にあるリンクは非ログイン状態のものになっているでしょうか? 確認してみましょう。
解答
_sample_app_sessionの値を削除してから画面を再読み込みしたものです。
新しいセッションIDが生成されていますが、ヘッダーが非ログイン状態のものになりました。
(他にもいろんなセッションがあるのは気にしないでくだされ…。)
2.もう一度ログインしてみて、ヘッダーのレイアウトが変わったことを確認してみましょう。その後、ブラウザを再起動させ、再び非ログイン状態に戻ったことも確認してみてください。注意: もしブラウザの [閉じたときの状態に戻す] 機能をオンにしていると、セッション情報も復元される可能性があります。もしその機能をオンにしている場合、忘れずにオフにしておきましょう (コラム 1.1)。
解答
再ログインすることでヘッダーが元に戻ることを確認しました。
ブラウザ再起動については省略します。
8.2.4 レイアウトの変更をテストする
1. 試しにSessionヘルパーのlogged_in?メソッドから!を削除してみて、リスト 8.23が redになることを確認してみましょう。
解答
!を消してみます。
# ユーザーがログインしていればtrue,その他ならfalseを返す def logged_in? current_user.nil? end
テストを実行することでREDになることが確認できます。
$ rails test test/integration/users_login_test.rb (中略) Failure: UsersLoginTest#test_login_with_valid_information [/home/vagrant/tutorial2/sample_app/test/integration/users_login_test.rb:26]: Expected exactly 0 elements matching "a[href="/login"]", found 1.. Expected: 0 Actual: 1 bin/rails test test/integration/users_login_test.rb:19 Finished in 0.75131s 2 tests, 8 assertions, 1 failures, 0 errors, 0 skips Finished in 0.762086s, 2.6244 runs/s, 10.4975 assertions/s. 2 runs, 8 assertions, 1 failures, 0 errors, 0 skips
2.先ほど削除した部分 (!) を元に戻して、テストが greenに戻ることを確認してみましょう。
解答
元に戻すだけなので省略。
8.2.5 ユーザー登録時にログイン
1.リスト 8.25のlog_inの行をコメントアウトすると、テストスイートは red になるでしょうか? それとも green になるでしょうか? 確認してみましょう。
解答
こんな聞き方するからredになると見せかけてgreenになるのか?とか思ったりしたのですが、
案の定redになりましたね。
$ rails test Running via Spring preloader in process 12307 Started with run options --seed 53333 Run options: --seed 53333--=---=---=---=---=---=-] 0% Time: 00:00:00, ETA: ??:??:?? # Running: FAIL["test_valid_signup_information", UserSignupTest, 0.8285849249996318] test_valid_signup_information#UserSignupTest (0.83s)6% Time: 00:00:00, ETA: 00:00: Expected false to be truthy. ] 30% Time: 00:00:00, ETA: 00:00:0 test/integration/users_signup_test.rb:32:in `block in <class:UserSignupTest>'. 23/11: [================= ] 47% Time: 00:00:00, ETA: 00:00:.. 23/13: [===================== ] 56% Time: 00:00:00, ETA: 00:00:F 23/18: [============================= ] 78% Time: 00:00:00, ETA: 00:00:00. 23/15: [======================== ] 65% Time: 00:00:00, ETA: 00:00:0Failure:: [========================== ] 69% Time: 00:00:00, ETA: 00:00:0UserSignupTest#test_valid_signup_information [/home/vagrant/tutorial2/sample_app/test/integration/users_signup_test.rb:32]: Expected false to be truthy. bin/rails test test/integration/users_signup_test.rb:21 . 23/21: [================================== ] 91% Time: 00:00:00, ETA: 00:00:0. 23/22: [==================================== ] 95% Time: 00:00:00, ETA: 00:00:0. 23/23: [=====================================] 100% Time: 00:00:00, Time: 00:00:00 . Finished in 0.93738s 23 tests, 59 assertions, 1 failures, 0 errors, 0 skips
assert is_logged_in?がfalseを返してエラーになってました。
sessionにuser_idをセットする処理をすっとばしちゃってるから
session確認したらエラーになって当たり前でしたね。
2.現在使っているテキストエディタの機能を使って、リスト 8.25をまとめてコメントアウトできないか調べてみましょう。また、コメントアウトの前後でテストスイートを実行し、コメントアウトすると red に、コメントアウトを元に戻すと green になることを確認してみましょう。ヒント: コメントアウト後にファイルを保存することを忘れないようにしましょう。また、テキストエディタのコメントアウト機能については Test Editor Tutorial の Commenting Out (英語) などを参照してみてください。
解答
テスト結果についてはほぼ自明n
普通のテキストエディタとかだとctrl+aしてからctrl+kとかctrl+qとかすると
できたりするのですが、私はvim使っているので、全ての行頭に#を付加する方法を紹介しようと思います。
ズバリ
gg0<ctrl+v>Gi#
です!w
gg:一行目に移動
0:行頭に移動
<ctrl+v>:矩形選択モード
G:行末に移動
i:挿入モード
#:#を挿入
ZZ:保存して終了
コメントアウトを解除するときは
gg0
です!
x:1文字削除
を利用します。
8.3 ログアウト
1.ブラウザから [Log out] リンクをクリックし、どんな変化が起こるか確認してみましょう。また、リスト 8.31で定義した3つのステップを実行してみて、うまく動いているかどうか確認してみましょう。
解答
[log out]をクリックすると、
- ホーム画面に遷移
- ヘッダーがログイン前の状態
になります。
リスト8.31で定義した処理の流れは
- ログインする
- ユーザー詳細画面に遷移する
- ログアウトしてホーム画面に遷移する
という流れです。各自確認してみてください。
2.cookiesの内容を調べてみて、ログアウト後にはsessionが正常に削除されていることを確認してみましょう。
解答
is_logged_inのパラメータが落ちます。
sessionは新しく別のができるみたいだけど、これで良いのかがちょっと不明です。
申し訳ありません。
内部の処理を想像できればだいたいどんなことするのかは検討つくとは思います。
実際実装できるかどうかは経験を積まないといけませんが、その検討がつくかつかないかは
エンジニアの自走力に大きく影響すると思います。
私もまだまだ未熟ですが、頑張っていきましょ!