【问题标题】:Rails - Email confirmation link giving 'Unknown Action' errorRails - 电子邮件确认链接给出“未知操作”错误
【发布时间】:2013-04-22 18:51:53
【问题描述】:

我需要一点帮助。我正在尝试:

  1. 发送带有链接的电子邮件。
  2. 让链接设置 user.email_activation_token = true
  3. 然后重定向到主页。

目前我有一个指向电子邮件的链接,但它给了我这个错误。 (顺便说一句,我正在使用 HAML。)

编辑:目前没有视图。

未知操作

The action 'show' could not be found for UsersController

user_mailer/registration_confirmation

Confirm your email address please!

= accept_invitation_users_url({:token=>@user.email_activation_token})

users_controller.rb

class UsersController < ApplicationController
  def new
    @user = User.new
  end
  def create
    @user = User.new(params[:user])
    if @user.save
      UserMailer.registration_confirmation(@user).deliver
        redirect_to root_url, :notice => "Signed up!"
    else
        render "new"
    end

    def accept_invitation
        @user = User.find_by_email_activation_token!(params[:token])
        @user.email_activation_token = true
        redirect_to root_url, :notice => "Email has been verified."
    end
  end
end

email_activations_controller.rb

class EmailActivationsController < ApplicationController
    def edit
        @user = User.find_by_email_activation_token!(params[:id])
        @user.email_activation_token = true
        save!
        redirect_to root_url, :notice => "Email has been verified."
    end
    def new
        @user = User.find_by_email_activation_token!(params[:id])
    end

    def edit
    end
end

user.rb(用户模型)

    class User < ActiveRecord::Base
      attr_accessible :email, :password, :password_confirmation

      attr_accessor :password
      before_save :encrypt_password
      before_save { |user| user.email = email.downcase }
      before_create { generate_token(:auth_token) }
      # before_create { generate_token(:email_activation_token) }

      VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
      VALID_PASSWORD_REGEX = /^(?=.*[a-zA-Z])(?=.*[0-9]).{6,}$/
      validates_confirmation_of :password
      validates :password, :on => :create, presence: true, format: { with: VALID_PASSWORD_REGEX }
      validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive: false }

  def self.authenticate(email, password)
   user = find_by_email(email)
   if user && user.password_hash == BCrypt::Engine.hash_secret(password, user.password_salt)
    user
   else  
    nil
  end
end

  def send_password_reset
    generate_token(:password_reset_token)
    self.password_reset_sent_at = Time.zone.now
    save!
    UserMailer.password_reset(self).deliver
  end

  def encrypt_password
    if password.present?
        self.password_salt = BCrypt::Engine.generate_salt
        self.password_hash = BCrypt::Engine.hash_secret(password, password_salt)
    end
  end

def generate_token(column)
  begin
    self[column] = SecureRandom.urlsafe_base64
  end while User.exists?(column => self[column])
end

end

routes.rb

LootApp::Application.routes.draw do
  get "password_resets/new"

  get "sessions/new"

  resources :users
  resources :sessions
  resources :password_resets
  resources :email_activations

  resources :users do
    collection do 
      get :accept_invitation
    end 
  end

  # get "users/new"
  get "static_pages/home"
  get "static_pages/help"


  root to: 'static_pages#home'
  match "sign_up",  to: "users#new"
  match '/help',    to: 'static_pages#help'
  match '/log_in',  to: 'sessions#new'
  match '/log_out', to: 'sessions#destroy'
end

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3 authentication email-validation


    【解决方案1】:

    你为什么在 accept_invitation_users_url 中传递激活令牌而不是 id?当你有这个代码时:

    resources :users do
      member do 
        get :accept_invitation
      end 
    end
    

    在路由中,我们假设accept_invitation 是一个Restful 路由并且会在它的url 中给出id。见http://guides.rubyonrails.org/routing.html#adding-more-restful-actions

    所以,我认为你应该这样做:

    routes.rb

    # resources :users ### Remove this as it is reduntant
    
    resources :users do
      member do 
        get :accept_invitation
      end 
    end
    

    user_mailer/registration_confirmation

    Confirm your email address please!
    
    = accept_invitation_users_url(@user)
    

    users_controller.rb

    def accept_invitation
      @user = User.find(params[:id])
      @user.email_activation_token = true
      redirect_to root_url, :notice => "Email has been verified."
    end
    

    看完cmets

    是的,正如@Frederick Cheung 在 cmets 中所说,传递 id 而不是令牌会破坏发送电子邮件确认的意义,并使人们可以轻松地确认电子邮件地址而无需实际接收电子邮件。

    所以,请参考@PriteshJ 的回答。显然,您刚刚在routes.rb 中添加了一个额外的行resources :users,我对此大惊小怪:)。只需删除该行就可以了。

    【讨论】:

    • 传递令牌应该没问题。如果不通过,我会失败,并且会让人们在没有实际收到电子邮件的情况下轻松确认电子邮件地址。
    • 嘿,我试过了,但后来我在 UsersController#accept_invitation 中得到 ActiveRecord::RecordNotFound ---找不到没有 ID 的用户
    • @AlainGoldman..我在前面的答案中使用了collection 而不是member。现在必须修复它。
    【解决方案2】:

    试着改变这样的路线..

        resources :users do
          collection do 
            get :accept_invitation
          end 
        end
    
        resources :users
        resources :sessions
        resources :password_resets
        resources :email_activations
    

    【讨论】:

      【解决方案3】:

      您已调用资源 :users 两次。

      删除第一个调用

      【讨论】:

        【解决方案4】:

        routes.rb中有两条用户路由

        删除resources :users

        第一个 resources users 覆盖下一个用户资源

        所以应用程序不知道 collection 路由 accept_invitation 和 将其视为 id 用于显示操作,因为该操作的 url 将是

        /users/accept_invitation
        

        与show /users/:id的签名相匹配

        删除第一个 resources :users 应该可以解决问题

        我也没有看到 email_activations_controller.rb 的任何用途

        也许你可以安全地删除它

        【讨论】:

          猜你喜欢
          • 2013-04-25
          • 2013-04-23
          • 2013-04-21
          • 2014-07-18
          • 2011-03-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-02-01
          相关资源
          最近更新 更多