どうも!chuckです。
引き続き、Railsでロシア語単語帳を作っていきます。今回はサインインとサインアウトの機能を実装していきます!
あっ、ちなみにグーグルで「ロシア語 単語帳」と検索すると、このブログが3番めに出ますw
やっぱり、ロシア語の学習環境はまだまだ貧弱ってことですね(;・∀・)
早く完成させて公開したいところです。
Session関連を整える
コントローラを作る
Sessionコントローラというものを作ります。このコントローラのcreateアクションにPOSTリクエストが送られたときにサインインを、destroyアクションにDELETEアクションが送られたときにサインアウトを処理させます(ちょっと日本語変かも、、、)
HTTPリクエストとRESTアクションの対応がだんだんと分かってきました!ヽ(=´▽`=)ノ
rails generate controller Sessions --no-test-framework コマンドを発行してSessionコントローラを作成。(今度はちゃんと複数形にした!)
rails generate integration_test authentication_pages コマンドで認証システムをテストする結合テストを作成します。
ルーティング
コントローラを作成したので、ルーティングをします。
config/routes.rb
アカウント機能の追加でも利用した、便利なresoucesを使います。
ただし、今回はsessionを編集したりビューに表示しないので、:onlyオプションを追加します。有効なアクションをnew,create,destroyに限定します
また、7,8行目に名前付きルートも追加しています。
その結果、ルーティングは以下のように。
アクションの作成
と言っても、枠を用意しただけですが…(;・∀・)
app/controllers/sessions_controller.rb
ビューの作成
app/views/sessions/new.html.erb
シンプルですが、ファイルを新規作成。
テスト
spec/requests/authentication_pages_spec.rb
ここまでひとまずテストはパスします。
サインイン
Sessionの準備ができたので、いよいよサインインにとりかかります。
サインインフォームの作成
app/views/sessions/new.html.erb
アカウント作成と同じく、form_forタグを使っています。ただし前回と異なり、Sessionにはモデルは存在しません。
なので、<% form_for(:session, url: session_path) do | f | %>のように、丸括弧の中でリソース名とURLを渡してあげる必要があります。
(うーん、よく分からない…そういうものなのかなヽ(´Д`;)ノ)
見た目はこんな風になりました。
下の方にリンクがついてますね!アカウントを持っていない人向けに、アカウント作成画面へと誘導しています。
フォームの確認
ここでフォームについて確認しておきます。
上記のform_forタグはHTTPリクエストのPOSTリクエストを送ります。そしてその中身は以下のとおり。
sessionというハッシュを送っているのです。つまり、sessionの中に{ email: "aaa", password: "aaa" }が入っています。
なのでemailの値を取り出したい時は、params[:session][:password] と記述します。
ユーザーの認証
sesisonコントローラに追記
app/controllers/sessinos_controllers.rb
6行目では入力されたemailを使ってユーザーを取得し、user変数に格納しています。
7行目ではhas_secure_passwordのauthenticateメソッドを使っています。このメソッドは認証に失敗するとfalseを返すので、その後に条件分岐をかけています。
サインインの失敗
サインインが失敗した場合、つまりcreateアクションでelseに入った時、エラーメッセージを表示してサインインページをもう一度表示します。
app/controllers/sessinos_controllers.rb
こんな感じになります。
サインインの成功
if文のtrue判定の処理に追記します。
app/controllers/sessinos_controllers.rb
一見完成したように見えますが、まだ課題が残っています。それは4行目のsign_in関数を作成することです(;・∀・)
Sessionヘルパーのインクルード
便利な部品であるヘルパーをインクルードします。
app/controllers/applicatoin_controller.rb
記憶トークンの作成
ブラウザを閉じてもサインイン状態を保持するために、モデルにカラムを追加します。それが記憶トークン(remember_token)です。
まずはテストに追記。
カラムを追加。カラムの追加はもう慣れたもんです(=´▽`=)
作成したマイグレーションファイルに追記。
ユーザーを記憶トークンで検索できるように、indexも追加しています。(どういうこっちゃ…)
記憶トークンには安全面から、ランダムな文字列を採用します。そこで使うのが、SecureRandomモジュールのurl_base64。
モデルへの記憶トークンの保持
userモデルに記憶トークンを保持させます。
app/model/user.rb
3行目でコールバックを使用。その呼ばれるメソッドが後半の17行目以降になります。
Sign_in関数の作成
モデルの準備が整ったので、ようやく sign_in関数を作成することができます。
app/helpers/sessions_helper.rb
こんな処理をしています。
1,トークンを新規作成
2,クッキーに保存
3,暗号化したトークンをDBに保存
4,与えられたユーザーを現在のユーザーにする
現在のユーザーの作成
sign_in関数で用いているcurrent_userを定義します。
さらに、クッキーから記憶トークンを取り出して現在のユーザーに渡す処理を||=で書いています。||=を使うことにより、ユーザーがWebサイトにアクセスすると、最低1回は記憶トークンを元にユーザーを検索します。(自分でも何を言ってるのかわからない…)
app/helpers/sessions_helper.rb
さらに、ユーザーがサインインしているかどうかでビューを分けたいので、メソッドを追加します。
9〜11行目がそれに当たります。current_userがnilかどうかで判定しています。
これにて、サインインに必要な機能が完成しました!
動作確認
必要な情報を入力します。
すると、サインインに成功して個人ページに飛びます。
まとめ
うーん、サインイン機能が完成したはいいけど、結局またRailsチュートリアルにベッタリだった…ヽ(´Д`;)ノアゥア…
current_userあたりはあんまり理解してないかも…。まあ、今はこれでいっか!まずはとにかくひと通り完成させよう!
Follow Me :)
ロシア語単語帳でググったら検索順位3位だったw pic.twitter.com/SYCESapIg6
— タク(chuck) (@chuck0523) 2015, 7月 25