【Ruby on Rails】gemのdeviseを使用し、名前とパスワードのみでログインする方法


目標

開発環境

ruby 2.5.7
Rails 5.2.4.3
OS: macOS Catalina

前提

※ ▶◯◯ を選択すると、説明等が出てきますので、
  よくわからない場合の参考にしていただければと思います。

homesコントローラーを作成し、以下を記述済。

config/routes.rb
root 'homes#top'
get 'mypage', to: 'homes#mypage'
app/controllers/homes_controller.rb
class HomesController < ApplicationController
 def top
 end
 def mypage
 end
end

1,deviseをインストールする

Gemfileの最後に、以下を追加。

Gemfile

gem 'devise'

保存後、ターミナルに移動し、下記を実行。

ターミナル
$ bundle install
ターミナル
$ rails g devise:install

解説
rails g devise:install は deviseの初期設定を行います。

以下のような表示がされればOKです。

ターミナル
===============================================================================

Depending on your application's configuration some manual setup may be required:

  1. Ensure you have defined default url options in your environments files. Here
     is an example of default_url_options appropriate for a development environment
     in config/environments/development.rb:

       config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

     In production, :host should be set to the actual host of your application.

     * Required for all applications. *

  2. Ensure you have defined root_url to *something* in your config/routes.rb.
     For example:

       root to: "home#index"

     * Not required for API-only Applications *

  3. Ensure you have flash messages in app/views/layouts/application.html.erb.
     For example:

       <p class="notice"><%= notice %></p>
       <p class="alert"><%= alert %></p>

     * Not required for API-only Applications *

  4. You can copy Devise views (for customization) to your app by running:

       rails g devise:views

     * Not required *

===============================================================================

エラー時
エラーが表示された場合は、Railsのアップデートによるエラーの可能性が高いため、
Gemfileのgem 'sqlite3'を見直してください。

2,ログイン画面を表示する

テーブルの作成(名前の追加)

通常時の記述とは異なり、
deviseの独自ルールである「rails g devise モデル名」と記述。
今回はUserモデルを作成するため、ターミナル上で下記を実行。

ターミナル
$ rails g devise User

下記フォルダにて、t.string :name を記述。

db/migrate/xxxxxxxxxxxxx_devise_create_users.rb
...

      t.string :name  # ←ここに追加
      t.timestamps null: false
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
    # add_index :users, :confirmation_token,   unique: true
    # add_index :users, :unlock_token,         unique: true
  end
end

補足1
null: falseを記述することで、空の状態での保存を防ぎます。
null: falseについてはこちら

補足2
名前以外でも登録情報を追加したい場合は、
t.string :nameと同じように記述することで可能。
ex) t.string :phone_number など

その後ターミナルに移動し、下記を実行。

ターミナル
$ rails db:migrate

以下のような表示がされればOKです。

ターミナル
== 20200901103907 DeviseCreateUsers: migrating ================================
-- create_table(:users)
   -> 0.0038s
-- add_index(:users, :email, {:unique=>true})
   -> 0.0013s
-- add_index(:users, :reset_password_token, {:unique=>true})
   -> 0.0013s
== 20200901103907 DeviseCreateUsers: migrated (0.0067s) =======================

viewの作成(名前の追加)

ターミナル
$ rails g devise:views users

解説
rails g devise:views usersとすることで、
app/views/usersの中にdeviseのviewsを格納可能。
viewsの編集も可能。

3行目にある<%= form_for %>の中に以下を記述。

app/views/devise/registrations/new.html.erb
...

  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name, autofocus: true, autocomplete: "name" %>
  </div>

...

下記のemailの3箇所をnameに, email_fieldをtext_field に変更

app/views/devise/sessions/new.html.erb
  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
  </div>

  ↓

  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name, autofocus: true, autocomplete: "name" %>
  </div>

49行目付近にある下記記述をコメントアウト外して[:email]を[:name]に変更

config/initializers/devise.rb

config.authentication_keys = [:name]

 ログイン前のview

app/views/homes/top.html.erb
<%= link_to '新規登録', new_user_registration_path %><br>
<%= link_to 'ログイン', new_user_session_path %>

 ログイン後のview

app/views/homes/mypage.html.erb
<%= current_user.name %><br>
<%= current_user.email %><br>
<%= link_to 'ログアウト', destroy_user_session_path, method: :delete %>

解説
current_userはdeviseのヘルパーメソッドであり、ログイン中のユーザー情報を取得可能。
ログアウト時はhttpメソッドでの被りはないものの、
method: :deleteを指定してあげると確実。

3,コントローラーの作成

ターミナル
$ rails g devise:controllers users

4行目,44〜46行目,54〜56行目をコメントアウトを外し、
45行目の:attributeを:name, :emailに変更。
55行目のsuper(resource)を飛ばしたいpathに変更。

app/controllers/users/registrations_controller.rb
# frozen_string_literal: true

class Users::RegistrationsController < Devise::RegistrationsController
  before_action :configure_sign_up_params, only: [:create]
  # before_action :configure_account_update_params, only: [:update]

...

  # protected

  # If you have extra params to permit, append them to the sanitizer.
  def configure_sign_up_params
    devise_parameter_sanitizer.permit(:sign_up, keys: [:name, :email])
  end

  # If you have extra params to permit, append them to the sanitizer.
  # def configure_account_update_params
  #   devise_parameter_sanitizer.permit(:account_update, keys: [:attribute])
  # end

  # The path used after sign up.
  def after_sign_up_path_for(resource)
    mypage_path
  end

  # The path used after sign up for inactive accounts.
  # def after_inactive_sign_up_path_for(resource)
  #   super(resource)
  # end
end

解説
44〜46行目で新規会員登録時のカラムの保存許可を指定。
55〜56行目で新規会員登録後の遷移先を指定。

補足会員情報更新後の遷移先も上記のようにすれば変更可能。記述は57行目以下でOK。
 def after_update_path_for(resource)
  mypage_path
 end

27行目以下に追加。

app/controllers/users/sessions_controller.rb
...

  def after_sign_in_path_for(resource)
    mypage_path
  end

  def after_sign_out_path_for(resource)
    root_path
  end
end

解説
ログイン時、ログアウト時の遷移先指定。

devise_for :users 以下に追加記述。

config/routes.rb
Rails.application.routes.draw do
  devise_for :users, controllers: {
    sessions: 'users/sessions',
    registrations: 'users/registrations',
  }
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html

  root 'homes#top'
  get 'mypage', to: 'homes#mypage'
end

P.S.

twitterではQiitaにはアップしていない技術や考え方もアップしていますので、
よければフォローして頂けると嬉しいです。
詳しくはこちら https://twitter.com/japwork