はじめに
deviseを使い始めたときにハマった部分があったので,記事に残しておきます。
※この記事は,deviseが導入済みであることが前提です。
導入方法については,前回の記事[【Rails】deviseの導入方法] (url)にまとめていますので参考にしてみてください。
【環境】
- macOS Catalina 10.15.7
- Vagrant 2.2.4 (CentOS 7.1)
- Ruby 2.5.7
- Rails 5.2.4.4
- devise 4.7.3
手順
全体の流れは以下のようになっています。
1. nameカラムを追加する
2. devise.rbの設定を変更する
3. コントローラーを編集する
4. Viewを編集する
1. nameカラムを追加する
マイグレーションファイルを新しく作成します。Userモデルにnameカラムを追加する場合は下記のようにコマンドを実行します。
$ rails g migration add_name_to_users name:string
以下のような画面が表示されたらOKです。
    invoke  active_record
    create    db/migrate/20201104152112_add_name_to_users.rb
マイグレーションファイルを確認すると以下のように記述されています。
class AddNameToUsers < ActiveRecord::Migration[5.2]
  def change
    add_column :users, :name, :string
  end
end
DBに反映するため,マイグレーションを実行します。
$ rails db:migrate
以下のように表示されればOKです。
== 20201104152112 AddNameToUsers: migrating ==================================
-- add_column(:users, :name, :string)
   -> 0.0042s
== 20201104152112 AddNameToUsers: migrated (0.0043s) =========================
これでUserモデルにnameカラムが追加され,DBに反映されました。
2. devise.rbの設定を変更する
emailの代わりにnameでログインするためには,devise.rbの設定を変更する必要があります。(私が以前ハマったのはこの変更をしていなかったためでした。忘れずに行いましょう!)
app/config/initializers/devise.rb の
config.authentication_keys = [:email] のコメントアウトを外し
config.authentication_keys = [:name] に変更します。
# 該当箇所は⌘Fで検索すると早いです。
  # ==> Configuration for any authentication mechanism
  # Configure which keys are used when authenticating a user. The default is
  # just :email. You can configure it to use [:username, :subdomain], so for
  # authenticating a user, both parameters are required. Remember that those
  # parameters are used only when authenticating and not when retrieving from
  # session. If you need permissions, you should implement that in a before filter.
  # You can also supply a hash where the value is a boolean determining whether
  # or not authentication should be aborted when the value is not present.
  # config.authentication_keys = [:email] この行を下のように変更する
    config.authentication_keys = [:name]
これで,emailの代わりにnameで認証するように設定を変更できました。
3. コントローラーを編集する
次にapplication_controller.rbを編集します。
class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?
  protected
  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
  end
end
before_action :configure_permitted_parameters, if: :devise_controller?
これについて簡単に説明すると,deviseを使用する際にはまず最初に configure_permitted_parameters メソッドを実行することを示しています。メソッドはその下に定義しています。
devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
これは,サインアップする際にnameの値を送信することを許可することを示しています。emailやpasswordの値はデフォルトで許可されています。
つまり,deviseの処理が実行される際に,configure_permitted_parameters メソッドによって,nameの値を使えるようにしているんだな,と思っていただければ大丈夫です。
(protectedってなんぞや?と思われた方は「rails ストロングパラメータ」などで検索してみると幸せになれると思います。)
4. Viewを編集する
devise関連のviewは以下のコマンドで作成できます。
$ rails g devise:views
      invoke  Devise::Generators::SharedViewsGenerator
      create    app/views/devise/shared
      create    app/views/devise/shared/_error_messages.html.erb
      create    app/views/devise/shared/_links.html.erb
      invoke  form_for
      create    app/views/devise/confirmations
      create    app/views/devise/confirmations/new.html.erb
      create    app/views/devise/passwords
      create    app/views/devise/passwords/edit.html.erb
      create    app/views/devise/passwords/new.html.erb
      create    app/views/devise/registrations
      create    app/views/devise/registrations/edit.html.erb
      create    app/views/devise/registrations/new.html.erb
      create    app/views/devise/sessions
      create    app/views/devise/sessions/new.html.erb
      create    app/views/devise/unlocks
      create    app/views/devise/unlocks/new.html.erb
      invoke  erb
      create    app/views/devise/mailer
      create    app/views/devise/mailer/confirmation_instructions.html.erb
      create    app/views/devise/mailer/email_changed.html.erb
      create    app/views/devise/mailer/password_change.html.erb
      create    app/views/devise/mailer/reset_password_instructions.html.erb
      create    app/views/devise/mailer/unlock_instructions.html.erb
viewの作成が完了しました。
ここからの作業は2つです。
- サインアップ画面を編集して,nameを登録できるようにする。
- ログイン画面を編集して,nameでログインできるようにする。
順に見ていきます。
まず,サインアップ画面のviewは,app/views/devise/registrationsにある new.html.erb になりますので,これを編集します。
<h2>Sign up</h2>
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= render "devise/shared/error_messages", resource: resource %>
  <%# 追加 %>
  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name, autofocus: true, autocomplete: "name" %>
  </div>
  <%# ここまで %>
  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
  </div>
# 中略
サーバーを立ち上げて /users/sign_up にアクセスします。

これでサインアップ画面に名前を入力する欄ができました。
次にログイン画面のviewは,app/views/users/sessionsにある new.html.erb になりますので,これを編集してnameでログインできるようにしていきましょう。
<h2>Log in</h2>
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
  <div class="field">
    <%# 削除 %>
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
    <%# ここまで %>
    <%# 追加 %>
    <%= f.label :name %><br />
    <%= f.text_field :name, autofocus: true, autocomplete: "name" %>
    <%# ここまで %>
  </div>
# 中略
以上で,名前でのログインが可能になりました。
参考文献
この記事は,以下の情報を参考に執筆しました。
devise機能を使ったユーザーログインガイド&名前でログイン
deviseでnameとpasswordのみでユーザー登録とログインできるように、初心者がdeviseをカスタマイズ!〜徹底的にゆっくり解説〜
before_actionとストロングパラメーターの編集について
