我正在使用Ruby on Rails 3.0.9,我正在尝试验证嵌套模型。假设我为“主”模型运行验证并为嵌套模型生成一些错误,我得到以下结果:
@user.valid?
@user.errors.inspect
# => {:"account.firstname"=>["is too short", "can not be blank"], :"account.lastname"=>["is too short", "can not be blank"], :account=>["is invalid"]}
如何看待RoR框架创建一个errors
哈希,其中包含以下密钥:account.firstname
,account.lastname
,account
。由于我想通过JavaScript(BTW:我使用jQuery)处理那些涉及CSS属性的错误键\值对,在前端内容上显示错误消息,我想“准备”该数据并将这些键更改为{ {1}},account_firstname
,account_lastname
(注意:我将account
替换为.
字符。
如何更改密钥值,例如_
到account.firstname
?
而且,最重要,我应该如何应对这种情况?我正在尝试以“好”方式处理嵌套模型错误?如果不是,这样做的常见\最佳方法是什么?
答案 0 :(得分:4)
我快速关注,显示了嵌套模型的完整错误消息:
https://gist.github.com/4710856
#1.9.3-p362 :008 > s.all_full_error_messages
# => ["Purchaser can't be blank", "Consumer email can't be blank", "Consumer email is invalid", "Consumer full name can't be blank"]
答案 1 :(得分:2)
对Rails错误哈希进行一些创意修补可以让您实现目标。在config/initalizers
中创建初始值设定项,将其称为errors_hash_patch.rb
并将以下内容添加到其中:
ActiveModel::Errors.class_eval do
def [](attribute)
attribute = attribute.to_sym
dotted_attribute = attribute.to_s.gsub("_", ".").to_sym
attribute_result = get(attribute)
dotted_attribute_result = get(dotted_attribute)
if attribute_result
attribute_result
elsif dotted_attribute_result
dotted_attribute_result
else
set(attribute, [])
end
end
end
您在此处所做的只是简单地覆盖访问方法[]
以尝试更难一点。更具体地说,如果您正在寻找的键具有下划线,它将尝试按原样查找它,但如果它找不到任何内容,它也将用点替换所有下划线并尝试查找它。除此之外,行为与常规[]
方法相同。例如,假设您有一个类似于示例中的错误哈希:
errors = {:"account.firstname"=>["is too short", "can not be blank"], :"account.lastname"=>["is too short", "can not be blank"], :account=>["is invalid"]}
以下是您可以访问它的一些方法以及返回的结果:
errors[:account] => ["is invalid"]
errors[:"account.lastname"] => ["is too short", "can not be blank"]
errors[:account_lastname] => ["is too short", "can not be blank"]
errors[:blah] => []
我们不会更改密钥存储在错误哈希中的方式,因此我们不会意外地破坏可能依赖于哈希格式的库和行为。关于我们如何访问哈希中的数据,我们所做的就是更聪明一些。当然,如果您想要更改散列中的数据,那么模式与您只需要覆盖[]=
方法相同,并且每次rails尝试存储带有点的键时,只需更改点到下划线。
至于你的第二个问题,即使我已经向你展示了如何做你所要求的,一般来说最好是尝试遵守rails尝试做事的方式,而不是试图弯曲你的轨道将。在你的情况下,如果你想通过javascript显示错误消息,大概你的javascript将有权访问错误数据的散列,所以为什么不用javascript调整这些数据,使其成为你需要的格式。或者,您可以在控制器内克隆错误数据并在那里进行调整(在您的javascript访问它之前)。在不了解您的情况(如何编写表单,您的验证JS试图做什么等等)的情况下很难提供建议,但这些是一些通用指南。
答案 2 :(得分:1)
我对AngularJs有同样的问题,所以我决定在名为as_json
的初始化程序中覆盖ActiveModel::Errors
类的active_model_errors.rb
方法,以便它可以替换.
_
这是初始化代码:
module ActiveModel
class Errors
def as_json(options=nil)
hash = {}
to_hash(options && options[:full_messages]).each{ |k,v| hash[k.to_s.sub('.', '_')] = messages[k] }
hash
end
end
end
我希望它对某人有帮助
答案 3 :(得分:0)
我不确定,但我认为你可以在没有痛苦的情况下改变这种行为。但是你可以试试像http://bcardarella.com/post/4211204716/client-side-validations-3-0
这样的解决方案