9
2

More than 1 year has passed since last update.

【Rails】devise_invitableで招待メールからパスワード登録したユーザのリダイレクト先を変更する

Posted at

deviseとdevise_invitable

deviseとはRailsで作成したアプリケーションへ簡単に認証機能を実装することができるgem(ライブラリ)の一つで、devise_invitableはdeviseに招待機能を追加するgemになります。

やりたいこと

devise_invitableで招待メールを送信

パスワード設定用の招待メールが送られてくる

パスワード設定

希望の画面にリダイレクトする (今回はこれをやりたい

問題点

パスワードを設定すると自動でログインしてくれるのですが、
設定後にroot_pathに遷移してしてしまう。

ハマったところ

deviseには元来after_sign_up_path_for(登録後のリダイレクト先を変更できるメソッド)や
after_sign_in_path_for(ログイン後のリダイレクト先を変更できるメソッド)が存在しており、
招待メールからパスワードを設定したのちに自動でログイン状態になっているので同様のやり方でいけると思っていました。

  • after_sign_up_path_forafter_sign_in_path_forについては
    こちらの記事で分かりやすくまとめられていました。

解決策

ログを読んでみたところ、招待メールからパスワードを登録した際にはライブラリのinvitations_controllerupdateアクションが呼ばれていることがわかりましたのでGitHubに公開されているコードを確認しました。

devise_invitable/app/controllers/devise/invitations_controller.rb
  # PUT /resource/invitation
  def update
    raw_invitation_token = update_resource_params[:invitation_token]
    self.resource = accept_resource
    invitation_accepted = resource.errors.empty?

    yield resource if block_given?

    if invitation_accepted
      if resource.class.allow_insecure_sign_in_after_accept
        flash_message = resource.active_for_authentication? ? :updated : :updated_not_active
        set_flash_message :notice, flash_message if is_flashing_format?
        resource.after_database_authentication
        sign_in(resource_name, resource)
        respond_with resource, location: after_accept_path_for(resource) // ←ここ
      else
        set_flash_message :notice, :updated_not_active if is_flashing_format?
        respond_with resource, location: new_session_path(resource_name)
      end
    else
      resource.invitation_token = raw_invitation_token
      respond_with_navigational(resource) { render :edit, status: :unprocessable_entity }
    end
  end

招待を受けた場合の処理として、ログイン(sign_in)を行なったのちafter_accept_path_for(resource)でroot_pathに遷移させていることが分かりました。

実際の作業

本来、外部ライブラリであるdevise又はdevise_invitableのコントローラーはGem内に記述されているため編集することはできません。
そこで、このcontrollerをオーバーライドしてカスタマイズをしていきます。

まずはオーバーライドするためのファイルを作成します。

$ rails g controller users/invitations

ファイルを作成したらGitHubのUpdateアクションの部分をコピペして先ほどのafter_accept_path_for(resource)の部分を遷移させたいパスに編集します。

編集後
module Users
  class InvitationsController < Devise::InvitationsController
    def update
      raw_invitation_token = update_resource_params[:invitation_token]
      self.resource = accept_resource
      invitation_accepted = resource.errors.empty?

      yield resource if block_given?

      if invitation_accepted
        if resource.class.allow_insecure_sign_in_after_accept
          flash_message = resource.active_for_authentication? ? :updated : :updated_not_active
          set_flash_message :notice, flash_message if is_flashing_format?
          resource.after_database_authentication
          sign_in(resource_name, resource)
          respond_with resource, location: users_path(resource)
        else
          set_flash_message :notice, :updated_not_active if is_flashing_format?
          respond_with resource, location: new_session_path(resource_name)
        end
      else
        resource.invitation_token = raw_invitation_token
        respond_with_navigational(resource) { render :edit, status: :unprocessable_entity }
      end
    end
  end
end

このとき、routes.rbでルーティングの設定を忘れないようにします。

routes.rb
  devise_for :users, controllers: {
    sessions: 'users/sessions',
    passwords: 'users/passwords',
    registrations: 'users/registrations',
    invitations: 'users/invitations'
  }

これでいけました。

9
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
2