sorceryを使ったユーザー機能の作成(登録機能編)
・そもそもsorceryとは?
ユーザ認証機能を簡単に実装できるライブラリ、MITライセンスのオープンソースソフトウェアとして公開されている
パスワード認証機能の他にも、
・Remember Me
・Reset Password etc...
などの色々な機能が揃っていて選んで使うことができる。
・sorceryの導入
Gemfileにsorceryを追加して、bundle install
gem 'sorcery'
Soceryが提供するジェネレータ bundle exec rails g sorcery:install
を実行すると、Userモデル、データベースのmigrationを生成される。
この時生成されるファイルは以下の通り、
app/models/user.rb
config/initializers/sorcery.rb
db/migrate/yyyymmddhhmmss_sorcery_core.rb
bundle exec rails db:migrate
でデータベースにusersテーブルを作成
app/models/user.rbに
# app/models/user.rb class User < ActiveRecord::Base 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 end
とバリデーションを記述、ここでauthenticates_with_sorcery!
でUserモデルに認証にはSorceryを使用することを伝えている
if: -> { new_record? || changes[:crypted_password] }は登録したユーザーがパスワード以外のプロフィール項目(属性)を更新したいとき、パスワードの入力を省略するということ
validates :password, confirmation: trueで、passwordというDBに存在しない仮想的な属性(virtual attributes)が追加される。
これに加え今回はUserモデルにlast_name、first_nameカラムを追加して、必須項目であることのバリデーションを追加するのでnull false制約を付与する、既存のdb/migrate/yyyymmddhhmmss_sorcery_core.rbに
class SorceryCore < ActiveRecord::Migration[5.2] def change create_table :users do |t| t.string :email, null: false t.string :crypted_password t.string :salt t.string :last_name, null: false t.string :first_name, null :false t.timestamps null: false end add_index :users, :email, unique: true end end
と記述、bundle exec rails db:migrate
によってカラムの追加が完了
次に bundle exec rails g controller users new create
を実行してapp/controllers/users_controller.rbを作成
コードは以下のように記述
class UsersController < ApplicationController skip_before_action :require_login, only: %i[new create] def new @user = User.new end def create @user = User.new(user_params) if @user.save redirect_to login_path else render 'new' end end private def user_params params.require(:user).permit(:last_name, :first_name, :email, :password, :password_confirmation) end end
この時、skip_before_actionメソッドのonlyオプションに指定するアクションを%iの配列で記述
ルーティングはroutes.rbにresousesを使って実装
resources :users, only: %i[new create]
そしてユーザー登録に必要なフォームのテンプレートをに記述
#app/views/users/new.html.erb <div class="container"> <div class="row"> <div class="col-md-10 offset-md-1 col-lg-8 offset-lg-2"> <h1>ユーザー登録</h1> <%= form_with(model:@user,local: true,) do |form| %> <div class="form-group"> <%= form.label :last_name %> <%= form.text_field :last_name,class: "form-control" %> </div> <div class="form-group"> <%= form.label :first_name %> <%= form.text_field :first_name,class: "form-control" %> </div> <div class="form-group"> <%= form.label :email %> <%= form.text_field :email,class: "form-control" %> </div> <div class="form-group"> <%= form.label :password %> <%= form.password_field :password,class: "form-control" %> </div> <div class="form-group"> <%= form.label :password_confirmation %> <%= form.password_field :password_confirmation,class: "form-control" %> </div> <%= form.submit "登録", class: "btn btn-primary" %> <% end %> <div class='text-center'> <%= link_to 'ログインページへ',login_path %> </div> </div> </div> </div>
resources :usersとすることでform_withの引数にUserモデルのインスタンスを渡すだけで、railsがモデル名やemailなどの必要なものを取り出して処理してくれている。classオプションでclassを指定できる。
最後に今回フォーム情報の姓名が最大255文字emailが未入力で新規登録ができないようにするバリデーションの追加
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, presence: true, uniqueness: true validates :last_name, presence: true, length: { maximum: 255 } validates :first_name, presence: true, length: { maximum: 255 } end
これでSorceryを使った登録機能の完成!!
参考文献
Simple Password Authentication · Sorcery/sorcery Wiki · GitHub