【Rails】deviseをIDとパスワードを使ってログインできる感じにするための手順のメモ

# personal_idカラムの作成
以下をターミナルで実行。
```
$ rails g migration add_personal_id_to_users personal_id:string:uniq  
```
すると以下のマイグレーションファイルが作成される。
```ruby:db/2022xxxxx_add_personal_id_to_uers
class AddUserIdToUsers < ActiveRecord::Migration[6.1]
  def change
    add_column :users, :personal_id, :string
    add_index :users, :personal_id, unique: true
  end
end
```
以下をターミナルで実行
```
$ docker-compose exec app rails db:migrate
```
これでpersonal_idカラムが作成された。スキーマは以下のようになっている。
```ruby:db/schema
ActiveRecord::Schema.define(version: 2022_10_30_072844) do

  create_table "users", charset: "latin1", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.string "personal_id" 
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
    t.index ["personal_id"], name: "index_users_on_personal_id", unique: true 
  end

end
```
# devise.rbの編集
以下の内容について、emailをpersonal_idに置き換える。
```ruby:initializers/devise.rb
Devise.setup do |config|
...
  # config.authentication_keys = [:email]
  config.authentication_keys = [:personal_id]
...
  #config.case_insensitive_keys = [:email]
  config.case_insensitive_keys = [:personal_id]
...
#config.strip_whitespace_keys = [:email]
  config.strip_whitespace_keys = [:personal_id]
...
end
```

# application controllerの編集
サインアップ時のストロングパラメータにpersonal_idを追加し、POSTリクエストからpersonal_idをコントローラーが取得できるように設定する。
```ruby:app/controllers/aplication_controller.rb
class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

  protected
  #sign up時のストロングパラメータにpersonal_idを追加する。
  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:personal_id])
  end
end
```
# user modelの編集
personal_idを各ユーザーについて一意とする。ユーザー情報等の変更や新規作成時にemailによる認証を不要とするため、関連するメソッドを無効化する。
```ruby:app/models/user.rb
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable, :recoverable, :rememberable,
 :validatable, authentication_keys:[:personal_id]

  validates :email, uniqueness: true 
  validates :personal_id, uniqueness: true #personal_idを一意とする。

#emailに関するメソッドを無効化。
  def email_required?
    false
  end

  def email_changed?
    false
  end

  def will_save_change_to_email?
    false
  end

end
```

# viewの編集
元々emailだった箇所をpersonal_id用のviewに変えていく。
```erb: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 :personal_id, "ID" %><br />
    <%= f.text_field :personal_id, autofocus: true, autocomplete: "personal_id" %>
  </div>

  <div class="field">
    <%= f.label :password %>
    <% if @minimum_password_length %>
    <em>(<%= @minimum_password_length %> characters minimum)</em>
    <% end %><br />
    <%= f.password_field :password, autocomplete: "new-password" %>
  </div>

  <div class="field">
    <%= f.label :password_confirmation %><br />
    <%= f.password_field :password_confirmation, autocomplete: "new-password" %>
  </div>

  <div class="actions">
    <%= f.submit "Sign up" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>

```
```erb:app/views/devise/sessions/new.html.erb
<h2>Log in</h2>

<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
  <div class="field">
    <%= f.label :personal_id, "ID" %><br />
    <%= f.text_field :personal_id, autofocus: true, autocomplete: "personal_id" %>
  </div>

  <div class="field">
    <%= f.label :password %><br />
    <%= f.password_field :password, autocomplete: "current-password" %>
  </div>

  <% if devise_mapping.rememberable? %>
    <div class="field">
      <%= f.check_box :remember_me %>
      <%= f.label :remember_me %>
    </div>
  <% end %>

  <div class="actions">
    <%= f.submit "Log in" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>

```