2011-08-13 72 views
3

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

如何将密钥值从例如account.firstname更改为account_firstname

而且,大部分重要,我应该如何处理这种情况呢?我试图做一个“好”的方式来处理嵌套的模型错误?如果不是,那么通常的最佳方法是什么?

回答

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试图存储带有点的键时,只需将点改为下划线即可。

至于你的第二个问题,即使我已经告诉你如何去做你所问的问题,但总的来说,最好的办法是遵循钢轨试图做的事情,而不是试图弯曲钢轨你的意愿。在你的情况下,如果你想通过javascript显示错误消息,大概你的JavaScript将有权访问错误数据的哈希值,那么为什么不用JavaScript来调整这些数据,使其成为你需要的格式。或者,您可以克隆控制器内的错误数据并在其中调整(在JavaScript访问之前)。如果你不了解你的情况(你如何编写你的表格,你的验证JS试图做什么等等),那么很难提供建议,但这些都是一些一般性的指导方针。

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

我有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 

我希望它可以为别人