LoginSignup
19
14
記事投稿キャンペーン 「Rails強化月間」

Gem sorceryを使い倒す① 基本のログイン機能

Last updated at Posted at 2023-11-05

環境

ruby "3.2.2"
rails "7.0.7"
Docker

Gemのインストール

 
【Gemのインストール】

Gemfileに以下を記述し、ターミナルでbundle installします。

Dockerを使用している場合の注意点

Dockerを使用している場合はコンテナ内に入ってから記述します。コンテナの外にいる状態で記述した場合、コンテナに入れなくなる場合があります。その場合は一旦削除してコンテナに入り再び記述し直してください。

Gemfile
gem 'sorcery'
bundle install

*インストールもDocker内で行います。

 

ターミナルで次のコマンドを実行して、コア移行ファイル、初期化ファイル、および Userモデル クラスを生成します。

rails generate sorcery:install

 
以下のファイルが作成されます。

app/models/user.rb
config/initializers/sorcery.rb
db/migrate/202◯◯◯◯◯◯◯◯◯◯_sorcery_core.rb
spec/factories/users.rb
spec/models/user_spec.rb
 

【マイグレーションファイルの確認】

db/migrate/202◯◯◯◯◯◯◯◯◯◯_sorcery_core.rb
class SorceryCore < ActiveRecord::Migration[6.1]
  def change
    create_table :User do |t|
      t.string :email,            null: false, index: { unique: true }
      t.string :crypted_password
      t.string :salt

      t.timestamps                null: false
    end

    add_index :User, :email, unique: true
  end
end

sorceryの基本のUserテーブルが作成されています。

カラムはemailとpasswordです。crypted_saltはパスワードをハッシュ化するためのものです。
emailはnull: falseで入力必須、index: { unique: true }で同じアドレスが登録できないバリデーションがかけられています。

もしUserテーブルにnameカラムを作成したい場合はここで記述します。

      t.string :email,          null: false, index: { unique: true }
      t.string :crypted_password
      t.string :salt
      t.string "first_name",    null: false
      t.string "last_name",     null: false

確認後、ターミナルでdb:migrateします。

rails db:migrate

 

sorcery基本のログイン編

 
【Userモデルを作成】

models/user.rb
class User < ApplicationRecord
  authenticates_with_sorcery!
  
end

authenticates_with_sorcery! は、Userモデルにsorceryによる認証機能を持たせています。
この下にバリデーションを記述していきましょう。

  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, presence: true, uniqueness: true
  validates :reset_password_token, presence: true, uniqueness: true, allow_nil: true

 
【コントローラーを作成】

rails g controller user_sessions

以下のファイルが作成されます。

app/controllers/user_sessions_controller.rb
app/views/user_sessions
test/controllers/user_sessions_controller_test.rb
app/helpers/user_sessions_helper.rb

 
controllerの中身を作成しましょう。こちらが超基本のかたちです。
公式参考ページ

controllers/user_sessions_controller.rb
class UserSessionsController < ApplicationController
 def new; end
 
 def create
   @user = login(params[:email], params[:password])
   if @user
     redirect_back_or_to root_path
   else
     render :new
   end
 end
 
 def destroy
   logout
   redirect_to root_path
 end
end
sorceryで提供されるメソッド
名前 説明
login (params[:email], params[:password])でformに入力されたemailとpasswordの値を受け取ります。 emailによるUser検索、パスワードの検証を行い、正常に処理できるとセッションデータにUserレコードのid値を格納する、という処理が行われています。
logout loginセッションをリセットします。
redirect_back_or_to 未ログイン時アクセス不可のページを開こうとした際、require_loginメソッドでユーザをログインページに誘導し、ログインが成功したら、最初に訪れようとしていたページにリダイレクトさせるということが可能になります。

 

【ルーティングの編集】

get 'login', to: 'user_sessions#new'
post 'login', to: 'user_sessions#create'
delete 'logout', to: 'user_sessions#destroy'

これでlogin_path、logout_pathが使えるようになります。
生成されたpathを確認してみましょう。
http://localhost:3000/rails/info/routes
 

 
【ビューの作成】

ログインフォーム

<%= form_with url: login_path do |f| %>
  <%= f.label :email %>
  <%= f.email_field :email %>
  
  <%= f.label :password %>
  <%= f.password_field :password %>
  
  <%= f.submit "ログイン" %>
<% end %>

 fieldに入力された値をuser_sessions_controllerのcreateで受け取ります。
 
 

sorceryの便利なメソッド

 
【logged_in?】
ログインしているかの有無で表示を変えたり処理を変えたりすることができます。
例えば、ログインしていなければログインリンクのついたヘッダーを、ログインしていればメニューが表示されるヘッダーを等切り替えることができます。

<body>
    <% if logged_in? %> # ログインしていたら
      <%= render 'shared/header' %> # こっちを表示
    <% else %> # してなかったら
      <%= render 'shared/before_login_header' %> # こっちを表示
    <% end %>
    
    <%= render partial:"shared/flash_message" %>
    <%= yield %>
    <%= render 'shared/footer' %>
  </body>

 

【require_login】
未ログイン状態で表示させられるページを制限できます。

controllers_application_controller.rb
class ApplicationController < ActionController::Base
  before_action :require_login
end

application_controllerでbefore_action :require_loginを記述するとすべてのコントローラーに対して適応されます。つまりこの状態だと、すべての画面がログインしていないとアクセスできなくなります。

controller/user_session_controller.rb
class UserSessionsController < ApplicationController
  skip_before_action :require_login, only: [:new, :create]
end

ログインを必要としないページのアクションをskip指定し、require_loginを回避します。
一般的にHome、Top画面に指定したページと、ユーザー登録、ログイン画面等、ログイン前に訪れるページはrequire_loginを回避します。

 
 
【not_authenticated】
ログインしていない場合に呼ばれるメソッドです。
『ログインしていなかったらフラッシュメッセージを表示する』『ログインしていなかったらこのページにリダイレクトをする』などの処理を記述します。

controllers/application_controller.rb

private

def not_authenticated
  redirect_to login_path
  flash[:danger] = 'ログインしてください'
end

 

参考サイト

関連記事

19
14
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
19
14