学習記録

アウトプット用に作りました

sorceryを使ってログイン機能を実装する

sorceryとは

Railsに認証機能を実装するためのライブラリです。
認証機能とは、システムへのログインやユーザの有効性確認を行うための機能のことを言います。
同じように認証機能を提供してくれているものとしてdeviseなどがあります。

sorceryの使い方

まずgemfileに以下を追加して、$bundle installを行います。

gem 'sorcery', '0.14.0'


以下のコマンドでsorceryに必須のカラムやモデルを追加。

$ rails g sorcery:install
$ rails db:migrate

このコマンドで通常で言うところの、$ rails g model の時のようにmodelとかカラムを作ってくれます。
config/initializers/sorcery.rb
models/users.rb
db/migrate/00000_sorcery_core.rb
が生成されます。


scafford_controllerを使って、userコントローラとビューファイルを作ります。

$ rails generate scafford_controller user  email:string crypted_password:string salt:string

app/controller/users_controller.rb
app/views/users
が生成されます。ここで生成された要らないビューファイルを消去します。


Userモデルにlast_nameとfirst_nameのカラムを追加します。
ここで生成されたマイグレーションファイルに、null制約をつけます。null: false

$ rails generate migration AddNameToUsers last_name:string first_name:string
$ rails db:migrate


Userコントローラのuser_paramsのコードを書き換えます。
:crypted_passwordと:saltが書いてありますが、:password, :password_confirmationに書き換えます。
新規登録画面でformから送られてくる値をpermitに書きます。

def user_params
    params.require(:user).permit(:email, :password, :password_confirmation, :last_name, :first_name)
end

※ここでコントローラの不要なコードも削除して、スッキリさせました。

ビューファイルにもcrypted_passwordとsaltが書いてあるので、passwordとpassword_confirmationに書き換えます。


Userモデルのバリデーションを追加します。

class User < ApplicationRecord
  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, presence: true
  validates :last_name, presence: true, length: { maximum: 255 }
  validates :first_name, presence: true, length: { maximum: 255 }
end

ここで使われてるコードの難しいところを下記でまとめてみました。

sorceryが準備しているメソッド。
Userモデルで必要なクラスメソッドとインスタンスメソッドを得ることができます。

authenticates_with_sorcery!

登録したユーザーがパスワード以外のプロフィール項目を更新したいときに、
パスワードの入力を省略できるようになります。

 if: -> { new_record? || changes[:crypted_password] }


ログイン機能を作るために、新しいコントローラを作成します。

$ rails generate controller UserSessions new create destroy

生成されたSessionsコントローラを下記のように書きます。

class UserSessionsController < ApplicationController
  
  def new; end

  def create
    @user = login(params[:email], params[:password])
    if @user
      redirect_back_or_to root_path, notice: 'Login successful'
    else
      flash.now[:alert] = 'Login failed'
      render :new
    end
  end

  def destroy
    logout
    redirect_to root_path, notice: 'Logged out!'
  end
end

redirect_back_or_toメソッドはSorceryが提供しているメソッドです。
SorceryがURLを保存している場合は、
コードで指定したURLではなく保存されたURLにリダイレクトします。
これで便利なのは、あるページにアクセスしたユーザをまずログインさせたいという場合に、
Sorceryがそのユーザをログインページに誘導し、
ログインが成功したら最初に訪れようとしていたページに戻してくれる点です。
今回のコードでは、root_pathが指定したURLになります。


ユーザーの新規登録画面を作成します。

<%= form_with model: @user, local: true do |f| %>

ログイン画面を作成します。

<%= form_with url: login_path, local: true do |f| %>


ルーティングを変更します。

  get 'login', to: 'user_sessions#new', as: :login
  post 'login', to: 'user_sessions#create'
  delete 'logout', to: 'user_sessions#destroy', as: :logout
  resources :users, only: %i[new create]


sorceryで使えるようになるメソッド

  • require_login

  • logout

  • logged_in?

  • current_user

  • redirect_back_or_to

  • not_authenticated

などなど....