Rails6.1+devise の controller と view をカスタマイズできる状態にする
前回の続きです。
- docker-compose 下で rails new して Rails6.1+deviseを試す | 北山淳也 | zenn
TL;DR
下記記事などとやってることと大差ないです。
ただ、コントローラー生成後にどう編集するとか
生成された controller や view の解説などをしっかりめに書いてる記事が見当たらなかったので
その辺りは丁寧めに書いてみました。
- Deviseの設定手順をまとめてみた。 その2 ViewとControllerのカスタマイズ編 | Qiita
- Rails deviseの導入とView + Controllerのカスタマイズ(sign_in/out後のpath指定など) | Qiita
今回やること、やらないこと
- やること
- devise のビューとコントローラーのカスタマイズ
 
- やらないこと
- ビューの見た目をきれいにする
 
準備
前回に引き続き appコンテナ のターミナルで作業を進めます。
docker-compose down でコンテナを落としてしまっていたら、再度
docker-compose run --rm --service-ports app bash
で app コンテナのターミナルにログインしておきましょう。
コマンドでサクッと準備する
bundle exec rails g devise:views users と
bundle exec rails g devise:controllers users して
必要なものを生成しましょう。
(前回、 bundle install 時に --path vendor/bundle をなくしたときは、以下のコマンドで bundle exec としている部分は bundle exec なしで実行してください)
$ bundle exec rails g devise:views users
Running via Spring preloader in process 10924
      invoke  Devise::Generators::SharedViewsGenerator
      create    app/views/users/shared
      create    app/views/users/shared/_error_messages.html.erb
      create    app/views/users/shared/_links.html.erb
      invoke  form_for
      create    app/views/users/confirmations
      create    app/views/users/confirmations/new.html.erb
      create    app/views/users/passwords
      create    app/views/users/passwords/edit.html.erb
      create    app/views/users/passwords/new.html.erb
      create    app/views/users/registrations
      create    app/views/users/registrations/edit.html.erb
      create    app/views/users/registrations/new.html.erb
      create    app/views/users/sessions
      create    app/views/users/sessions/new.html.erb
      create    app/views/users/unlocks
      create    app/views/users/unlocks/new.html.erb
      invoke  erb
      create    app/views/users/mailer
      create    app/views/users/mailer/confirmation_instructions.html.erb
      create    app/views/users/mailer/email_changed.html.erb
      create    app/views/users/mailer/password_change.html.erb
      create    app/views/users/mailer/reset_password_instructions.html.erb
      create    app/views/users/mailer/unlock_instructions.html.erb
      invoke  Devise::Generators::SharedViewsGenerator
      create    app/views/users/shared
      create    app/views/users/shared/_error_messages.html.erb
      create    app/views/users/shared/_links.html.erb
      invoke  form_for
      create    app/views/users/confirmations
      create    app/views/users/confirmations/new.html.erb
      create    app/views/users/passwords
      create    app/views/users/passwords/edit.html.erb
      create    app/views/users/passwords/new.html.erb
      create    app/views/users/registrations
      create    app/views/users/registrations/edit.html.erb
      create    app/views/users/registrations/new.html.erb
      create    app/views/users/sessions
      create    app/views/users/sessions/new.html.erb
      create    app/views/users/unlocks
      create    app/views/users/unlocks/new.html.erb
      invoke  erb
      create    app/views/users/mailer
      create    app/views/users/mailer/confirmation_instructions.html.erb
      create    app/views/users/mailer/email_changed.html.erb
      create    app/views/users/mailer/password_change.html.erb
      create    app/views/users/mailer/reset_password_instructions.html.erb
      create    app/views/users/mailer/unlock_instructions.html.erb
$ bundle exec rails g devise:controllers users
Running via Spring preloader in process 10933
      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
