首页 > 解决方案 > 设计确认账号并设置密码

问题描述

在我的应用程序中,我使用的是 Devise 和 Active Admin。用户是在没有密码的管理区域创建的,然后他们会收到一封邮件,其中包含指向确认页面的链接,他们可以在其中输入新帐户的密码。

这是确认控制器:

class ConfirmationsController < Devise::ConfirmationsController

  def show
    @original_token = params[:confirmation_token]
    digested_token = Devise.token_generator.digest(self, :confirmation_token,params[:confirmation_token])
    self.resource = resource_class.find_by_confirmation_token(digested_token) if params[:confirmation_token].present?
    super if resource.nil? or resource.confirmed?
    render :layout => "internal"
    end


  def confirm
    digested_token = Devise.token_generator.digest(self, :confirmation_token, params[resource_name][:confirmation_token])
    self.resource = resource_class.find_by_confirmation_token(digested_token) if params[resource_name][:confirmation_token].present?
    if resource.update_attributes(params[resource_name].except(:confirmation_token).permit(:email, :password, :password_confirmation)) && resource.password_match?
      self.resource = resource_class.confirm_by_token(params[resource_name][:confirmation_token])
      set_flash_message :notice, :confirmed
  sign_in_and_redirect(resource_name, resource)

    else
      @original_token =  params[resource_name][:confirmation_token]
      render :action => "show", :layout => "internal"
    end    
    
  end
  
end

相关路线:

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

  devise_scope :user do
    patch "/confirm" => "confirmations#confirm"
  end

当用户在后台单击激活链接时,它将帐户设置为在数据库中确认,但不是被重定向到确认/显示以设置密码,而是在此行渲染:layout =>“内部”

在此操作中多次调用渲染和/或重定向。请注意,您只能调用渲染或重定向,并且每个操作最多调用一次。另请注意,重定向和渲染都不会终止操作的执行,因此如果您想在重定向后退出操作,则需要执行“redirect_to(...) and return”之类的操作。

为什么会这样?

标签: ruby-on-railsdevise

解决方案


In your ConfirmationsController:

class ConfirmationsController < Devise::ConfirmationsController

  def show
    @original_token = params[:confirmation_token]
    digested_token = Devise.token_generator.digest(self, :confirmation_token,params[:confirmation_token])
    self.resource = resource_class.find_by_confirmation_token(digested_token) if params[:confirmation_token].present?
    # here you call super if resource is nil or confirmed
    # super calls the show action of Devise::ConfirmationController
    # it results with the first render (but doesn't call any return)
    super if resource.nil? or resource.confirmed?
    # after super is finished you continue and render layout internal
    # (again, since it has happened in the parent controller already)
    render :layout => "internal"
  end
...

you can check what exactly is being done in Devise::ConfirmationsController on their github page: https://github.com/heartcombo/devise/blob/master/app/controllers/devise/confirmations_controller.rb

if you want to render render the confirmations/show page then just remove the

render layout: 'internal'

line.


推荐阅读