14
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Rails】Sorceryでログイン機能を実装する

Last updated at Posted at 2020-03-10

Sourceryでログイン機能を実装してみました。
Deviseよりカスタマイズしやすそうで、自分で実装するより手軽なので結構好印象です。
フレンドリーフォワーディングが簡単に実装できるのが良いですね。

(3月12日追記)4年以上更新されていないので、system specが使えません。

##セットアップ

Gemfile
gem 'sorcery'
terminal
$ bundle install
$ rails g sorcery:install

Userモデルとマイグレーションファイル、設定ファイルなどもろもろ生成されます。

terminal
$ rails db:migrate

モデルにバリデーションを設定

model/user.rb
class User < ApplicationRecord
  authenticates_with_sorcery!
  validates :email, uniqueness: true, presence: true
  validates :password, presence: true
end

application_controller.rbにbefore_actionとメソッドを定義

application_controller.rb
class ApplicationController < ActionController::Base
  before_action :require_login #sorceryが作成するメソッド。ログインしてない時not_authenticatedメソッドを発火する

  protected

  def not_authenticated
    redirect_to login_url
  end
end

##新規ユーザー登録

users_controller.rb
class UsersController < ApplicationController
  skip_before_action :require_login, only: [:new, :create]

  def new
    @user = User.new
  end

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

  private

  def user_params
    params.require(:user).permit(:email, :password)
  end
end
new.html.erb
<%= form_with model: @user, local: true 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 %>
route.rb
resources :users, only: %i[index create]

##ログイン
login:見つかったユーザーでログインする
logout:ログアウトする
redirect_back_or_to:保存されたURLがある場合そのURLに、ない場合は指定されたURLにリダイレクトする。(フレンドリーフォワーディング)

sessions_controller.rb
class UsersController < ApplicationController
  skip_before_action :require_login, only: [:new, :create]

  def index
    @user = User.new
  end

  def create
    if @user = login(params[:email], params[:password])
      redirect_back_or_to(hoge_url, notice: 'ログインしました')
    else
      flash[:alert] = 'ログイン失敗'
      render :new
    end
  end

  def destory
    logout
    redirect_to(root_url, notice: 'ログアウトしました')
  end
end
new.html.erb
<%= form_with url: sessions_path, local: true do |f| %>
  <%= f.label :email, 'メールアドレス' %>
  <%= f.text_field :email  %>

  <%= f.label :password, 'パスワード' %>
  <%= f.password_field :password  %>  
    
  <%= f.submit "ログイン" %>        
<% end %>
routes.rb
get '/login' => 'sessions#new'
post '/login' => 'sessions#create'
post '/logout' => 'sessions#destroy'

##公式よりメソッドを抜粋

require_login # This is a before action
login(email, password, remember_me = false)
auto_login(user) # Login without credentials
logout
logged_in? # Available in views
current_user # Available in views
redirect_back_or_to # Use when a user tries to access a page while logged out, is asked to login, and we want to return him back to the page he originally wanted
@user.external? # Users who signed up using Facebook, Twitter, etc.
@user.active_for_authentication? # Add this method to define behaviour that will prevent selected users from signing in
@user.valid_password?('secret') # Compares 'secret' with the actual user's password, returns true if they match
User.authenticates_with_sorcery!

Sorcery/sorcery

##テスト
4年以上更新されていないgemなので、system specには対応していないようです。(3月12日時点)
###フィーチャースペック

spec/support/authentication.rb
#sessions_urlの部分をログイン画面のURLに合わせる
#password = 'login'の部分は適当な文字列に変えてもなぜか動く
module AuthenticationForFeatureRequest
  def login user, password = 'login'
    user.update_attributes password: password
    page.driver.post sessions_url, {email: user.email, password: password}
    visit root_url
  end
end
spec/support/authentication.rb
RSpec.configure do |config|
  # ...
  config.include AuthenticationForFeatureRequest, type: :feature
  # ...
end
spec/factories/users.rb
FactoryBot.define do
  factory :user do
    email { 'test1@test.com' }
    password { 'hogehoge' }
    salt { 'salt' }
    crypted_password { Sorcery::CryptoProviders::BCrypt.encrypt('hogehoge', 'salt') }
  end
end
spec/features/hoge_spec.rb
RSpec.feature "hoge", type: :feature do
  let(:user) { create(:user) }
  it 'ユーザー情報編集' do
    login(user)
    click_link 'マイページ'
    #...
  end
end

##参考

14
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?