===============================================================================
生成されたものの解説
$ bundle exec rails g devise:views users
| 今回使う | 概要 | path | 
|---|---|---|
| ○ | 共通で使うもの | app/views/users/shared 配下 | 
| ○ | ユーザー登録確認メール後 | app/views/users/confirmations 配下 | 
| ○ | パスワードを忘れたとき〜のやつ | app/views/users/passwords 配下 | 
| ○ | サインアップ(パスワード登録),パスワード編集など | app/views/users/registrations 配下 | 
| ○ | ログイン,ログアウト | app/views/users/sessions 配下 | 
| ○ | 各機能で送信されるHTMLメール本文 | app/views/users/mailer 配下 | 
$ bundle exec rails g devise:controllers users
| 今回使う | 概要 | path | 
|---|---|---|
| ○ | ユーザー登録確認メール後 | app/controllers/users/confirmations_controller.rb | 
| ○ | パスワードを忘れたとき〜のやつ | app/controllers/users/passwords_controller.rb | 
| ○ | サインアップ(パスワード登録),パスワード編集など | app/controllers/users/registrations_controller.rb | 
| ○ | ログイン,ログアウト | app/controllers/users/sessions_controller.rb | 
| ○ | ブロック解除機能 | app/controllers/users/unlocks_controller.rb | 
| × | OmniAuth のコールバック | app/controllers/users/omniauth_callbacks_controller.rb | 
生成されたコントローラーのコメントを外す
bundle exec rails g devise:controllers users で生成されたコントローラーは
全てコメントアウトされています。
使用するコントローラーのコメントを外して使える状態にしましょう。
ついでなので生成された時のコメントを翻訳しておきました。
あとさらについでなので、本当に生成したコントローラーが叩かれているか確認するための puts をいくつか追加しておきました。
自身でもっと確認したいときは適宜 puts を追加したりしてください。
また、生成されたコントローラー内にあるコメントの
# GET /resource/sign_in
など /resource となっている部分は、それぞれ生成対象とした resource のことですよ、
という意味です。
なので今回は /resource は /user を指していますね。
# GET /resource/sign_in であれば # GET /users/sign_in です。
同様に該当のコメント部分は編集してあります。
では、生成されたコントローラーのコメントを外していきましょう。
# frozen_string_literal: true
class Users::ConfirmationsController < Devise::ConfirmationsController
  # GET /users/confirmation/new
  def new
    super
  end
  # POST /users/confirmation
  def create
    super
  end
  # GET /users/confirmation?confirmation_token=abcdef
  def show
    super
  end
  protected
  # 確認指示を再送した後に使用する path
  def after_resending_confirmation_instructions_path_for(resource_name)
    super(resource_name)
  end
  # 確認後に使用する path
  def after_confirmation_path_for(resource_name, resource)
    super(resource_name, resource)
  end
end
# frozen_string_literal: true
class Users::PasswordsController < Devise::PasswordsController
  # GET /users/password/new
  def new
    super
  end
  # POST /users/password
  def create
    super
  end
  # GET /users/password/edit?reset_password_token=abcdef
  def edit
    super
  end
  # PUT /users/password
  def update
    super
  end
  protected
  def after_resetting_password_path_for(resource)
    super(resource)
  end
  # リセットパスワードの指示を送信した後に使用する path
  def after_sending_reset_password_instructions_path_for(resource_name)
    super(resource_name)
  end
end
# frozen_string_literal: true
class Users::RegistrationsController < Devise::RegistrationsController
  before_action :configure_sign_up_params, only: [:create]
  before_action :configure_account_update_params, only: [:update]
  # GET /users/sign_up
  def new
    super
    puts '========================='
    puts 'GET /resource/sign_up'
    puts '========================='
  end
  # POST /users
  def create
    super
  end
  # GET /users/edit
  def edit
    super
    puts '========================='
    puts 'GET /resource/edit'
    puts '========================='
  end
  # PUT /users
  def update
    super
  end
  # DELETE /users
  def destroy
    super
  end
  # GET /users/cancel
  # 通常はサインイン後に
  # 期限切れになるセッションデータを強制的に今すぐ期限切れにします。
  # これは、ユーザーがすべての OAuth セッションデータを削除して、
  # 途中で oauth サインイン/アップをキャンセルしたい場合に便利です。
  def cancel
    super
  end
  protected
  # 許可するための追加のパラメータがある場合は、sanitizer に追加してください
  def configure_sign_up_params
    devise_parameter_sanitizer.permit(:sign_up, keys: [:attribute])
  end
  # 許可するための追加のパラメータがある場合は、sanitizer に追加してください
  def configure_account_update_params
    devise_parameter_sanitizer.permit(:account_update, keys: [:attribute])
  end
  # サインアップ後に使用する path
  def after_sign_up_path_for(resource)
    super(resource)
  end
  # アクティブでないアカウントのサインアップ後に使用する path
  def after_inactive_sign_up_path_for(resource)
    super(resource)
  end
