I am using Rails 3.2.13 and Devise 3.2.4. After user registration, the confirmation link is generated:
localhost:3000/users/confirmation?confirmation_token=HpPHitLtV3CnLy2z1ZmQ
I want to redirect to the mentors/new
action after clickin on the confirmation link, but after confirmation it redirects to /users/sign_in
which I don't want.
This is my code so far:
Routes:
devise_for :users
devise_for :users, :controllers => { :confirmations => 'confirmations' }
Created Confirmations controller and overrides from Devise::ConfirmationsController:
class ConfirmationsController < Devise::ConfirmationsController
protected
def after_confirmation_path_for(resource_name, resource)
if resource.has_role? :user
redirect_to new_mentor_path("account_id")
else
root_path
end
end
end
In ConfirmationsController, maybe I have to add some extra code.
In application controller I have this code which takes me to the mentor/student
home after a successfull sign-in:
def after_sign_in_path_for(resource_or_scope)
if resource_or_scope.is_a?(User)
if current_user.user_type == "mentor"
home_mentors_path(:account_id => current_user.account_id)
else
home_students_path(:account_id => current_user.account_id)
end
end
end
def after_sign_up_path_for(resource_or_scope)
root_path
end
Generally the logic is like this, but I do not understand how to do this with Devise:
def activate
@user = User.where("activation_code = ?","#{params[:id]}").first
if [email protected]?
if @user.created_at < 24.hours.ago
if @user and @user.activate
cookies[:user_id][email protected]
if @user.user_type == "student"
redirect_to new_student_path
else
redirect_to new_mentor_path
end
else
@user.destroy
redirect_to "/"
end
else
@user.destroy
redirect_to "/"
end
else
redirect_to "/"
end
end
If you look at the Devise GitHub repository, this method is called when you click on the confirmation link:
# GET /resource/confirmation?confirmation_token=abcdef
def show
self.resource = resource_class.confirm_by_token(params[:confirmation_token])
yield resource if block_given?
if resource.errors.empty?
set_flash_message(:notice, :confirmed) if is_flashing_format?
respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) }
else
respond_with_navigational(resource.errors, status: :unprocessable_entity){ render :new }
end
end
Now you have overriden Devise's after_confirmation_path
method:
protected
def after_confirmation_path_for(resource_name, resource)
if resource.has_role? :user
redirect_to new_mentor_path("account_id")
else
root_path
end
end
which is fine and Devise will redirect to your new_mentor_path
but inside your Mentor controller you would have a before
filer to check for authentication, something like:
before_action :authenticate_user! #this will check if your user is signed in or not and if not it'll redirect you
So as @Rich Peck suggested, you basically need to override your show
action also so that your user is signed in before being redirected to your new_mentor_path
.
In your show
action you can do something like this to make sure your user is signed in:
# GET /resource/confirmation?confirmation_token=abcdef
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)
respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource) }
else
respond_with_navigational(resource.errors, :status => :unprocessable_entity){ render :new }
end
end
Also, I noticed in your after_confirmation_path
you have
redirect_to new_mentor_path("account_id")
Why are you passing account_id
as a string in your path?
If your account_id
is an integer then you'll have to first set it inside the show
action and then call your after_confirmation_path
like
respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource_name, resource, account_id) }
Also you'll have to change the definition of after_confirmation_path
like:
def after_confirmation_path_for(resource_name, resource, account_id)
if resource.has_role? :user
redirect_to new_mentor_path(account_id)
else
root_path
end
end