嵌套模型错误消息

我正在使用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.firstnameaccount.lastnameaccount 。 由于我想通过JavaScript(BTW:我使用jQuery)处理那些涉及CSS属性的错误键值对我在前端内容上显示错误消息,我想“准备”该数据并将这些键更改为account_firstnameaccount_lastnameaccount (注意:我用.替换. )。

如何将密钥值从例如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这样的解决方案