【devise】モデル作成前後のdeviseの導入方法

# はじめに

devise機能の導入を行なったので、まとめておきます。

# deviseのGemを導入

Gemfileにdeviseを記入しインストールします。

```:Gemfile
gem 'devise'
```

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

インストールを行うと、ターミナルに以下が表示されます。

```
create  config/initializers/devise.rb
create  config/locales/devise.en.yml
```
この2つのファイルが作られました。
以下、続きます。

```
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 *
```
これで設定してください、と言ってくれています。
次はこれに沿って設定を行います。

# 各種設定

ユーザー登録の際に登録したメールアドレスにメールが送られます。
そのメールに記載するURLを指定します。

```config/environments/development.rb
Rails.application.configure do
    config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
end
```

ユーザー登録や変更をした後の、リダイレクト先のデフォルトはrootのため設定が必要です。
アプリに合わせて、ルーティングは変更します。

```config/routes.rb
Rails.application.routes.draw do
    root to: "home#index"
end
```

フラッシュメッセージの設定をします。

```app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
    <body>
##以下を追記##
        <p class="notice"><%= notice %></p>
        <p class="alert"><%= alert %></p>
##以上を追記##
    </body>
</html>
```

# モデルの作成

deviseを使いたいモデルを作成します。
すでに作成している場合でも、devise用に必要なカラム等もあるため、行います。

```
$ rails g devise 〇〇
```

〇〇に作りたいモデル名を入れます。

Userというモデルを作った場合、以下がターミナルに表示されます。

```
invoke  active_record
      create    db/migrate/20230403070347_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

```

これでモデルの作成やルーティングの追加、マイグレーションファイルの作成などが行われます。

マイグレーションファイルは以下のようになっています。

```db/migrate/yyyymmddhhmmss_devise_create_users.rb
# frozen_string_literal: true

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: ""

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

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      # t.integer  :sign_in_count, default: 0, null: false
      # t.datetime :current_sign_in_at
      # t.datetime :last_sign_in_at
      # t.string   :current_sign_in_ip
      # t.string   :last_sign_in_ip

      ## Confirmable
      # t.string   :confirmation_token
      # t.datetime :confirmed_at
      # t.datetime :confirmation_sent_at
      # t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at


      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
```

マイグレートしておきましょう。

```
$ rails db:migrate
```

これで基本的な機能の準備は完了です。
導入後は、rails sを再起動しておきましょう。


### すでに作成したモデルにdeviseを追加したい場合

すでにモデルを作成している場合、エラーが表示される可能性があります。

```
ERROR: column "email" of relation "users" already exists
```

こういった感じのエラーが出ました。
Userテーブルにすでにemailカラムを作ってしまっているのが原因のようです。

この場合は、マイグレーションファイルを書き換えます。

```db/migrate/yyyymmddhhmmss_add_devise_to_users.rb
# frozen_string_literal: true

class AddDeviseToUsers < ActiveRecord::Migration[6.1]
  def self.up
### 以下を追記 ###
    change_column_default :users, :email, from: nil, to: ""
### 以上を追記 ###
    change_table :users do |t|
      ## Database authenticatable
### 以下をコメントアウト ###
      #t.string :email,              null: false, default: ""
### 以上をコメントアウト ###
      t.string :encrypted_password, null: false, default: ""

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

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      # t.integer  :sign_in_count, default: 0, null: false
      # t.datetime :current_sign_in_at
      # t.datetime :last_sign_in_at
      # t.string   :current_sign_in_ip
      # t.string   :last_sign_in_ip

      ## Confirmable
      # t.string   :confirmation_token
      # t.datetime :confirmed_at
      # t.datetime :confirmation_sent_at
      # t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at


      # Uncomment below if timestamps were not included in your original model.
      # t.timestamps null: false
    end

### すでにemailカラムにユニーク制約をつけている場合のみ、以下をコメントアウト ###
    #add_index :users, :email,                unique: true
### すでにemailカラムにユニーク制約をつけている場合のみ、以上をコメントアウト ###
    add_index :users, :reset_password_token, unique: true
    # add_index :users, :confirmation_token,   unique: true
    # add_index :users, :unlock_token,         unique: true
  end

  def self.down
    # By default, we don't want to make any assumption about how to roll back a migration when your
    # model already existed. Please edit below which fields you would like to remove in this migration.
    raise ActiveRecord::IrreversibleMigration
  end
end
```

Userテーブルにemailカラムを作る部分の記載をコメントアウトし、
emailカラムに必要なデフォルト値を指定しました。

上記では、ユニーク制約を追加する部分もコメントアウトしていますが、まだ制約がついていない場合はそのままにしましょう。

## 終わりに

エラーが出ても、ちゃんと読んで理由を考えれば、調べずともすぐ解決できるんだなぁと感じました。
まだまだ分からないことも多いですが...


お読みいただき、ありがとうございました！