Ruby好き非エンジニアのブログ

〜Ruby on Railsの学習記録〜

sorceryによるログイン画面実装

今日はログイン画面。
 

ログイン機能の実装でまず名前があがるのがdeviseでしょうか。

単純な登録やログイン画面の作成ならdeviseはとても便利!

ただ、カスタマイズをしようとすると途端にハードルがあがる。。

 

もっと柔軟に作れるgemがいい!ということで、

今回はsorceryを使うことにしました。

GitHub - NoamB/sorcery: Magical authentication for Rails 3 & 4

 

またまた流れをメモしていきます。

 

まずはgemfileにsorceryを追加。

gem 'sorcery'

を記述した後、

$ bundle install

 

とりあえず必要な機能を実装するため下記コマンドを実行

$ rails generate sorcery:install core remember_me reset_password

・remember_me:ログイン状態の維持

・reset_password:パスワードを忘れた際の再設定

 

出来上がったdb/migrate/2016******_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

次はconfig/initializers/sorcery.rbのファイル設定の変更

Rails.application.config.sorcery.submodules = [:core, :remember_me, :reset_password]

 

Rails.application.config.sorcery.configure do |config|

  config.user_config do |user|

    user.username_attribute_names = [:email]

    user.reset_password_mailer = UserMailer

  end

 

  config.user_class = "User"

end

 

一応、reset_password用にメーラーを設定

$ rails g mailer UserMailer reset_password_email

 

UsersControllerは作成済みなので、ログイン処理のためのSessionsControllerを作成

$ rails g controller sessions new


/app/views/sessions/new.html.erbにログイン用のフォームも作成

<h1>Log in</h1>

    <%= form_tag sessions_path do %>
      <div class="field">
        <%= label_tag :email %>
        <%= text_field_tag :email, params[:email] %>
      </div>
      <div class="field">
        <%= label_tag :password %>
        <%= password_field_tag :password %>
      </div>
      <div class="field">
        <%= check_box_tag :remember_me, 1, params[:remember_me] %>
        <%= label_tag :remember_me %>
      </div>
      <div class="actions"><%= submit_tag "Log in" %></div>
    <% end %>

app/controllers/sessions_controller.rbに
ログイン・ログアウトの処理を記述。

class SessionsController < ApplicationController
  def new
  end

  def create
    user = login(params[:email], params[:password], params[:remember_me])
    if user
      redirect_back_or_to root_url, :notice => "Logged in!"
    else
      flash.now.alert = "Email or password was invalid."
    end
  end

  def destroy
    logout
    redirect_to root_url, :notice => "Logged out!"
  end
end

routesは、下記のように変更・追加

get 'login', to: 'sessions#new'
get 'logout', to: 'sessions#destroy'

 

resources :sessions


と、ここで久々にサーバーを起動させるとエラー発生。

Migrations are pending. To resolve this issue, run: bin/rails db:migrate RAILS_ENV=development

おお!しまった。

migration未実行によるエラー。

すかさず

$rake db:migrate

を実行。

しかしまだエラーは残ったまま。

エラーの中身をよく見てみると、

table "users" already exists

とのこと。

 

新規登録画面作成時に作ったusersテーブルとsorceryで作成したテーブルがかぶってました。

ということで、

$rails dbconsole

でdbコンソール開いて、該当するテーブルを削除

sqlite> drop table users:

これで無事解決!

あとは、 

$ rails g model user --skip-migration

でモデル・テーブルの作り直しをして、

app/models/user.rbに

authenticates_with_sorcery!

とその他validationを追加して、

 

$rails generate migration AddNicknameToUsers nickname:string

で再度nicknameカラム追加。

これでまずは新規登録が元通り実装でき、
f:id:Jyoko:20160813234210g:plain

 

ログインフォームからの
f:id:Jyoko:20160813234330g:plain


ログインも無事完了!
f:id:Jyoko:20160813234411g:plain



 

途中エラーがたくさんでましたが何とか無事実装完了。(もっと良い方法がある気がしますが…)

sorceryの認証機能は、必要に応じて随時追加していきます。

 

あとは見た目が悪いので、レイアウトやルートを直してから次に進みます。

 

参考:

#283 Authentication with Sorcery - RailsCasts

Railsでテーブルを削除したい時の対処法 - Qiita