LoginSignup
44
49

More than 5 years have passed since last update.

Railsの認証管理gem sorcery導入メモ(slim)

Last updated at Posted at 2015-10-29

Railsの認証機能実装gemといえばdeviseが有名だと思う。deviseを使うと実装そのものはとても簡単に実現できるのだが、内部構造が複雑なため、漫然と使うのは少し不安。そこで、別の認証gemであるsorceryを使用してみた。

基本的には公式のtutorial通りだけど所々違います。

環境
ruby 2.0
rails 4.2
テンプレートエンジン slim

準備

まずは以下のgemを追加してbundle installする。

gemfile
gem 'sorcery'

必要な機能をインストールするために、以下のコマンドを実行。

rails g sorcery:install
rake db:migrate

これで登録ユーザーを保存するためのUserモデルが作成される。ちなみに"User"というモデル名はオプションで変更することもできる。

ユーザー登録機能の実装

Userモデルのコントローラーとビューを作成する。今回はジェネレーターを使うので、以下のコマンドを実行。

rails g scaffold user email:string crypted_password:string salt:string --migration false

"users_controller.rb"の以下の部位を編集

app/controllers/users_controller.rb
def user_params
      params.require(:user).permit(:email, :password, :password_confirmation)
end

user_paramsメソッドはcreate、updateアクションから呼ばれる。フォームに入力した内容をstrong Parameterに関する処理を行った上で、上記のメソッドに渡す。

次にビューの設定を行う。メールアドレスとパスワードを入力するフォームと登録ボタンを配置する。

views/users/_form.slim
=form_for(@user) do |f|
  -if @user.errors.any?
    div#error_explanation
      h2 =pluralize(@user.errors.count, "error") + 'prohibited this user from being saved:'
      ul
      -@user.errors.full_messages.each do |message|
        li =message
  div.field
    =f.label :email
    br
    =f.text_field :email
  div.field
    =f.label :password
    br
    =f.text_field :password
  div.field
    =f.label :password_confirmation
    br
    =f.text_field :password_confirmation
  div.actions
    =f.submit

これで取りあえずユーザー登録は出来るようになるはず。しかし、このままだと、ユーザー一覧画面(index.slim)や詳細画面(show.slim)に暗号化されたパスワードが表示されてしまうので、これらのビューに少しだけ手を加える。

view/users/index.slim
h1 Listing Users

table
  thead
    tr
      th Email
      th colspan="3"
  tbody
    -@users.each do |user|
      tr
        td =user.email
        td =link_to 'Show', user
        td =link_to 'Edit', edit_user_path(user)
        td =link_to 'Destroy', user, method: :delete, data: { confirm: 'Are you sure?' }
br

= link_to 'New User', new_user_path

view/users/show.slim
p
  strong Email:
  =@user.email


=link_to 'Edit', edit_user_path(@user)
span |
=link_to 'Back', users_path

最後に、モデルにバリデーションを行う

models/user.rb
class User < ActiveRecord::Base
  authenticates_with_sorcery!

  validates :password, length: { minimum: 3 }, if: -> { new_record? || changes["password"] }
  validates :password, confirmation: true, if: -> { new_record? || changes["password"] }
  validates :password_confirmation, presence: true, if: -> { new_record? || changes["password"] }

  validates :email, uniqueness: true
end

これでユーザー登録、メールアドレスの変更、パスワードの変更、ユーザーの削除が行えるようになった。

ログイン、ログアウト機能の実装

次に登録したユーザーのログイン、ログアウト状態を管理するためのコントローラーを作成する。以下のコマンドを実行。

rails g controller UserSessions new create destroy

生成されたコントローラーを以下のように編集。

app/controllers/user_sessions_controller.rb
class UserSessionsController < ApplicationController

  def new
    @user = User.new
  end

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

  def destroy
    logout
    redirect_to :users, notice: 'Logged out!'
  end
end

createアクション中の"login"とdestroyアクションの"logout"はsorceryによって提供される主要メソッド。

コントローラーに対応するビューを作成。

app/views/user_sessions/new.slim
h1 Login

==render 'form'

=link_to 'Back', users_path
app/views/user_sessions/_form.slim
=form_tag user_sessions_path, method: :post do

    div.field
        =label_tag :email
        =text_field_tag :email
    div.field
        =label_tag :password
        =password_field_tag :password
    div.field
        =submit_tag 'Login'

ルーティングの設定

config/routes.rb
root  'users#index'
resources :user_sessions
resources :users

get 'login' => 'user_sessions#new', :as => :login
post 'logout' => 'user_sessions#destroy', :as => :logout

ログイン及びログアウトボタンや通知を表示するための領域を作成。今回はヘッダー領域の部分テンプレートとして作成する。

app/views/layout/application.slim
html
    head
      title Marktodo
      =stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true
      = javascript_include_tag 'application', 'data-turbolinks-track' => true
      = csrf_meta_tags
    body
        ==render 'shared/header'
        ==yield
app/views/shared/_header.slim
div#nav
-if current_user
  =link_to "Edit Profile", edit_user_path(current_user.id)
  span |
  =link_to "Logout", :logout, method: :post
-else
  =link_to "Register", new_user_path
  span |
  = link_to "Login", :login
div
  p#notice =flash[:notice]
  p#alert =flash[:alert]

最後に、アクセス制限を実現するために"application_controller.rb"に以下を追加

app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
    before_filter :require_login
    中略~

これだけだと非ログインユーザーは全てのページにアクセスできなくなるので、トップ画面(index)や登録、ログインに関わるアクションにはアクセスできるようにする。

app/controllers/users_controller.rb
class UsersController < ApplicationController
  skip_before_action :require_login, only: [:index, :new, :create]
    中略~
app/controllers/users_sessions_controller.rb
class UserSessionsController < ApplicationController
    skip_before_action :require_login, except: [:destroy]
    中略~

これで登録・認証に必要な一通りの処理が行えるようになる。

44
49
1

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
44
49