OneDay

40歳からプログラマとして生活しています。

Devise でログイン後に処理を挟み込む

plataformatec/devise · GitHub

Deviseでユーザーの登録やログイン、パスワード変更を実装していますが、ユーザーがログインしたときに一つ処理を入れるときの方法をシェアします。Railsではbefore_action, after_action, around_actionが基本的なフィルタとして用いられています。これらをDeviseのコントローラーにどう実装していくかがポイントです。

devise modelが 'User'とします。ジェネレーターでDeviseのコントローラーを生成します。

bin/rails g devise:controllers users

とすると、app/controllers/usersの配下に下記のコントローラーが生成されます。

├── confirmations_controller.rb
├── omniauth_callbacks_controller.rb
├── passwords_controller.rb
├── registrations_controller.rb
├── sessions_controller.rb
└── unlocks_controller.rb

例えば一番上のconfirmations_controller.rbの中身を見ると#でスケールアウトされています。メソッドをオーバーライドするときは#を外してコードを書いていきます。

class Messengers::ConfirmationsController < Devise::ConfirmationsController
  # GET /resource/confirmation/new
  # def new
  #   super
  # end
(略)

Deviseのカスタマイズ、メソッドのオーバーライドの要点は2つです。

  1. この生成されたコントローラーにコードを書く
  2. 修正したコントローラーをconfig/routes.rbに明示する

今回行いたいことは、ユーザーがログイン後に処理を走らせることです。新たなセッションが生成された後にということになるので、session#createがフックポイントです。app/controllers/users/sessions_controller.rbに書いていきます。

class Users::SessionsController < Devise::SessionsController
  after_action :additional_task, only: [:create]

  # GET /resource/sign_in
  #def new
    #super
  #end

  # POST /resource/sign_in
  def create
    super
  end

  # DELETE /resource/sign_out
  #def destroy
     #super
  #end

  private
  def additional_task
     #処理の中身
  end
end

これでsession#createの後に処理を走らせる準備ができました。単純にprivate以下にaddtional_taskというメソッドを追加し、after_action :additional_task, only: [:create]でcreateの後に処理を走らせるようにしています。newとcreateとdestroyというメソッドは#でスケールアウトしたままでも、メソッドが見つからなければRubyはsuperclassを見に行くのでエラーにはなりませんが、createのafter_actionという設定をしたのでcreateだけ#を外しています。
次はroute設定で、上書きした内容を読むように設定します。

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

これでRailsは、Deviseのsessionsを探す時にapp/controllers/users/sessions_controller.rbを見に行きます。このroutes設定をしなければDevise::SessionsControllerを見に行ってしまい、せっかく個別の設定をしても反映されません。

最後にもう一つ。viewsはデフォルトでdevise/sessions/new.html.erbでしたが、コントローラーはapp/controllers/users/sessions_controller.rbを適用としたので、viewsもapp/views/users/sessions/new.html.erbへ移動します。(デフォルトのままでもTemplate Missing等のエラーにはならずにうごきます)