Rails - 电子邮件确认链接给出“未知操作”错误
Posted
技术标签:
【中文标题】Rails - 电子邮件确认链接给出“未知操作”错误【英文标题】:Rails - Email confirmation link giving 'Unknown Action' error 【发布时间】:2013-04-22 18:51:53 【问题描述】:我需要一点帮助。我正在尝试:
-
发送带有链接的电子邮件。
让链接设置 user.email_activation_token = true
然后重定向到主页。
目前我有一个指向电子邮件的链接,但它给了我这个错误。 (顺便说一句,我正在使用 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
【问题讨论】:
【参考方案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 的任何用途
也许你可以安全地删除它
【讨论】:
以上是关于Rails - 电子邮件确认链接给出“未知操作”错误的主要内容,如果未能解决你的问题,请参考以下文章
Rails 中的电子邮件确认,无需使用任何现有的身份验证 gem/插件
rails - Gibbon mailchimp gem 将订阅者添加到列表中,但不发送确认电子邮件