Railsチュートリアル8章(2周目)メモ

まずこの章ではユーザーがログイン・ログアウトができる機能を実装します。また、そのために必要なユーザー情報をブラウザ上に保存しておくための方法についてを学びます。僕たちが普段使う”http”というプロトコルは「健忘症」的で、以前のリクエスト情報を全く利用できないらしい。だからこそセキュリティが頑丈(データを保持してたら流出の可能性とかも出てくるから)なのだけど、ユーザーIDを保持する手段がHTTPにはないので他の手段を講じる必要がある。それが”session”というもの。

Railsでsessionを実装するにはcookiesというものを使うみたい。これってweb上のcookieと同じなのかな?sessionもRESTアーキテクチャっぽく理解ができて、newで新しいセッションを出力→createで作成して保存→destroyで破棄。でも一つだけUserリソースと違う部分があってそこが「どこのデータにアクセスしてるの?」という点。Userリソースの場合、永続的なデータベースにアクセスしてモデルを介してデータをいじるけど今回のsession”リソース”の場合はcookiesに保存されているデータにアクセスする。とはいえコントローラを作ったりという基本の部分は変わらないよう。

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

コントローラを生成したら例のごとくroutes.rbにルーティングを書いていきます。ですが、前回のresourcesメソッドは使いません。というのも、前回のようなフルセットは必要ないから。余計なものは入れない。new, create, destroyのアクションをそれぞれ記述します。

続いてユーザー登録フォームを書いていくのですが、前回の新規登録と少し違う部分があります。前回はform_for(@user) do |f|みたいなのを書いたんですが、今回はモデルというものがないのでform_forの中身には具体的にリソース名とURLを記述する必要があります。

次にログイン時のcreateアクションの中身を書いていきます。新規登録からの流れをさらっておきます。まず各ユーザーにpassとconfirmation passwordを入力、それをハッシュ化(暗号化みたいな)してデータベースに保存します。ログイン画面ではユーザーがパスワードを送信し、そのパスワードをハッシュ化。データベース内のハッシュと比較し、一致していたら認証が成功してログインできるという流れ。コードは以下の通りです。

次に失敗時のフラッシュメッセージを書いていきたいのですが、これが難しい。違うページへ移動してもそのままメッセージが残ったりしてて厄介。なので統合テストから書くのだけど、その流れがこんな感じ。

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

さて、ここからが本題みたいなもの。次章ではちゃんと長く使えるcookiesを使うけど今回は一時的にログイン情報を保持できるcookiesを使っていく。

このコードの意味を理解するのに若干時間を食った。まずこれuser.id(ユーザーのid)はsession[:user_id]だよっていう意味。このsessionメソッドというのはハッシュと近くて、user_idを暗号化してくれる(一時的に)。なので、このコードを使うとユーザーのIDを暗号化した上で保存し、その後session[:user_id]を使えばいつでもユーザー情報を取り出せるようにしてくれる。

これでユーザーログインは正常に動作するようになったのですが、今のままだと画面上にログイン状態にあるかどうかが表示されておらず判断ができません。なので、この後はセッションに含まれるIDを利用してデータベースから現在のユーザーの名前を取り出して画面上に表示できるようにします。

またまた理解に時間がかかってしまいました。User.find(session[:user_id])の場合、例外が発生(データベースに値がありませんよ)してしまうと扱いが面倒臭い。なぜかというと、今回はデータベースにないパターンではなく、ログインしてないだけパターンが考えられるから。なので今回はその例外が発生せず、値が見つからなかったらnilが返るようにしたい。コードはこんな感じ。

ちなみにfindとfind_byの違いについてちょっとわからなかったところがあったのでQiitaを見てみたら、

システムの挙動として、Recordが見つからないことが織り込み済みの場合は find_by を使って分岐か何かでnilを処理する。見つからないのが異常なら find を使ってエラーを投げて404ページを表示する。

だそうです。

ただ高速化させるためにインスタンス変数に保存したいので、sessionhelperに以下を記述。

とりあえず理解微妙なところを抽出するとこんな感じです。とりあえずこれで8章まで終わったので旅行に出発する3/4までになんとか二周目終わりたい・・!!

シェアする

  • このエントリーをはてなブックマークに追加

フォローする