コンパイラかく語りき

import { Fun } from 'programming'

文系プログラマーがRailsでロシア語アプリケーションをつくる⑭ ~サインイン機能~

どうも!chuckです。

引き続き、Railsでロシア語単語帳を作っていきます。今回はサインインとサインアウトの機能を実装していきます!

 

chuckwebtips.hatenablog.com

 

あっ、ちなみにグーグルで「ロシア語 単語帳」と検索すると、このブログが3番めに出ますw

 

f:id:chuck0523:20150726134654p:plain

やっぱり、ロシア語の学習環境はまだまだ貧弱ってことですね(;・∀・)

早く完成させて公開したいところです。

 

 

Session関連を整える

コントローラを作る

Sessionコントローラというものを作ります。このコントローラのcreateアクションにPOSTリクエストが送られたときにサインインを、destroyアクションにDELETEアクションが送られたときにサインアウトを処理させます(ちょっと日本語変かも、、、)

 

HTTPリクエストとRESTアクションの対応がだんだんと分かってきました!ヽ(=´▽`=)ノ

 

rails generate controller Sessions --no-test-framework コマンドを発行してSessionコントローラを作成。(今度はちゃんと複数形にした!)

f:id:chuck0523:20150726135624p:plain

 

rails generate integration_test authentication_pages コマンドで認証システムをテストする結合テストを作成します。

f:id:chuck0523:20150726140300p:plain

 

ルーティング

コントローラを作成したので、ルーティングをします。

f:id:chuck0523:20150726140559p:plain

config/routes.rb

アカウント機能の追加でも利用した、便利なresoucesを使います。

ただし、今回はsessionを編集したりビューに表示しないので、:onlyオプションを追加します。有効なアクションをnew,create,destroyに限定します

また、7,8行目に名前付きルートも追加しています。

 

その結果、ルーティングは以下のように。

f:id:chuck0523:20150726140834p:plain

 

アクションの作成

と言っても、枠を用意しただけですが…(;・∀・)

f:id:chuck0523:20150726141107p:plain

app/controllers/sessions_controller.rb

 

ビューの作成

f:id:chuck0523:20150726141317p:plain

app/views/sessions/new.html.erb

シンプルですが、ファイルを新規作成。

 

テスト

f:id:chuck0523:20150726141446p:plain

spec/requests/authentication_pages_spec.rb

 

ここまでひとまずテストはパスします。

 

サインイン

Sessionの準備ができたので、いよいよサインインにとりかかります。

 

サインインフォームの作成

f:id:chuck0523:20150726142808p:plain

app/views/sessions/new.html.erb

 

アカウント作成と同じく、form_forタグを使っています。ただし前回と異なり、Sessionにはモデルは存在しません。

なので、<% form_for(:session, url: session_path) do | f | %>のように、丸括弧の中でリソース名とURLを渡してあげる必要があります。

(うーん、よく分からない…そういうものなのかなヽ(´Д`;)ノ)

 

見た目はこんな風になりました。

f:id:chuck0523:20150726143544p:plain

下の方にリンクがついてますね!アカウントを持っていない人向けに、アカウント作成画面へと誘導しています。

 

フォームの確認

ここでフォームについて確認しておきます。

上記のform_forタグはHTTPリクエストのPOSTリクエストを送ります。そしてその中身は以下のとおり。

f:id:chuck0523:20150726144407p:plainsessionというハッシュを送っているのです。つまり、sessionの中に{ email: "aaa", password: "aaa" }が入っています。

なのでemailの値を取り出したい時は、params[:session][:password] と記述します。

 

ユーザーの認証

sesisonコントローラに追記

f:id:chuck0523:20150726145149p:plain

 app/controllers/sessinos_controllers.rb

 

6行目では入力されたemailを使ってユーザーを取得し、user変数に格納しています。

7行目ではhas_secure_passwordauthenticateメソッドを使っています。このメソッドは認証に失敗するとfalseを返すので、その後に条件分岐をかけています。

 

サインインの失敗

サインインが失敗した場合、つまりcreateアクションでelseに入った時、エラーメッセージを表示してサインインページをもう一度表示します。

f:id:chuck0523:20150726150113p:plain

 app/controllers/sessinos_controllers.rb

こんな感じになります。

 

サインインの成功

if文のtrue判定の処理に追記します。

f:id:chuck0523:20150726150213p:plain

 app/controllers/sessinos_controllers.rb

 

一見完成したように見えますが、まだ課題が残っています。それは4行目のsign_in関数を作成することです(;・∀・)

 

Sessionヘルパーのインクルード

便利な部品であるヘルパーをインクルードします。

f:id:chuck0523:20150726152130p:plain

app/controllers/applicatoin_controller.rb

 

記憶トークンの作成

ブラウザを閉じてもサインイン状態を保持するために、モデルにカラムを追加します。それが記憶トークン(remember_token)です。

 

まずはテストに追記。

f:id:chuck0523:20150726152519p:plain

 

カラムを追加。カラムの追加はもう慣れたもんです(=´▽`=)

f:id:chuck0523:20150726152711p:plain

 

作成したマイグレーションファイルに追記。

f:id:chuck0523:20150726152910p:plain

ユーザーを記憶トークンで検索できるように、indexも追加しています。(どういうこっちゃ…)

 

記憶トークンには安全面から、ランダムな文字列を採用します。そこで使うのが、SecureRandomモジュールのurl_base64

 

モデルへの記憶トークンの保持

userモデルに記憶トークンを保持させます。

f:id:chuck0523:20150726154846p:plain

app/model/user.rb

 

3行目でコールバックを使用。その呼ばれるメソッドが後半の17行目以降になります。

 

Sign_in関数の作成

モデルの準備が整ったので、ようやく sign_in関数を作成することができます。

f:id:chuck0523:20150726155143p:plain

app/helpers/sessions_helper.rb

 

こんな処理をしています。

1,トークンを新規作成

2,クッキーに保存

3,暗号化したトークンをDBに保存

4,与えられたユーザーを現在のユーザーにする

 

現在のユーザーの作成

sign_in関数で用いているcurrent_userを定義します。

さらに、クッキーから記憶トークンを取り出して現在のユーザーに渡す処理を||=で書いています。||=を使うことにより、ユーザーがWebサイトにアクセスすると、最低1回は記憶トークンを元にユーザーを検索します。(自分でも何を言ってるのかわからない…)

f:id:chuck0523:20150726160212p:plain

app/helpers/sessions_helper.rb

 

さらに、ユーザーがサインインしているかどうかでビューを分けたいので、メソッドを追加します。

f:id:chuck0523:20150726160337p:plain

9〜11行目がそれに当たります。current_userがnilかどうかで判定しています。

 

これにて、サインインに必要な機能が完成しました!

 

動作確認

必要な情報を入力します。

f:id:chuck0523:20150726161836p:plain

 

すると、サインインに成功して個人ページに飛びます。

f:id:chuck0523:20150726161907p:plain

 

まとめ

うーん、サインイン機能が完成したはいいけど、結局またRailsチュートリアルにベッタリだった…ヽ(´Д`;)ノアゥア…

current_userあたりはあんまり理解してないかも…。まあ、今はこれでいっか!まずはとにかくひと通り完成させよう!

 

Follow Me :)