Passion make things more better

Rails, Swiftあたりの話題を中心に書いています

sorceryを使ってEmail + Passwordログインを実装

先日、sorceryを使ってFacebookログインを実装する方法を紹介しましたが、今回はその関連で、Email + Passwordのログインを実装する方法を紹介します。

初期設定

# Gemfile
gem 'sorcery'

# bundle install
~ bundle install --path vendor/bundle

# sorceryの初期ファイルのインストール
~ bundle exec rails g sorcery:install

Migration

# db/migrate/xxxxxxxxxxx_sorcery_core.rb
class SorceryCore < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.string :email, null: false
      t.string :crypted_password
      t.string :salt

      t.timestamps
    end

    add_index :users, :email, unique: true
  end
end

Controller

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception

  before_action :require_login

  private
  def not_authenticated
    redirect_to sign_in_path, alert: 'ログインが必要です'
  end
end
# app/controllers/users_controller.rb
class UsersController < ApplicationController

  skip_before_action :require_login, only: [:new, :create]

  def dashboard
  end

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)
    if @user.save
      login(params[:user][:email], params[:user][:password])
      redirect_to dashboard_path, notice: 'ユーザー登録が完了しました'
    else
      render :new
    end
  end

  private
  def user_params
    params.require(:user).permit(:email, :password, :password_confirmation)
  end
end
# app/controllers/users/sessions_controller.rb
class Users::SessionsController < ApplicationController

  skip_before_action :require_login, only: [:new, :create]

  def new
    @user = User.new
  end

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

  def destroy
    logout
    redirect_to sign_out_path, notice: 'ログアウトしました'
  end

end
# app/controllers/pages_controller.rb
class PagesController < ApplicationController

  skip_before_action :require_login

  def home
  end

end

View

# app/views/users/new.html.erb
<%= form_for @user, url: { action: 'new' } do |f| %>

  <div class="form-group">
    <%= f.label :email %>
    <%= f.text_field :email, class: 'form-control' %>
  </div>

  <div class="form-group">
    <%= f.label :password %>
    <%= f.password_field :password, class: 'form-control' %>
  </div>

  <div class="form-group">
    <%= f.label :password_confirmation %>
    <%= f.password_field :password_confirmation, class: 'form-control' %>
  </div>

  <%= f.submit 'この内容でユーザー登録を行う', class: 'btn btn-primary' %>

<% end %>
# app/views/users/sessions/new.html.erb
<%= form_tag sign_in_path, method: :post do %>
<div class="form-group">
  <%= label_tag :email %>
  <%= text_field_tag :email, nil, class: 'form-control' %>
</div>
<div class="form-group">
  <%= label_tag :password %>
  <%= password_field_tag :password, nil, class: 'form-control' %>
</div>
<div class="actions">
  <%= submit_tag 'ログイン', class: 'btn btn-primary' %>
</div>
<% end %>
# app/views/users/dashboard.html.erb
<h1>dashboard</h1>
# app/views/pages/home.html.erb
<h1>home</h1>

Routing

Rails.application.routes.draw do
  root to: 'pages#home'
  get 'dashboard', to: 'users#dashboard', as: 'dashboard'

  # ユーザー登録関連
  get 'sign_up', to: 'users#new', as: 'sign_up'
  post 'sign_up', to: 'users#create'
  get 'sign_in', to: 'users/sessions#new', as: 'sign_in'
  post 'sign_in', to: 'users/sessions#create'
  post 'sign_out', to: 'users/sessions#destroy', as: 'sign_out'
end

参考