嵌套模型错误消息
我正在使用Ruby on Rails 3.0.9,我正在尝试validation嵌套模型。 假设我为“main”模型运行validation并为嵌套模型生成一些错误,我得到以下结果:
@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属性的错误键值对我在前端内容上显示错误消息,我想“准备”该数据并将这些键更改为account_firstname
, account_lastname
, account
(注意:我用.
替换.
)。
如何将密钥值从例如account.firstname
更改为account_firstname
?
而且, 最重要的是 ,我应该如何处理这种情况? 我正在尝试以“好”方式处理嵌套模型错误? 如果不是,这样做的常见\最佳方法是什么?
一些创意修补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
你在这里所做的只是简单地覆盖访问器方法[]
尝试一点点努力。 更具体地说,如果您正在寻找的键具有下划线,它将尝试按原样查找它,但如果它找不到任何内容,它也将用点替换所有下划线并尝试查找它。 除此之外,行为与regular []
方法相同。 例如,假设您有一个类似于示例中的错误哈希:
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访问它之前)。 在不了解您的情况(如何编写表单,您的validationJS试图做什么等等)的情况下很难提供建议,但这些是一些通用指南。
我做了一个快速关注,它显示了嵌套模型的完整错误消息:
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"]
我对AngularJs有同样的问题,所以我决定在名为active_model_errors.rb
的初始化程序中覆盖ActiveModel::Errors
类的as_json
方法,以便它可以替换.
为_
这是初始化代码:
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
我希望它对某人有帮助
我不确定,但我认为你无法在没有痛苦的情况下改变这种行为。 但你可以试试像http://bcardarella.com/post/4211204716/client-side-validations-3-0这样的解决方案