How to make Devise redirect after confirmation
Asked Answered
G

6

45

How can I create an after-confirmation redirect in Devise?

Before I added the confirmation module the custom after_sign_up_path worked fine for the first time login/signup but now when I click the confirmation link in the email it redirects to the path I set for the after-login path (user profile).

My goal is to create a form wizard and "getting started" page to collect additional information. The obvious caveat being that this redirect will only happen one time, upon confirmation.

I tried some other solutions that have been posted on Stack Overflow but none of them seem to work any longer.

Gauthier answered 7/6, 2012 at 6:20 Comment(0)
A
20

Essentially, you want to change around line 25 of Devise's ConfirmationsController.

This means you need to override the show action modifying the "happy path" of that if statement in the show action to your heart's content:

class ConfirmationsController < Devise::ConfirmationsController
  def new
    super
  end

  def create
    super
  end

  def show
    self.resource = resource_class.confirm_by_token(params[:confirmation_token])

    if resource.errors.empty?
      set_flash_message(:notice, :confirmed) if is_navigational_format?
      sign_in(resource_name, resource)
      respond_with_navigational(resource){ redirect_to confirmation_getting_started_path }
    else
      respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render_with_scope :new }
    end
  end
end

And a scoped route for it (I put the view and action in the registrations controller but you can change it to whatever):

devise_for :users, controllers: { confirmations: 'confirmations' }
devise_scope :user do
  get '/confirmation-getting-started' => 'registrations#getting_started', as: 'confirmation_getting_started'
end

The default show action is referring to the protected after_confirmation_path_for method, so as another option, you could just modify what that method returns.

Abradant answered 2/7, 2012 at 18:40 Comment(3)
If I add a confirmations_controller.rb to my app does that override the one devise provides? Otherwise, how would I edit the one supplied by Devise?Gauthier
Yes, you're overriding Devise's ConfirmationsController so you can make your own changes...which I thought is what you were trying to do. Also, see my edit to my answer...I forgot the addition to the routes file where you specify that you're using your own ConfirmationsController. Good luck!Abradant
Well, you are only overriding the methods/actions you define. Any methods you don't touch get sent to Devise::ConfirmationsController.Stagemanage
D
141

A less intrusive way of achieving this might be just overriding the after_confirmation_path_for method of Devise::ConfirmationsController.

Create a new confirmations_controller.rb in app/controllers directory:

class ConfirmationsController < Devise::ConfirmationsController

  private

  def after_confirmation_path_for(resource_name, resource)
    your_new_after_confirmation_path
  end

end

In config/routes.rb, add this line so that Devise will use your custom ConfirmationsController. This assumes Devise operates on users table (you may edit to match yours).

devise_for :users, controllers: { confirmations: 'confirmations' }

Restart the web server, and you should have it.

Direction answered 27/2, 2013 at 15:12 Comment(5)
@azure_ardee That's not true. This new hash syntax was introduced in Ruby 1.9 and works fine for newer Ruby versionsImpasto
Thanks for this. I wonder why those basic paths can't be defined trough devise configuration...Exasperation
this is the best answer.Disappointment
This IS the best answer. June 13th, 2015 and this answer still works!Statics
Here is the actual original code, up to date github.com/plataformatec/devise/blob/master/app/controllers/…Rena
A
20

Essentially, you want to change around line 25 of Devise's ConfirmationsController.

This means you need to override the show action modifying the "happy path" of that if statement in the show action to your heart's content:

class ConfirmationsController < Devise::ConfirmationsController
  def new
    super
  end

  def create
    super
  end

  def show
    self.resource = resource_class.confirm_by_token(params[:confirmation_token])

    if resource.errors.empty?
      set_flash_message(:notice, :confirmed) if is_navigational_format?
      sign_in(resource_name, resource)
      respond_with_navigational(resource){ redirect_to confirmation_getting_started_path }
    else
      respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render_with_scope :new }
    end
  end
end

And a scoped route for it (I put the view and action in the registrations controller but you can change it to whatever):

devise_for :users, controllers: { confirmations: 'confirmations' }
devise_scope :user do
  get '/confirmation-getting-started' => 'registrations#getting_started', as: 'confirmation_getting_started'
end

The default show action is referring to the protected after_confirmation_path_for method, so as another option, you could just modify what that method returns.

Abradant answered 2/7, 2012 at 18:40 Comment(3)
If I add a confirmations_controller.rb to my app does that override the one devise provides? Otherwise, how would I edit the one supplied by Devise?Gauthier
Yes, you're overriding Devise's ConfirmationsController so you can make your own changes...which I thought is what you were trying to do. Also, see my edit to my answer...I forgot the addition to the routes file where you specify that you're using your own ConfirmationsController. Good luck!Abradant
Well, you are only overriding the methods/actions you define. Any methods you don't touch get sent to Devise::ConfirmationsController.Stagemanage
S
19

Have you checked the Devise wiki? It explains how to do this, with the after_signup_path_for being the path to define in your case.

From the wiki:

Make a new controller "registrations_controller.rb" and customize the appropriate method:

class RegistrationsController < Devise::RegistrationsController
  protected

  def after_sign_up_path_for(resource)
    '/an/example/path'
  end
end

Then add a route to use it:

Modify config/routes.rb to use the new controller

devise_for :users, :controllers => { :registrations => "registrations" }
Stagemanage answered 7/6, 2012 at 7:56 Comment(2)
Do you mean that you want the redirect to happen after creating the account, but before the confirmation? Than you should set after_inactive_sign_up_path_for. It's in the Devise wiki page I linked to, but just in a little line between examples, easy to miss (it took me a while to figure this out when I needed it...).Stagemanage
Here is the reference to the after_inactive_sign_up_path_for that mentions Niels: Devise wikiUncouple
A
3

The solution given by @Lee Smith is working perfectly but I wish to add a little addition: We don't need to add the new and create actions while overriding the Devise confirmations controller for this case:

class ConfirmationsController < Devise::ConfirmationsController
  def show
    self.resource = resource_class.confirm_by_token(params[:confirmation_token])

    if resource.errors.empty?
      set_flash_message(:notice, :confirmed) if is_navigational_format?
      sign_in(resource_name, resource)
      respond_with_navigational(resource){ redirect_to your_desired_redirect_path }
    else
      respond_with_navigational(resource.errors, status: :unprocessable_entity){ render_with_scope :new }
    end
  end
end

Then in the route file, just add routing for the confirmations controller.

devise_for :users, controllers: { confirmations: "confirmations" }
Avitzur answered 18/10, 2017 at 3:28 Comment(0)
U
2

I just went through all of this and none of the other answers worked (2015-04-09 with devise 3.4.1).

After signup, I wanted the user to be redirected to the login page with a message about a confirmation email. To get that working, here's what I had to do:

class RegistrationsController < Devise::RegistrationsController

protected
  # This is the method that is needed to control the after_sign_up_path 
  # when using confirmable. 
  def after_inactive_sign_up_path_for(resource)
    new_user_session_path
  end

end

I just found this comment which would have sent me exactly where I needed to be much sooner.

Here is the reference to the after_inactive_sign_up_path_for that mentions Niels: Devise wiki – marrossa Nov 13 '12 at 3:38

Uncork answered 9/4, 2015 at 6:42 Comment(1)
undefined local variable or method `not_confirmed_path' for #<User:0x00007fbfd9c2a7b8>Isogamete
P
-3

The confirmation_path also must be configured while working with refinerycms integrated in a rails app

Pestilent answered 19/5, 2013 at 17:43 Comment(1)
What does refinerycms have to do with this question?Anticlockwise

© 2022 - 2024 — McMap. All rights reserved.