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時間のプログラミング学習に耐え抜くコツ」という記事がおすすめです。