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

8章でやる事
→ユーザーがログインやログアウトを出来る様にする

ここでいうログインの基本的な仕組みとは、ブラウザがログインしている状態を保持し、ユーザーによってブラウザが閉じられたら状態を破棄するといった仕組み (認証システム (Authentification System))です。この認証システムの基盤が出来上がったら、ログイン済みのユーザー (current user) だけがアクセスできるページや、扱える機能などを制御していきます。

※適宜日本語化しているので本文とコードが違う部分があります

8.1 セッション

HTTPのリクエスト1つ1つは独立した処理の単位で、それより前のリクエストの情報は利用できない
→あるページから別のページに移動した時にユーザー情報を保持する手段がHTTPプロトコル内には無い
→sessionと呼ばれる接続を別途設定する

cookie

cookie→セッションを実装する一般的な方法
→ユーザーのブラウザに保存される小さなテキストデータ

ログインの仕組みの大半は、cookiesを使った認証メカニズムによって構築されています。

例によって作業用ブランチを作ってから開始ー!

8.1.1 Sessionsコントローラ

ログインとログアウトの要素を、Sessionsコントローラの特定のRESTアクションにそれぞれ対応付けることにします。ログインのフォームは、この節で扱うnewアクションで処理します。createアクションにPOSTリクエストを送信すると、実際にログインします (8.2)。destroyアクションにDELETEリクエストを送信すると、ログアウトします (8.3) (表 7.1のHTTPメソッドとRESTアクションの関連付けを思い出しましょう)。

Rails gでアクションを生成すると、それに対応するビューも生成されるので
対応するビューが必要ないcreateやdestroyはコマンドで指定していない

routes.rb

SessionリソースではフルセットのRESTfulなルーティングは必要ない
→「名前付きルーティング」だけを使用

追加した全ルーティングを表示

まだよくわからないのも(PATCHとかPUTとか)あるけど多分後でやる

演習

  1. GET login_pathとPOST login_pathとの違いを説明できますか? 少し考えてみましょう。
  2. ターミナルのパイプ機能を使ってrails routesの実行結果とgrepコマンドを繋ぐことで、Usersリソースに関するルーティングだけを表示させることができます。同様にして、Sessionsリソースに関する結果だけを表示させてみましょう。現在、いくつのSessionsリソースがあるでしょうか? ヒント: パイプやgrepの使い方が分からない場合は Learn Enough Command Line to Be Dangerousの Section on Grep (英語) を参考にしてみてください。

#1.
GET login_path → getのリクエスト → newアクションを呼び出す → viewの表示
POST login_path → postのリクエスト → createアクションを呼び出す → ログイン

#2.
本文の参考ページが英語過ぎて分からなかった🐫

8.1.2 ログインフォーム

セッションはActive Recordオブジェクトではないのでエラーメッセージの自動生成はされない
→flashメッセージでエラーを表示させる

Active Recordオブジェクトとはなんぞ

Active Recordを継承しているオブジェクト
Active Recordとは→
データオブジェクトの作成/保存/検索のためのメソッドを持つライブラリ
modelとDBの間でデータのやり取りをしてくれるモノ的な?

セッションフォームとユーザー登録フォームの違い

セッションにはSessionモデルというものがなく、そのため@userのようなインスタンス変数に相当するものもない点です

form_forとform_tag

どちらもフォームを作ってくれるヘルパーだけど働きがかなり違う

form_forの代わりにform_tagを使うこともでき、Railsではこの方が慣用的な方法です。しかし、ユーザー登録フォームではform_forを使うのが一般的であり、並列構造を強調するためにもform_forを使いました。

参考



ざっくり言うと
モデルを通してテーブルに情報を追加・編集を行うフォーム→form_for
情報の追加・編集を行わないフォーム→form_tag
この考えで言うとログインフォームは情報の追加・編集が無いからform_tagじゃね?って思うけど
登録フォーム(modelに基づく)と並列構造なので敢えてform_forと言う事っぽい

from_with

form_forとform_tagはRails5.1では非推奨
→form_withに置き換えられる

ログインフォームのコード

ユーザー登録ページのコードを参考にログインフォームを作る

演習

リスト 8.4で定義したフォームで送信すると、Sessionsコントローラのcreateアクションに到達します。Railsはこれをどうやって実現しているでしょうか? 考えてみてください。ヒント:表 8.1とリスト 8.5の1行目に注目してください。

<form accept-charset=”UTF-8″ action=”/login” method=”post”>
→URL「/login」に「post」のリクエスト
→routes.rbに「post ‘/login’, to: ‘sessions#create’」が設定されている
→Sessionsコントローラのcreateアクションが実行される

8.1.3 ユーザーの検索と認証

無効な場合の処理から行っていく

最小限のアクションの設定

createアクションの中では、ユーザーの認証に必要なあらゆる情報をparamsハッシュから簡単に取り出せるということです。

ユーザーをデータベースから見つけて検証する

Railsコンソールを使って、表 8.2のそれぞれの式が合っているか確かめてみましょう. まずはuser = nilの場合を、次にuser = User.firstとした場合を確かめてみてください。ヒント: 必ず論理値オブジェクトとなるように、4.2.3で紹介した!!のテクニックを使ってみましょう。例: !!(user && user.authenticate(‘foobar’))

動作確認のみにて省略

8.1.4 フラッシュメッセージを表示する

ユーザー登録のエラーメッセージ表示にUserモデルのエラーメッセージをうまく利用したことを思い出しましょう。ユーザー登録の場合、エラーメッセージは特定のActive Recordオブジェクトに関連付けられていたのでその手が使えました。しかしセッションではActive Recordのモデルを使っていないため、その手が通用しません。

よって、flashでエラーメッセージを表示させる

flashメッセージが消えない問題

現在のコードのままでは表示されたフラシュメッセージが残り続けてしまう
→renderメソッドで描画したページはリクエストとみなされないため

8.1.5 フラッシュのテスト

上記の「flashメッセージが消えない問題」はこのアプリの小さなバグ
→本文のコラム 3.3に照らし合わせると
「エラーをキャッチするテストを先に書いて、そのエラーが解決するようにコードを書く」に該当する状況
→早速テストを作成する!!

ログインフォームの送信についての統合テスト

統合テストを生成

下記の手順をテストコードで再現する

  1. ログイン用のパスを開く
  2. 新しいセッションのフォームが正しく表示されたことを確認する
  3. わざと無効なparamsハッシュを使ってセッション用パスにPOSTする
  4. 新しいセッションのフォームが再度表示され、フラッシュメッセージが追加されることを確認する
  5. 別のページ (Homeページなど) にいったん移動する
  6. 移動先のページでフラッシュメッセージが表示されていないことを確認する

flash.now

flashをflash.nowに書き換える



大雑把に考えると
flashメッセージを表示させたいページの描写が
→redirect_toの時はflash[:notice]
→renderの時はflash.now[:notice]

実習

  1. 8.1.4の処理の流れが正しく動いているかどうか、ブラウザで確認してみてください。特に、flashがうまく機能しているかどうか、フラッシュメッセージの表示後に違うページに移動することを忘れないでください。

動作確認のみにて省略

まとめとか感想

ActiveRecordについて調べたりform_forとform_tagの違いについて調べたりした
8.1は結構スムーズに進んじゃったので逆に不安!
でも引っ掛かりのあったことはこのページにメモったから!大丈夫と思いたい!

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

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

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