在我们的注册表单上,我们validates_uniqueness_of :email
当用户尝试使用我们的注册表单并指定现有的电子邮件地址时,我希望他们看到这样的错误消息
此电子邮件地址已被使用。如果您在登录时遇到问题,可以reset your password
显然,我想使用命名路由作为链接,但我的用户模型无法访问它。我怎么能做到这一点?
旁注:我们很快会为我们的应用提供翻译,所有这些错误消息都会以YAML文件结尾。我可以以某种方式在我的YAML语言环境文件中的消息中注入new_password_url
吗? (例如,config/locales/en.yml
)
答案 0 :(得分:14)
我知道这是一个老问题,但对于想要在错误消息中插入链接的未来用户,以下是一些适用于我的指南。
首先,I18n错误消息已被假定为html安全,因此您可以继续编写合适的错误消息。在这个例子中,我正在更改“发送电子邮件”消息。
# config/locales/en.yml
activerecord:
errors:
models:
user:
attributes:
email:
taken: 'has already been taken. If this is your email address, try <a href="%{link}">logging in</a> instead.'
注意插值变量%link
。
现在您需要在验证器中传递该变量的值,如下所示:
# app/models/user.rb
validates :email, :uniqueness => {:link => Rails.application.routes.url_helpers.login_path}
(默认情况下,您在此处传递的所有选项都会自动作为变量发送到I18n翻译器,包括一些特殊的预填充变量,如%value
,%model
等。
就是这样!您现在在错误消息中有一个链接。
答案 1 :(得分:1)
这可能不能很好地简化翻译,但这里有一个建议:
在user_controller #create操作中,使用if语句包装已有的所有内容。这是一个粗略的例子:
class UserController < ApplicationController
...
def create
if User.find(params[:email])
flash[:alert] = "This email address is in use. You can ".concat(generate_reset_password_link(params[:email])
render :action => 'new'
else
<your current code>
end
end
在此之后,你将不得不编写一个辅助方法generate_reset_password_link
,但我认为这主要是尊重MVC布局。控制器用于与视图和模型连接。它稍微违反了DRY原则,因为你基本上绕过了validates_uniqueness_of :email
,但是你得到了一些自定义行为。如果你想制作更复杂的应用程序,DRY对我来说似乎不是100%可行的,但也许你可以改进这个并证明我错了;)
您可能需要按一下这一点,以便render :action => 'new'
将使用先前输入的数据重新填充自己(如果用户只是错误输入了自己的电子邮件地址,并且实际上不在系统中)。< / p>
如果你决定使用这种方法,我会在两者控制器和模型中发表评论,表明电子邮件的唯一性基本上是在2个地方检查过的。如果其他人必须查看此代码,它将帮助他们理解和维护它。
答案 2 :(得分:0)
您可以在错误消息中放置自己的标记,如〜[new_password_url]。然后在渲染您的错误消息gsub ur标签与实际。如果你想一般性地做到这一点,你可以使用regexp获取路径,然后评估它以获取url然后gsub它。如果你将html放入你的文本,请使用raw方法。
答案 3 :(得分:0)
如果您使用的是2.3.x,请使用自己的帮助程序替换对error_messages
的调用,并使用UsersHelper编写。它应该接受FormBuilder或ActiveRecord对象,并根据需要调整错误消息。您可以根据需要进行任意数量的自定义,也可以像gsub一样简单:
def user_error_messages(f)
find_error = "This email address is already in use."
replacement = "This email address is already in use. #{link_to(...)} to reset your password"
f.error_messages.sub(find_error, replacement).html_safe
end
如果您正在使用Rails3,请创建一个帮助方法,以便在它们发送到视图之前处理@user.errors.full_messages
。
答案 4 :(得分:0)
今天偶然发现了这个:
http://api.rubyonrails.org/classes/ActionDispatch/Routing/UrlFor.html
如果您需要从其他地方(例如模特)访问此自动生成的方法,那么您可以通过在班级中加入
ActionController::UrlFor
来实现此目的:
了解模型的命名路线是困难的部分;这让我大部分时间。
现在我可以按照
的方式做点什么class User < ActiveRecord::Base
include Rails.application.routes.url_helpers
def reset_password_uri
new_user_password_path(self)
end
end
# User.find(1).reset_password_uri => "/users/password/new"
所以我们可以访问命名路由,但现在我们需要将它注入YAML消息。
以下是我刚学到的关于YAML变量的内容:
# en.yml
en:
welcome: "Hello, %{username}!"
# es.yml
es:
welcome: "¡Hola, %{username}!"
我可以通过在username
方法
t
<div id="welcome">
<%= t :welcome, :username => @user.username %>
</div>
现在我们只需要一种方法来为原始问题中描述的错误消息添加插值。这就是我目前陷入困境的地方:(
答案 5 :(得分:-1)
经过几个小时试图用设计来解决Rails 4,我意识到你可以直接将链接添加到验证中:
# app/models/user.rb
validates :username, presence: true, uniqueness: {:message => "username has already been taken - <a href='/users'>search users</a>" }
这种情况下的链接是我的用户索引。希望这会对某人有所帮助!