sorcery GemとCookie,セッション

[sorcery]Gemの導入手順

・Gemfileに以下を記載

[Gemfile]

gem "sorcery"


$ bundle install


$ rails g sorcery:install

※[rails g sorcery:install]を実行すると、以下のファイルが作成される。
・migrationファイル(db/migrate/〇〇〇〇_sorcery_core.rb)
・initializerファイル(config/initializers/sorcery.rb)
・Userモデル
※注意
create_tableの名称がUserになっているので、usersに訂正!!


$ rails db:migrate


下記のようにバリデーションを追加

class User < ActiveRecord::Base
  authenticates_with_sorcery!

  validates :password, length: { minimum: 3 }, if: -> { new_record? || changes[:crypted_password] }
  validates :password, confirmation: true, if: -> { new_record? || changes[:crypted_password] }
  validates :password_confirmation, presence: true, if: -> { new_record? || changes[:crypted_password] }

  validates :email, uniqueness: true
end

※if: -> { new_record? || changes[:crypted_password] }
上記の意味は、 登録したユーザーがパスワード以外のプロフィール項目を更新したい場合に、パスワードの入力を省略させることができます。
また、passwordとpassword_confirmationはcrypted_passwordカラムに対する仮想属性となっている。
「validatesの使い方」

validates :カラム名, :カラム名, :カラム名, ヘルパー

[Confirmationヘルパー]
2つのフォームで入力された内容が完全に一致するかを検証します。
メールアドレスのフォームとメールアドレスの確認フォームが全く同じであるか検証したいときなどに利用します。
一致しているか確認したいもう一つのカラム名は末尾に_confirmationをつけます。
こちらはフォームでのみ使うカラムなのでデータベースにこのカラムを作成する必要はありません。
メールアドレスを例にすると下記のようになります。

validates :email, confirmation: true
validates :email_confirmation

「sorceryで用意されているメソッド」

・[login]
認証処理が行われる。
以下のように使う

@user = login(params[:email], params[:password])

上記は、emailによるUser検索、パスワードの検証を行い、正常に処理できるとセッションデータにUserレコードのid値を格納する、という処理が行われている。
イメージは、下記と一緒

User = User,find_by(email: session_params[:email])
If user&.authenticate(session_params[:password])
session[:user_id] = user.id

・[logout]
ログアウトをする為のメソッド
以下のように使う

def destroy
  logout
  redirect_to root_path
end

・[require_login]
その名前の通りログインを強制します。
ログインが必須の画面、コントローラにおいてbefore_action :recuire_loginを書きます。
以下のように使う

class ApplicationController < ActionController::Base
  before_action :require_login
end

・[not_authenticated]
ログインしていなかった場合に呼ばれるメソッドが[not_authenticated]
ログインしていなかったら「フラッシュメッセージを表示する」、「ログインしていなかったらこのページにリダイレクトをする」のように使う。
以下のように使う

class ApplicationController < ActionController::Base
  before_action :require_login

  private

  def not_authenticated
    redirect_to login_url, info: (t 'defaults.please_login')
  end
end

・[logged_in?]
現在のユーザーがログインしているかを判別する。
以下のように使う

    <% if logged_in? %>
      <%= render 'shared/header' %>
    <% else %>
      <%= render 'shared/before_login_header' %>
    <% end %>

・[current_user]
cookieに保存されたユーザーidを元にユーザーの情報を取得するメソッド。
以下のように使う

@board = current_user.boards.new(board_params)

・[login_from_session]
user_class.sorcery_adapter.find_by_id(session[:user_id])とUser.find_byのような処理でユーザーのオブジェクトを取得している。)

※ポイント
フォームからログイン情報を受け取って[loginメソッド]を使ってログインする際は、以下のような形でparamsが送られてくる。
([loginメソッド]でフォーム欄から送られてくるparamsの形式が決まっているので、form_withでscopeなどを指定してログイン情報をグループかするとおかしくなる。)

# このようなparamsが送られてくる
params: {email: xxxxxxxx@xxx, password: xxxxxxxx, 以下略}

# こうではない
# params: {session: {email: xxxxxxxx@xxx, password: xxxxxxxx}, 以下略}

[redirect_back_or_to root_path]
上記の記述でフレンドリーフォワーディングを実装できる。
ログインが必要なページAにアクセスして時に、ログイン画面に移動しログイン後にページAを表示させるという機能。
分かりやすくいうと、require_loginのときにセッションに格納されたURLまたはデフォルトのURLにリダイレクトする。
あるページにアクセスしたユーザをまずログインさせたいという場合に、そのユーザをログインページに誘導し、ログインが成功したら最初に訪れようとしていたページに戻ること。
[redirect_back_or_to root_path]の場合は、ページAが存在しなければroot_pathに飛ぶようになっている。

Railscookieの設定」

Railsの場合、[config/initializer/session_store.rb]にて、セッション情報をどこに保存するのかが指定されています。
デフォルトでは、以下のようになっている。

Rails.application.config.session_store :cookie_store, key: '_○○_session'

これは、○○sessionというkeyで、cookieを用いてセッション情報を管理するといった意味。

参考記事

【Rails】 Railsのバリデーションの使い方をマスターしよう! | Pikawaka - ピカ1わかりやすいプログラミング用語サイト