Rails deviseの導入〜新規登録、ログイン時のカラム追加まで


# 初めに
某プログラミングスクールの卒業生です。 
スクールに通う中で学んだことや、つまづいたことを備忘録としてまとめてます。 
今回は、deviseを扱う際に必ず調べるであろう、独自カラムの追加方法をdeviseの導入からまとめておきたいと思います。
# 環境
・Ruby 2.5.7 
・Rails 5.2.4.1
# deviseの導入
deviseとは、ログインや新規登録機能等を簡単に実装できるgemです。   
まず初めに、Gemfileに以下の1行追加して保存します。  

```ruby:Gemfile
gem 'devise'
```
次にターミナルで下記を実行し、deviseをアプリケーションに読み込ませます。

```
$ bundle install
```

最後にターミナルで下記を実行し、deviseの初期設定を行います。

```
$ rails g devise:install
```

```
Running via Spring preloader in process 29980
      create  config/initializers/devise.rb
      create  config/locales/devise.en.yml
===============================================================================

Some setup you must do manually if you haven't yet:

  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.

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

       root to: "home#index"

  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>

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

       rails g devise:views
===============================================================================
```
ターミナルに上記のような表示がされれば成功です。
以上でdeviseを使う準備が整いました。

# deviseでモデルを作成する
準備が整ったので、いよいよdeviseを使ってみましょう。
今回は、ユーザー登録時の名前の追加と、ログイン時は名前とパスワードでログインできるようにカスタマイズしていきます。  
まず初めに、モデルを作成します。
ターミナルで下記のを実行し、モデルを作成します。

```
$ rails g devise User
```

```
Running via Spring preloader in process 30045
      invoke  active_record
      create    db/migrate/20200319222813_devise_create_users.rb
      create    app/models/user.rb
      invoke    test_unit
      create      test/models/user_test.rb
      create      test/fixtures/users.yml
      insert    app/models/user.rb
       route  devise_for :users
```
これで、「User」という名のモデルと、usersテーブル用のマイグレーションファイルが作成されました。
# 独自のカラムを追加しよう
モデルとマイグレーションファイルの作成ができたので、usersテーブルにカラムを追加していきましょう。
今回はnameカラムを追加します。
先ほど、作成したマイグレーションファイルに以下の１行を追加します。

```ruby:20200319222813_devise_create_users.rb
class DeviseCreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""
      t.string :name, null: false　←追加

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at
以下省略
```
追加したら、ターミナルでマイグレーションを実行しましょう。

```
$ rails db:migrate
```

実際にカラムが追加できたかschemaファイルで確認します。

```ruby:schema.rb
ActiveRecord::Schema.define(version: 2020_03_19_222813) do

  create_table "users", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "name", null: false ←追加されている
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
  end
```

追加されていることが確認できれば成功です。
# Viewを追加しよう
カラムの追加がおわったら、次に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
```
これでdevise用のViewを作成する事ができました。

# deviseをカスタマイズしよう
Viewが作成できたので、いよいよdeviseをカスタマイズしていきます。
今回は、ユーザー登録時の名前の追加と、ログイン時は名前とパスワードでログインできるようにカスタマイズしていきたいと思います。 
###新規登録画面に名前を追加 　
deviseの新規登録画面はデフォルトで、以下のようになっています。
今回はここに名前（Name）を追加します。
<img width="299" alt="スクリーンショット 2020-03-20 8.51.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529558/4516d5e0-186c-208a-cef9-5adc8f699a47.png"> 

新規登録のViewにNameを追加します。
以下を参考に追加してみてください。
※registrationsが新規登録のviewなので覚えておきましょう

```ruby: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 %>
  </div>
<%# ここまで　%>
  
  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autocomplete: "email" %>
  </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" %>

```
<img width="322" alt="スクリーンショット 2020-03-20 9.06.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529558/84b4159a-6068-65ef-5353-8e8c13deb3f6.png">

上記の追記で名前が追加できた事が確認できます。
これではまだ、名前の登録がデータベースに反映されません。
なので、最後にストロングパラメーターを設定しましょう。

```ruby:controllers/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
```
これでデータベースに名前が登録できるようになりました。
今後、カラムを増やす場合はストロングパラメーターにも忘れずに追加しましょう。

###名前とパスワードでログインできるように変更
deviseのログイン画面はデフォルトで、以下のようになっています。
今回はEmailを名前（Name）に変更します。
<img width="257" alt="スクリーンショット 2020-03-20 9.40.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529558/c2e2157c-69da-e28a-8941-775a69ae10a5.png">

ログインのViewをEmailからNameを変更します。
以下を参考に変更してみてください。
※sessionsがログインのviewなので覚えておきましょう

```ruby: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 :name %><br />
    <%= f.text_field :name, autofocus: true %>
  </div>
  <%# ここまで追加 %>
  
  <%# ここから %>
  <div class="field">
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true, autocomplete: "email" %>
  </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" %>
```
<img width="260" alt="スクリーンショット 2020-03-20 9.46.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529558/a1c864fd-51e2-d59f-44ad-bdcc33cbf926.png">

上記の追記でEmailが名前（Name)が変更できた事が確認できます。
これではまだ、名前でのログインができません。
devise.rbを書き換えて名前でのログインができるように変更します。

```ruby:config/initializers/devise.rb
# ==> 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]
```
devise.rbの中に上記のような記述があるかと思います。
その一番下の行をを変更してください。
※#を外すのを忘れないように注意してください。

```ruby:config/initializers/devise.rb
# config.authentication_keys = [:email]
↓　変更
config.authentication_keys = [:name]
```
これで名前をとパスワードでログインできるようになりました。
以上で新規登録とログインのカスタマイズが終わります。

# 最後に
備忘録程度のまとめになっているので、もしかしたら分かりにくいかもしれませんがご了承ください。
この投稿が少しでも役に立つ事があれば幸いです。