【Ruby on Rails】emailを使わずにユーザー機能を実装する方法

# はじめに
ユーザー登録機能を実装する際に'devise'を使う人が多いかと思います。deviseはデフォルトでemailとpasswordでの登録、ログイン機能が実装されていますが、今回はemailではなく、email以外の認証でユーザー機能の実装方法について投稿します。
以後、number_idというキーを利用します。

# devise実装
【参考】
https://qiita.com/cocoa-engineer/items/625da569fcac1ad2db1f


# マイグレーションファイル編集

number_idを必須、一意性を持たせるために以下のように編集しました。
この時、マイグレーションファイルからemailを消さずに、下記のemailの一意性制約は削除しました。理由としては、一人目のユーザー登録は行えるのですが、二人目以降のユーザー登録が行えなかったためです。ユーザー登録時emailカラムは空欄のまま一人目は登録されですが、一意性制約はnullに対しても働くため二人目以降のユーザー登録時にmysqlエラーを起こしてしまいます。

```ruby:~_devise_create_users.rb
  def change
    create_table :users do |t|
      t.string  :email,              null: false, default: ""
      t.string  :encrypted_password, null: false, default: ""
      t.string  :number_id,          null: false
# 中略
      t.timestamps null: false
    end
# 追記
    add_index :users, :number_id,            unique: true
 # 以下削除
    - add_index :users, :email,               unique: true
```
作成されたマイグレーションファイルを実行する。

```
$ rails db:migrate
```
＊ ファイルの編集前にマイグレーションを実行している人は

```
$ rails db:drop
$ rails db:create
```
を行なってからマイグレーションファイルを実行しましょう。

# ストロングパラメーターの設定
number_idを使って登録、ログイン、number_idの変更等を行えるようにapplication_controller.rbにストロングパラメーターを設定します。

```ruby:application_controller.rb
class ApplicationController < ActionController::Base
  before_action :configure_permitted_parameters, if: :devise_controller?

    private

    def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:number_id)
    devise_parameter_sanitizer.permit(:sign_in, keys: [:number_id])
    devise_parameter_sanitizer.permit(:account_update, keys: [:number_id])
    end
end
```

# number_idでユーザー登録するための設定
deviseではユーザー登録の際にemailは必須となっていますので、emailは不要にし、認証にnumber_idを利用するように以下のように追記します。

```ruby:user.rb
class User < ApplicationRecord

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
        # number_idで認証を可能にするため
         authentication_keys: [:number_id]

   # number_idを必須、一意性とする
  with_options presence: true do
    validates :number_id, uniqueness: true
  end

#登録時にemailを不要とするため
  def email_required?
    false
  end

  def email_changed?
    false
  end
end
```

# Viewの編集
email入力欄をnumber_id入力欄に編集しました。
この時、emailフォームはf.email_fieldからf.text_fieldに変更しましょう。

```ruby:views/devise/registrations/new.html.erb
<h2>ユーザー登録</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 :number_id, "ID"%><br />
    <%= f.text_field :number_id, autofocus: true, autocomplete: "number_id" %>
  </div>

  <div class="field">
    <%= f.label :password, "パスワード"%>
    <% if @minimum_password_length %>
    <em>(<%= @minimum_password_length %>文字以上)</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 "登録" %>
  </div>
<% end %>

<%= render "devise/shared/links" %>
```
ユーザーログイン用のviewファイルも編集すると完了です。

## 参考
https://qiita.com/cocoa-engineer/items/cfa31b0a81489c9ced83

### 最後に
初のQiita投稿でした。
業務未経験なりにわかりやすく編集したつもりですが、間違っていたらご指摘をお願いします。