[Rails] devise の使い方 (備忘録)

# はじめに
これまでログイン、ログアウトといった認証系の機能は自前で実装していたのですが、今回ポートフォリオを制作するにあたってdeviseを使っておきたいなと思い、その使い方の備忘録として本記事を残します。
# 実行環境
この記事は以下の環境で動作確認しています。
ruby 2.7.1
rails 6.0.3
devise 4.7.3
# インストール
Gemfileに追記。
後半で日本語化するのでそのgemも入れておきます。

```ruby:Gemfile
gem 'devise'
gem 'devise-i18n'
gem 'devise-i18n-views'
```

`bundle install`を実行。

```
$ bundle install
```
# deviseの設定
関連ファイルを作成。

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

するとファイルが作成され、以下のような英文が表示されます。

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

Depending on your application's configuration some manual setup may be required:

  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 *

===============================================================================
```
1.　環境ファイルにデフォルトのurlオプションを定義します。

```ruby:config/environments/development.rb
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
```

2.　ルートurlを定義します。

```ruby:config/routes.rb
root to: 'homes#index'
```
3.　flashを表示させたい場所に以下を記載します。

```
<p class="notice"><%= notice %></p>
<p class="alert"><%= alert %></p>
```
4.　viewのカスタマイズについては後ほど記載します。


# Userモデルの作成
```
$ rails g devise User
```

作成されたマイグレーションファイルを見ると、emailとpasswordしかないので追加したいカラムがあれば追記します。追記し終えたらマイグレーションを実行。

```
$ rails db:migrate
```
この時点で http://localhost:3000/users/sign_up を開けば新規登録ページが作成されています。
もしカラムの追記を忘れていて後から追加したい場合は以下を実行する。（今回はusernameカラムの追加を想定して行う）

```
$ rails g migration add_username_to_users username:string
```

usernameは必ず記入して欲しいので NOT NULL 制約をつけておきます。

``` ruby:db/migrate/XXXXXXXXXXXXXX_add_username_to_users.rb
class AddUsernameToUsers < ActiveRecord::Migration[6.0]
  def change
    add_column :users, :username, :string, null: false
  end
end
```

# deviseに対応したviewの作成
viewのカスタマイズをしたいので以下を実行。

```
$ rails g devise:views users
```

viewの編集内容を反映させます。

```ruby:config/initializers/devise.rb
# 247行目の config.scoped_views = false のコメントアウトを外して true に変更
config.scoped_views = true
```

sign_upの際にusernameを登録できるようにします。

```ruby:app/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: [:username])
  end
end
```

# コントローラーを作成し、ルーティングを変更する

```
$ rails g devise:controllers users
```

コントローラーファイルと英文が表示されます。

```
Running via Spring preloader in process 9004
      create  app/controllers/users/confirmations_controller.rb
      create  app/controllers/users/passwords_controller.rb
      create  app/controllers/users/registrations_controller.rb
      create  app/controllers/users/sessions_controller.rb
      create  app/controllers/users/unlocks_controller.rb
      create  app/controllers/users/omniauth_callbacks_controller.rb
===============================================================================

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

  Ensure you have overridden routes for generated controllers in your routes.rb.
  For example:

    Rails.application.routes.draw do
      devise_for :users, controllers: {
        sessions: 'users/sessions'
      }
    end

===============================================================================
```

ここで現在のルーティングを確かめておきます。

```
$ rails routes

Prefix               Verb   URI Pattern                          Controller#Action
new_user_session     GET    /users/sign_in(.:format)             devise/sessions#new
user_session         POST   /users/sign_in(.:format)             devise/sessions#create
destroy_user_session DELETE /users/sign_out(.:format)            devise/sessions#destroy
...
new_user_registration GET    /users/sign_up(.:format)       devise/registrations#new
```
このようにController#Actionの部分が devise/registrations,devise/sessionsになっていると、これから定義するメソッドが反映されません。


コントローラーを作成した際に表示された英文に従ってルートをオーバーライドします。

```ruby:config/routes.rb
devise_for :users, controllers: {
    registrations: 'users/registrations',
    sessions: 'users/sessions'
  }
```

オーバーライドできたので現在のルーティングを確認します。

```
$ rails routes

Prefix               Verb   URI Pattern                    Controller#Action
new_user_session     GET    /users/sign_in(.:format)       users/sessions#new
user_session         POST   /users/sign_in(.:format)       users/sessions#create
destroy_user_session DELETE /users/sign_out(.:format)      users/sessions#destroy
...
new_user_registration GET    /users/sign_up(.:format)      users/registrations#new                   
```

このようになり、コントローラーのカスタマイズができるようになります。
メソッドを定義します。

```ruby:app/controllers/users/registrations_controller.rb
  # アカウント作成後のリダイレクト先
  def after_sign_up_path_for(resource)
    root_path
  end

  # アカウント編集後のリダイレクト先
  def after_update_path_for(resource)
    root_path
  end
```

```ruby:app/controllers/users/sessions_controller.rb
  # ログアウト後のリダイレクト先
  def after_sign_out_path_for(resource)
    root_path
  end

  # ログイン後のリダイレクト先
  def after_sign_in_path_for(resource)
    root_path
  end
```

これで全てのリダイレクト先がトップページになりました。

# 日本語化する
まず、このRailsアプリケーションのデフォルトの言語を日本語にします。

```ruby:config/application.rb
require_relative 'boot'
require 'rails/all'

Bundler.require(*Rails.groups)

module ConnectStudy
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 6.0
  
    config.i18n.default_locale = :ja # ここを追記
  end
end
```

devise の日本語翻訳ファイルを生成します。

```
$ rails g devise:views:locale ja
```
これで日本語になります。configを変更した際はサーバーの再起動をお忘れなく。

deviseには便利なヘルパーメソッドもたくさん用意されているのでそれらを利用してアプリ開発を効率よく行っていこうと思います。