end
# frozen_string_literal: true
class Users::SessionsController < Devise::SessionsController
  before_action :configure_sign_in_params, only: [:create]
  # GET /users/sign_in
  def new
    super
    puts '========================='
    puts 'GET /resource/sign_in'
    puts '========================='
  end
  # POST /users/sign_in
  def create
    super
  end
  # GET /users/sign_out
  # ここは config/initializers/devise.rb で config.sign_out_via = :get としているので DELETE ではなく GET
  def destroy
    super
  end
  protected
  # 許可するための追加のパラメータがある場合は、sanitizer に追加してください
  def configure_sign_in_params
    devise_parameter_sanitizer.permit(:sign_in, keys: [:attribute])
  end
end
# frozen_string_literal: true
class Users::UnlocksController < Devise::UnlocksController
  # GET /users/unlock/new
  def new
    super
  end
  # POST /users/unlock
  def create
    super
  end
  # GET /users/unlock?unlock_token=abcdef
  def show
    super
  end
  protected
  # パスワードのロック解除指示を送信した後に使用する path
  def after_sending_unlock_instructions_path_for(resource)
    super(resource)
  end
  # リソースのロックを解除した後に使用する path
  def after_unlock_path_for(resource)
    super(resource)
  end
end
生成されたコントローラーを使用するように config/routes.rb を編集する
これを
# 前回の作業が終わった状態の config/routes.rb
Rails.application.routes.draw do
  devise_for :users
  get 'home/index'
  get 'home/show'
  root to: "home#index"
  ## 開発環境用letter_opener
  mount LetterOpenerWeb::Engine, at: "/letter_opener" if Rails.env.development?
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
こんな感じに編集します。
Rails.application.routes.draw do
  devise_for :users, :controllers => {
    :confirmations => 'users/confirmations',
    :registrations => 'users/registrations',
    :sessions => 'users/sessions',
    :passwords => 'users/passwords'
   }
  get 'home/index'
  get 'home/show'
  root to: "home#index"
  ## 開発環境用letter_opener
  mount LetterOpenerWeb::Engine, at: "/letter_opener" if Rails.env.development?
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
難しくはないですね。
動作確認
では Rails サーバーを起動して動作確認します。
bundle exec rails s -b "0.0.0.0"
http://localhost:3000 にアクセスし、「サインイン」を押してみましょう。
rails s したターミナルに
=========================
GET /resource/sign_up
=========================
Completed 200 OK in 135ms (Views: 124.2ms | Allocations: 5207)
と出たでしょうか?
やりました! 生成したコントローラーとビューが使われるようにカスタマイズできました。
他の部分も puts を追加したりいじってみたりして
生成したコントローラーとビューが使われているか確認してみてください。
今回のリポジトリはこちらです。
参考
- Deviseの設定手順をまとめてみた。 その2 ViewとControllerのカスタマイズ編 | Qiita
- Rails deviseの導入とView + Controllerのカスタマイズ(sign_in/out後のpath指定など) | Qiita
- Rails で Devise のコントローラーをカスタマイズ | EasyRamble
- Devise で devise_for メソッドによるルーティングを確認 | EasyRamble
- devise ユーザーのプロフィール画面作成と編集(デフォルトをカスタマイズ) | Qiita


Discussion