嵌套模型错误消息

时间:2011-08-13 12:58:49

标签: ruby-on-rails ruby ruby-on-rails-3 validation model

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

如何更改密钥值,例如_account.firstname

而且,最重要,我应该如何应对这种情况?我正在尝试以“好”方式处理嵌套模型错误?如果不是,这样做的常见\最佳方法是什么?

4 个答案:

答案 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

这样的解决方案