【问题标题】:A url issue when implementing a resend token feature实现重新发送令牌功能时的 url 问题
【发布时间】:2016-08-10 03:02:52
【问题描述】:

在开始解释问题之前,我将简要解释一下该功能。当用户注册时,他们会在其电子邮件中获得一个激活令牌,该令牌将在 2 小时后过期。我试图实现一个功能,允许用户在他们的电子邮件中重新发送激活令牌。

重新发送激活令牌功能的代码如下所示。

用户控制器中的控制器代码

 def resend_verification_email
    @user = User.find_by(email: params[:resend_verification_email] [:email].downcase)
    if valid_email(params[:resend_verification_email] [:email])
      if !@user 
        redirect_to resend_verification_path
        flash[:danger] = "Email does not exist"
      elsif
        !@user.activated?
        UserMailer.resend_activation(@user).deliver_now
        flash[:success] = "Check your email for the activation token"
        redirect_to resend_verification_path
      else
        redirect_to resend_verification_path
        flash[:success] = "User is already activated."             
      end
    else
      flash[:danger] = "Email format is Invalid"
      redirect_to resend_verification_path
    end
  end

帐户激活控制器

class AccountActivationsController < ApplicationController

def edit
  user = User.find_by(email: params[:email])
  if user && !user.activated? && user.authenticated?(:activation, params[:id]) #the token is actually available by params id
    user.activate
    log_in user
    flash[:success] = "Account activated."
    redirect_to home_path
  else
    flash[:danger] = "Invalid activation link"
    redirect_to root_url
  end
end


end

邮件控制器方法

def resend_activation(user)
    @user = user
    @userid = user.id
    mail to: user.email, subject: "Account activation"
  end

邮件视图

<%= link_to "Activate your account", edit_account_activation_url(id: @user.activation_token, email: @user.email) %>

我收到以下错误。 No route matches {:action=&gt;"edit", :controller=&gt;"account_activations", :email=&gt;"example@gmail.com", :id=&gt;nil} missing required keys: [:id]

我明白错误在说什么。 url 的第一个参数是令牌,获取方式是通过 params[:id] 因为在 RESTful 路由中,id 始终是第一个参数。如果我去掉 URL,电子邮件就会很好地发送出去。 URL 引发了该错误,我不确定为什么。任何帮助,将不胜感激。谢谢!

我只包括了相关路线。

  get 'resend_verification'  => 'users#resend_verification'
  post 'resend_verification_email'  => 'users#resend_verification_email'

  resources :account_activations, only: [:edit]
  resources :password_resets,     only: [:new, :create, :edit, :update]

相关的rake路线

edit_account_activation GET    /account_activations/:id/edit(.:format)                                          account_activations#edit

                    users GET    /users(.:format)                                                                 users#index
                          POST   /users(.:format)                                                                 users#create
                 new_user GET    /users/new(.:format)                                                             users#new
                edit_user GET    /users/:id/edit(.:format)                                                        users#edit
                     user GET    /users/:id(.:format)                                                             users#show
                          PATCH  /users/:id(.:format)                                                             users#update
                          PUT    /users/:id(.:format)                                                             users#update
                          DELETE /users/:id(.:format)                                                             users#destroy


resend_verification GET    /resend_verification(.:format)                                                   users#resend_verification
resend_verification_email POST   /resend_verification_email(.:format)                                             users#resend_verification_email

【问题讨论】:

  • 我有一个解决办法。但在分享之前,请发布rake routes 的输出。我需要确定我是否正确。
  • @ArunKumar,我在原始问题中包含了 rake 路线。
  • 请发布rake routes的输出。不是您在 routes.rb 中定义的路由
  • @ArunKumar,我包括了用户模型、帐户激活以及 resend_token 路由的 GET 和 POST 请求。
  • 你解决过这个问题吗?我也有同样的问题。

标签: ruby-on-rails ruby


【解决方案1】:

好吧,我不会将account_activations 定义为资源丰富的路线。

评论:#the token is actually available by params id 解释了为什么,imo id 应该引用模型资源。

这是我解决此问题的方法:

  1. 将路线定义为:

get "/account_activations/edit", to: "account_activations#edit", as: 'edit_account_activation'

  1. 如下定义激活链接:

<%= link_to "Activate your account", edit_account_activation_url(token: @user.activation_token, email: @user.email) %>

  1. 更新控制器:

class AccountActivationsController < ApplicationController def edit user = User.find_by(email: params[:email]) if user && !user.activated? && user.authenticated?(:activation, params[:token]) #... rest of code...

或者,如果您真的想保持现状,请尝试重新定义您的电子邮件链接,如下所示:

<%= link_to "Activate your account", edit_account_activation_url(@user.activation_token, email: @user.email) %>

那么,params[:id] 可能指的是您提供的令牌。

【讨论】:

  • &lt;%= link_to "Activate your account", edit_account_activation_url(@user.activation_token, email: @user.email) %&gt; 这就是它应该的样子。 railstutorial.org/book/account_activation
  • 但我认为他的问题,以及我目前的问题,是出于某种原因@user.activation_token = nil。
【解决方案2】:

重新定义您的电子邮件链接如下:

<%= link_to "Activate your account", edit_account_activation_path( @user.activation_token, @user.email) %>

或者您可以将对象的主键传递给控制器​​,例如:@user.id 并使用

before_action :set_user, only: [:edit]  

在控制器内部定义私有方法以设置用户前:

private 
  def set_user
    @user = User.find_by_id(params[:id])
    redirect_to xyz_path if @user.blank?
  end

【讨论】:

    【解决方案3】:

    :activation_token 虚拟创建为attr_accessor

    这不是路由问题。

    @user.activation_token
    

    实际上返回 nil。

    如果您希望发送更多验证电子邮件,则需要将 activation_token 保存到用户模型。

    【讨论】:

      猜你喜欢
      • 2019-02-04
      • 2022-11-22
      • 1970-01-01
      • 2012-01-29
      • 2018-11-02
      • 2022-11-02
      • 2020-11-09
      • 2020-11-29
      • 1970-01-01
      相关资源
      最近更新 更多