はじめに
Railsチュートリアル第8章のログイン機構についてのまとめ記事です。
筆者もまだまだ未熟者ですので間違っているところなどはバシバシコメント欄などで指摘してください。
なお演習の解説や答えなどは載っていません
また、いくつかまとめていない節があります(基本的に難しいと感じるところだけを取り上げています)
セッション
まずはhttpについて解説します。
httpとはステートレス(Stateless)なプロトコルです。
ステートレスとは文字通り「状態(state)」が「ない(less)」ことです。
HTTPリクエストの1つ1つは前のリクエストの情報を全く利用できないのです。
例えば前のHTTPリクエストがAという情報を持っていたとしても2つ目のHTTPリクエストは情報が利用できないので、その前のHTTPリクエストによって動きを変えることができません。
つまりログインしたところでページを移動してしまうとログイン状態が保持されないのです。
これはHTTPリクエストの特徴であり、ステートレスだからこそシンプルで使いやすく発展したとも言えます。
しかしログイン状態を保持できないのなら使い物になりません。
そこでセッション(Session)と呼ばれる半永続的な接続をコンピューター間(パソコンやスマホのwebブラウザとRailsサーバーなど)に別途で設定します。
セッションはHTTPプロトコルとはOSI参照モデルの階層が違うのでHTTPとの特性とは別に(若干影響を受けるものの)接続を確保できます。

引用:https://bit.ly/3m7muyE (短縮urlです)
HTTPやftp、dnsなどは一番上のアプリケーション層ですが、セッションはセッション層でお互いに違う階層にいることがわかります。
Railsでセッションを実装する方法として最も一般的なのはcookiesを使う方法です。
Cookieとは
Cookieとは、Webサイトの提供者が、Webブラウザを通じて訪問者のコンピュータに一時的にデータを書き込んで保存させる仕組み。 CookieにはWebサイト(Webサーバ)側が指定したデータを保存しておくことができ、利用者の識別や属性に関する情報や、最後にサイトを訪れた日時などを記録しておくことが多い。ネットサービスなどのサイトで利用者のIDなどが保存されると、次にアクセスしたときに自動的に利用者の識別が行われ、前回の続きのようにサービスを受けることができる。 1つのCookieには4096バイトのデータを記録でき、1台のサーバが同じコンピュータに対して発行できるCookieの数は20個に制限されている。Cookieの総数は300個までで、これを超えると古い方から削除される。また、個々のCookieには有効期限が設定されており、期限を過ぎたものは破棄される。 参考:https://bit.ly/2PFNWaJ (短縮urlです)Sessionsコントローラー
ログインとログアウトの要素を、Sessionsコントローラーの特定のRESTアクションにそれぞれ対応させます。
RESRアクションについてはこちらをご覧ください。
まずはコントローラーの作成ですがrails generateでnewアクションを生成するとそれに対応するビューも生成されます。
createやdestoryには対応するビューがないのでnewだけを指定します。
SessionリソースはUserリソースとは違い、専用のresourcesメソッドを使ってRESTfulなルーティングをフルセットで利用する必要がないため、「名前付きルーティング」だけを使います。
名前付きルーティングでは、GETリクエストやPOSTリクエストをloginルーティングで、DELETEリクエストをlogoutルーティングで扱います。
| HTTPリクエスト | URL | 名前付きルート | アクション名 | 用途 |
|---|---|---|---|---|
| GET | /login | login_path | new | 新しいセッションのページ(ログイン) |
| POST | /login | login_path | create | 新しいセッションの作成(ログイン) |
| DELETE | /logout | logout_path | destory | セッションの削除(ログアウト) |
つまりユーザーがログインしたりするたびにセッションを実行しています。
ユーザーの検索と認証
ユーザー登録では最初にユーザーを作成しましたが、ログインでセッションを作成する場合に最初に行うのは、入力が無効な場合の処理です。
最初に最小限のcreateアクションをSessionsコントローラで定義し、空のnewアクションとdestroyアクションも作成します。
paramsハッシュではsessionキーの下にメールアドレスとパスワードがあります。
ユーザー登録の場合と同様でこれらのパラメーターは**ネストしたハッシュ(入れ子になった)**になっています。
ネストしたハッシュとはハッシュの中にハッシュがあることです
celebrity = { sports: { soccer: "Osako", basketball: "Htimura" } }
paramsの場合次のような入れ子ハッシュになっています。
params = { session: { password: "foobar", email: "user@example.com" } }
つまり以下のようになります
params = { session: { password: "foobar", email: "user@example.com" } }
puts params[:session]
# { password: "foobar", email: "user@example.com" }
puts params[:session][:email]
# "user@example.com"
puts params[:session][:password]
# "foobar"
このようになっていてparamsハッシュを使うことでフォームから送信された情報にアクセスできます。
要するにcreateアクションの中では、ユーザーの認証に必要なあらゆる情報をparamsハッシュから簡単に取り出せるということです。
これでユーザーをデータベースから探して認証できます。
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by(email: params[:session][:email].downcase)
if user && user.authenticate(params[:session][:password])
# ユーザーログイン後にユーザー情報のページにリダイレクトする
else
# エラーメッセージを作成する
render 'new'
end
end
def destroy
end
end
&&(論理積(and))は取得したユーザーが有効かどうか決定するために使います。
Rubyではnilとfalse以外のすべてのオブジェクトは真偽値ではtrueになるという性質があり、それを考慮して組み合わせを考えると以下の表のようになります
| User | Password | a && b |
|---|---|---|
| 存在しない | 何でも良い | (nil && [オブジェクト]) == false |
| 有効なユーザー | 誤ったパスワード | (true && false) == false |
| 有効なユーザー | 正しいパスワード | (true && true) == true |
ちなみに論理積(and)はどちらも0のときは0、またはどちらも1のときは1を出力し、それ以外はすべて0を出力します。
| Inpu 1 | Input 2 | Output |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 0 | 0 |
| 1 | 1 | 1 |
つまり「ユーザーが存在している(trueなどで1)」「正しいパスワード(trueなので1)」で結果はtrue(1)になります。
前半のまとめ
- Railsの
sessionメソッドを使うと、あるページから別のページに移動するときの状態を保持できる。一時的な状態の保存にはcookiesも使える - ログインフォームでは、ユーザーがログインするための新しいセッションが作成できる
さいごに
最後まで読んでいただきありがとうございました!
この記事が少しでもRailsチュートリアルを進めるのに役に立てたら嬉しいです。
後半は明日の朝に投稿します。
参考文献