読者です 読者をやめる 読者になる 読者になる

コンパイラかく語りき

import { Fun } from 'programming'

RubyOnRailsチュートリアル8章(後半)

どうも!chuckです。8章の学習が終わりましたのでメモ。

 

8章 サインイン、サインアウト

ここまではサインインが失敗した場合を実装しました。ここからはサインインが成功する場合を実装していきます。

 

Sign_in関数をつくろう

なにはともあれ、Sign_in関数を完成させます。ここでの目標はユーザの登録が完了して、プロフィールページへとリダイレクトされることです。

サインイン関数は、新しくモジュールを作成する手もありますが、ここではSessionHelperを使います。なぜならばサインイン関数はビューとコントローラから参照される必要があるからです。

Helperならばビューから無条件で使えますし、コントローラとの連携もincludeの記述を追加するだけで済みます。

 

ユーザ情報の保持の仕方

HTTPリクエストは基本的にはステートレスです。つまりセッションが保持されません。ここではCookieに情報を保持させることにします。これならばCookieを参照することでページをまたいでもユーザを追跡することができます。

 

記憶トークン

そこで登場するのが記憶トークンです。この記憶トークンにサインインしたユーザの情報を保持させます。

f:id:chuck0523:20150705132320p:plain

このSessionオブジェクトがCookieにユーザーIDを追加してくれます。

 

また、記憶トークンとユーザを関連付けるためにモデルに変更を加えます。

f:id:chuck0523:20150705132743p:plain

 

一方、実際のコマンドはこちら。

f:id:chuck0523:20150705132930p:plain

addでレコードを追加するんですね。

 

モデルを変更したので、おなじみのモデル更新コマンド。

f:id:chuck0523:20150705133327p:plain

 

さらに、記憶トークンを検索できるようにindexを振っておきます。

f:id:chuck0523:20150705133243p:plain

 

ユーザ認証の方向性

さて、これでモデルの準備が整いました。

ここでは記憶トークンにはSecureRandomモジュールの持つurlsafe_base64メソッドを利用することにします。これは長さ16の英数字ランダム文字列を返します。

 

認証の方向性としては、ブラウザにこのbase64トークンを保存しておき、DBにはトークンを暗号化したものを保存しておきます。そしてCookieからトークンを読みだして、暗号化してDB上のものと照会します。これでユーザを自動的にサインインさせます。

 

記憶トークンのテスト

まずテストユーザーを保存して、そのユーザの記憶トークンが空でないことを確認します。

 

ここで、before_createというコールバックを利用する。

f:id:chuck0523:20150705140049p:plain

create_remember_tokenはメソッド参照というもので、同名のメソッドを探してくれる。

 

f:id:chuck0523:20150705140219p:plain

こちらがそのメソッド。まずランダム文字列を作って暗号化、そしてユーザーの属性の一つに要素代入をしている。selfを使っているのがそれにあたり、これがないと新しくローカル変数が作られてしまう。

 

これらを最終的にユーザーモデルに記述したのがこちら。

冒頭のbefore_createを忘れないようにしたい。

f:id:chuck0523:20150705140756p:plain

 

Sign_inメソッドの実装

いよいよSign_inメソッドの実装です。

こちらがSign_in関数

f:id:chuck0523:20150705141144p:plain

def sign_in(user)の中身を1行ずつ見ていくと、

1, トークンを新規作成。

2, 暗号化されていないトークンをブラウザのCookieに保存。

3, 暗号化されたトークンをDBに保存。

4, 与えられたユーザーを現在のユーザーに設定。

といった感じ。うん、流れはわかるけど、新規要素多すぎ…(ヽ´ω`)笑

 

さて、ここで未実装なのがcurrent_user。これを実装していく。

current_userはビューからもコントローラからもアクセスできる必要がある。

そうすることで以下の構文を使用できるようになる。(そうなんだ)

f:id:chuck0523:20150705141624p:plain

f:id:chuck0523:20150705141634p:plain

 

ちなみに、ここでもcurrent_userへは要素代入する必要がある。

そのための記述がこちら。

f:id:chuck0523:20150705141955p:plain

(なんだこれは…)

 

remember_tokenを使用して現在のユーザを検索するための、最終的なコード。

f:id:chuck0523:20150705142121p:plain

| |=とかいう変な論理演算子が見えるけど、きっと気のせいだろう。今はスルーしよう(ヽ´ω`)

 

 

レイアウト変更

サインインの状態に応じてレイアウトを変更します。

埋め込みRubyのif-elseを利用する。

f:id:chuck0523:20150705142334p:plain

なので、signed_in?論理値を定義する必要がある。

 

 ユーザーがサインインしている状態とはつまり、セッションに現在のユーザがいることで表せる。(current_user != nil

 

また、この後、サインアップ(登録)した後にも個別のプロフィールページに飛ぶように設定。

 

以上でサインイン、サインアウト機能は完成ですヽ(=´▽`=)ノ

次回は9章 ユーザーの更新・表示・削除です。