设计 - 用户确认如何重定向到其他页面

时间:2014-07-13 07:33:02

标签: ruby-on-rails ruby-on-rails-3 devise confirmation

我正在使用Rails 3.2.13Devise 3.2.4。用户注册后,生成确认链接。

  localhost:3000/users/confirmation?confirmation_token=HpPHitLtV3CnLy2z1ZmQ

点击确认链接后,我想重定向到导师/新动作。

但在确认后,它会重定向到 / users / sign_in ,这是我不想要的。以下是我到目前为止的代码。

路线

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

从Devise :: ConfirmationsController

创建了Confirmations控制器和覆盖
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

在ConfirmationsController中,我可能需要添加一些额外的代码。请提供一些解决方案。

在应用程序控制器中,我已经放置了以下代码,这些代码在成功登录后将我带到导师/学生家中

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

def after_sign_up_path_for(resource_or_scope)
  root_path
end

一般来说,逻辑是这样的,但我不知道如何用Devise做到这一点。

def activate
  @user = User.where("activation_code = ?","#{params[:id]}").first
  if !@user.blank?
   if @user.created_at < 24.hours.ago
     if @user and @user.activate
      cookies[:user_id]=@user.id
      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

2 个答案:

答案 0 :(得分:1)

如果你看devise github repository。这是单击确认链接时调用的方法

# 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

现在你已经覆盖了设计 after_confirmation_path 这样的方法

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

哪个好,设计会重定向到你的new_mentor_path,但在你的导师控制器中你需要一个文件管理器来检查身份验证,如:

before_action :authenticate_user! #this will check if your user is signed in or not and if not it'll redirect you

因为@Rich Peck建议您在重定向到new_mentor_path 之前,基本上还需要覆盖您的show动作以便用户登录

在您的展示操作中,您可以执行以下操作以确保您的用户已登录

# 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

还在你的after_confirmation_path中注意到你有redirect_to new_mentor_path("account_id")为什么你在路径中将account_id作为字符串传递?

如果您的account_id是一个整数,那么您必须先在show action中设置它,然后调用after_confirmation_path,如 respond_with_navigational(resource){redirect_to after_confirmation_path_for(resource_name,resource,account_id)}。您还必须更改after_confirmation_path的定义,如:

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 

答案 1 :(得分:0)

经过研究,我发布了问题的正确答案。

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)  #This will detect if user is logged in.

  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

protected
def after_confirmation_path_for(resource_name, resource)

  if resource.is_a?(User)
   new_mentor_path("account_id") #do not provide redirect_to which is already taken in respond_with_navigational(resource)
  else
   root_path
  end
 end  
end

我评论devise_for:用户,因为每次点击确认链接并且确认控制器没有调用并重定向到登录路径时,此路由都在调用。以下是我面临的问题的主要解决方案。

# devise_for :users
devise_for :users, :controllers => { :confirmations => 'confirmations' }