SorceryでRailsアプリケーションに認証機能を実装する

deviseを使って認証機能を実装することが多かったのですが、最近はSorceryが流行ってるよということで、Sorceryを使ってみました。

まずgemをGemfileに追記します。

gem 'sorcery'

そして、bundle installします。

続いて、SorceryをRailsアプリにインストールします。

rails generate sorcery:install

すると、Userモデルに対してのマイグレーションファイルが生成されます。

  create_table "users", force: :cascade do |t|
    t.string   "email",null: false
    t.string   "crypted_password"
    t.string   "salt"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["email"], name: "index_users_on_email", unique: true
  end

Userモデルの定義が問題なければrails db:migrateします。

続いて、Userモデルのバリデーションを設定します。

class User < ApplicationRecord
  authenticates_with_sorcery! do |config|
    config.authentications_class = Authentication
  end

  validates :email, presence: true
  validates :email, uniqueness: true
  validates :password, presence: true
end

Userモデルを操作するUsersコントローラを作成します。

rails g controller users new create

Sorceryには色々な便利なヘルパーがありますが、require_loginはログインしているかどうかを判断してくれるヘルパーです。認証されていない場合、デフォルトでnot_authenticatedというメソッドを実行します。Usersコントローラを実装する前にApplicationControllerにbefore_actionで設定しておきます。

class ApplicationController < ActionController::Base
  before_action :require_login

  protect_from_forgery with: :exception

  protected

  def not_authenticated
    redirect_to "/login"
  end

end

Usersコントローラのnewとcreateを作成します。ストロングパラメータも忘れずに。ストロングパラメータのpermit内に登録するべき項目を記入し忘れているとUserデータを登録できないので気をつけてください。

skip_before_actionでrequire_loginはスキップして認証していなくても、会員登録画面が使えるようにしておきます。

class UsersController < GeneralController
    skip_before_action :require_login, only: [:index, :new, :create]

    def new
        @user = User.new
    end

    def create
        @user = User.new(user_params)
        if @user.save
            redirect_to root_path
        else
            render :new
        end
    end

    private

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

ログイン用のUserSessionsコントローラも実装します。こちらも、skip_before_actionでrequire_loginはスキップしておきます。

class UserSessionsController < GeneralController
    skip_before_action :require_login, except: [:destroy], raise: false

    def new
        @user = User.new
    end

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

    def destroy
        logout
        redirect_to "/login"
    end

    private

    def user_session_params
        params.permit(:email, :password)
    end
end

app/views/users/new.html.erbにユーザーサインアップ用のフォームを作成します。

<%= form_for @user do |f| %>

    <%= f.label :email, :メールアドレス %>
    <%= f.text_field :email  %>

    <%= f.label :password, :パスワード %>
    <%= f.password_field :password  %>  

    <%= f.label :password_confirmation, :パスワード確認 %>
    <%= f.password_field :password_confirmation  %>     
  
    <%= f.submit :登録 %>
  
<% end %>

app/views/user_sessions/new.html.erbにログイン用のフォームを作成します。本筋と関係ないですが、form_tagの各項目にclassを設定したい場合、valueを""のように空で設定しないといけないようで、ちょっと詰まりました。

<%= form_tag(user_sessions_path, method: :post) do %>
      
    
    <%= text_field_tag "email",""  %>

    
    <%= password_field_tag "password", "" %>
    
    <%= submit_tag "ログイン" %>
        
<% end %>

config/routes.rbにルーティングを設定します。下記のような感じになるかと思います。

Rails.application.routes.draw do  
  root to: "home#index"

  resources :users, only: [:new, :create]
  get "/login" => "user_sessions#new"
  post '/login' => 'user_sessions#create'
  post '/logout' => 'user_sessions#destroy'
end

これで実装完了です。

参考

Ruby on Railsをこれから本格的に勉強したい人は「エンジニアになるための600時間のプログラミング学習に耐え抜くコツ」という記事がおすすめです。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする