-
注意:プログラミング歴34日の初心者が書いています
-
注意:間違っていたら優しく教えてください(喜びます)
「Ruby on Rails チュートリアル実例を使ってRailsを学ぼう」
https://railstutorial.jp/
素晴らしいチュートリアルに感謝します。
#8.1 セッション
HTTPは、その場限り。以前の情報を全く持たないリクエストです。
そのため、ログイン情報の保持には、セッションという接続を使います。
Railsでセッションを実装する方法として最も一般的なのは、cookiesを使う方法です。cookiesとは、ユーザーのブラウザに保存される小さなテキストデータです。
セッションについても例に漏れず、Sessionsコントローラで操作します。
コントローラを追加したら、routes.rb
に対応するルーティングを追加します。今回は、
-
new 新しいセッションのページ (ログイン画面)
-
create 新しいセッションの作成 (実際のログイン)
-
destroy セッションの削除 (ログアウト)
という3つのアクションを、/login
というURLに紐づけます。
#8.1.2 ログインフォーム
フォームに入力されたログイン情報を保存したい、でもセッションにはUserのときのようなモデル、データベースはありません。
form_for(:session, url: login_path)
そのため上記のように、データを保存するリソース名(ここでは:session
)とそのパスを指定ながら、form_for
でformタグを生成します。
rb
<%= form_for(:session, url: login_path) do |f| %>
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
<%= f.submit "Log in", class: "btn btn-primary" %>
<% end %>
送信されたデータは、
-
params[:session][:email]
-
params[:session][:password]
で受け取ることができます。こうしてみると、リソース名(ここでは:session
)をシンボルで記述する意味がわかりますね。
"session" => {
"email" => "foo@bar.com",
"password" => "something",
}
送信されるデータはこういうハッシュになってるということですね。
これが、login_path
のPOST、つまりcreate
アクションに受け渡されるということです。
#8.1.3 ユーザーの検索と認証
session
コントローラのcreate
アクションでparamsからデータを受け取ることができます。
##render
とredirect_to
について
flash
で表示させるエラーメッセージは、redirect_to
の場合は次のページ移動で消えるのに、rederではページ移動しても消えずに残ったままになってしまう。
renderを使用する場合はflash.now
を使う。
###renderとは
-
render
は指定したviewを呼び出します。
def new
end
これも実はrender
が動いています。
GETアクション内になにも記述がない場合は、
def new
render 'new'
end
に勝手に補完されています。
###redirect_toとは
-
redirect_to
はHTTPリクエスト(GET)をサーバーに送ります。
def create
@user = User.new(user_params)
if @user.save
flash[:success] = "Welcome to the Sample App!"
redirect_to @user
else
render 'new'
end
end
わかりにくいですが、ここでもRailsの自動補完が効いているのでした。
redirect_to
の行は、以下と同じ意味です。
redirect_to user_url(@user)
#8.1.5 フラッシュのテスト
require 'test_helper'
class UsersLoginTest < ActionDispatch::IntegrationTest
test "login with invalid information" do
get login_path #1
assert_template 'sessions/new' #2
post login_path, params: { session: { email: "", password: "" } } #3
assert_template 'sessions/new' #4
assert_not flash.empty? #4 flashはemptyでない
get root_path #5
assert flash.empty? #6 flashはemptyである
end
end
- ログイン用のパスを開く
- 新しいセッションのフォームが正しく表示されたことを確認する
- わざと無効なparamsハッシュを使ってセッション用パスにPOSTする
- 新しいセッションのフォームが再度表示され、フラッシュメッセージが追加されることを確認する
- 別のページ (Homeページなど) にいったん移動する
- 移動先のページでフラッシュメッセージが表示されていないことを確認する
#8.2 ログイン
##ApplicationコントローラにSessionヘルパーモジュールを読み込む
ApplicationコントローラにSessionヘルパーモジュールを読み込むと、他の全てのコントローラで使用できるようになります。
それは、他の全てのコントローラが、Applicationコントローラを継承しているからです。
#8.2.1 log_inメソッド
##sessionメソッドについて
session[:name]
sessionメソッドはRailsにあらかじめ組み込まれているメソッドです。
名前をつけて、セッションに登録できます。
これは、8章冒頭に自分でrails -g
して作ったSessionsコントローラとは無関係です。
module SessionsHelper
# 渡されたユーザーでログインする
def log_in(user)
session[:user_id] = user.id #user.idを`:user_id`という名前で保存
end
end
どのviewでも使うことができるように、ヘルパーに関数を定義します。
sessionメソッドで作成した一時cookiesは自動的に暗号化されます。すごい。
##ブラウザからcookiesの情報を調べてみてください。の演習について
AWS Cloud9を使っている人は、amazonaws
でcookies検索すると出るかと思います。
#8.2.2 現在のユーザー
##「例外を発生させる」or「例外を発生させない」
User.find(session[:user_id]) #例外が発生する
User.find_by(id: session[:user_id]) ##例外が発生しない(nillを返す)
-
find
メソッドは例外を発生させて処理を中断する。 -
find_by
メソッドはnilを返すため処理は中断されない。
「ユーザページの表示」の場合は、ユーザーのidが無いのは「例外」です。(表示するページもなにもない)
一方、「ユーザーのログイン」の場合、まだログインしていないなど、クッキーにデータがあったりなかったり、両方の状態が考えられます。そのため、「例外」での処理はしません。
##現在のユーザーを定義する
def current_user
if session[:user_id]
@current_user ||= User.find_by(id: session[:user_id])
end
end
「もし、session[:user_id]
が存在するなら、
@current_user
がnill
ならUser.find_by(id: session[:user_id])
を代入する」
@current_user ||= User.find_by(id: session[:user_id])
上記は、以下と同じです。
if @current_user.nil?
@current_user = User.find_by(id: session[:user_id])
else
@current_user
end
まず、@current_user
がnil
かどうか(値があるかどうか)チェック。
@current_user
がnil
(つまりログインしてない)なら、セッションIDからuserを検索して@current_user
とします。
もし@current_user
がnil
でないなら、すでにログイン中ですので、そのまま@current_user
を返します。
#8.2.3 レイアウトリンクを変更する
ログインしている場合orしていない場合で、レイアウトを変更します。
view内で、if
を使って表示する内容を変える。
if
の条件分岐を使用して、current_user
がtrueかfalseか(ログインしているか否か)で分岐させます。
ユーザーがログイン中の状態とは「sessionにユーザーidが存在している」こと、つまりcurrent_userがnilではないという状態を指します。
# ユーザーがログインしていればtrue、その他ならfalseを返す
def logged_in?
!current_user.nil?
end
ログインしているかどうかを確かめるメソッドをヘルパーに定義して、便利にすぐ呼び出せるようにしておきます。
true
やfalse
など真偽値を返すメソッドは名前に「?」をつけて置くのがルールです。
#リスト 8.21: fixture向けのdigestメソッドを追加する
全く意味がわかりません。誰かたすけてください。
#8.3 ログアウト
session.delete(:user_id)
上記のdelete
メソッドでセッションを削除できます。