首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Rails 3的更好的validates_associated方法?

Rails 3的更好的validates_associated方法?
EN

Stack Overflow用户
提问于 2010-09-08 21:05:58
回答 4查看 8.9K关注 0票数 18

Rails3包含在保存嵌套模型时自动调用的validates_associated。这个方法的问题是消息太可怕了-- "Model(s) is invalid“

在Rails2中有一些帖子攻击这个问题:

而且可能还有更多。如果能有一个更好的版本,就像这些文章中描述的那样,并且兼容Rails3,那就太好了。主要的改进将包括相关模型失败的原因。

EN

回答 4

Stack Overflow用户

发布于 2012-02-14 09:57:49

在关系上,您可以改用:autosave => true,它将在您保存父模型时尝试保存子模型。这将自动运行子项的验证,并且它们将报告正确的错误消息。

此外,如果在必须设置父对象的子对象上添加存在验证,并通过关联构造子对象,则甚至不需要autosave标志,就会得到一条漂亮的错误消息。例如:

代码语言:javascript
复制
class Trip < ActiveRecord::Base
  validates :name, :presence => true

  attr_accessible :name

  has_many :places, dependent: :destroy, :inverse_of => :trip
end

class Place < ActiveRecord::Base
  belongs_to :trip

  validates :name, :trip, presence: true

  attr_accessible :name
end

然后,您可以通过以下使用场景获得一条不错的错误消息:

代码语言:javascript
复制
> trip = Trip.new(name: "California")
=> #<Trip id: nil, name: "California"> 
> trip.places.build
=> #<Place id: nil, name: nil, trip_id: nil>
> trip.valid?
=> false
> trip.errors
=> #<ActiveModel::Errors:0x00000004d36518 @base=#<Trip id: nil, name: "California">, @messages={:places=>["is invalid"]}>
> trip.errors[:places]
=> ["is invalid"] 

我认为validates_associated是儿童自动保存之前时代的遗物,不再是做事情的最佳方式。当然,这并不一定有很好的文档记录。我不能百分之百确定这是否也适用于Rails2.3,但我有一种感觉。这些更改是在添加嵌套属性特性时发生的(在2.x中的某个时候)。

这是来自training project I posted on github的简化代码片段。

票数 5
EN

Stack Overflow用户

发布于 2012-11-28 05:44:07

我遇到了这个问题,最后我使用了Ben Lee给出的解决方案

validates associated with model's error message

本说:

您可以根据内置验证器的代码编写自己的自定义验证器。

查看validates_associated的源代码,我们发现它使用了"AssociatedValidator“。它的源代码是:

代码语言:javascript
复制
module ActiveRecord
  module Validations
    class AssociatedValidator < ActiveModel::EachValidator
      def validate_each(record, attribute, value)
        return if (value.is_a?(Array) ? value : [value]).collect{ |r| r.nil? || r.valid? }.all?
        record.errors.add(attribute, :invalid, options.merge(:value => value))
      end
    end

    module ClassMethods
      def validates_associated(*attr_names)
        validates_with AssociatedValidator, _merge_attributes(attr_names)
      end
    end
  end
end

因此,您可以使用它作为示例来创建一个自定义验证器,该验证器生成如下错误消息:

代码语言:javascript
复制
module ActiveRecord
  module Validations
    class AssociatedBubblingValidator < ActiveModel::EachValidator
      def validate_each(record, attribute, value)
        (value.is_a?(Array) ? value : [value]).each do |v|
          unless v.valid?
            v.errors.full_messages.each do |msg|
              record.errors.add(attribute, msg, options.merge(:value => value))
            end
          end
        end
      end
    end

    module ClassMethods
      def validates_associated_bubbling(*attr_names)
        validates_with AssociatedBubblingValidator, _merge_attributes(attr_names)
      end
    end
  end
end

您可以将此代码放入初始化器中,就像/initializers/associated_bubbling_validator.rb一样。

最后,您可以像这样进行验证:

代码语言:javascript
复制
class User < ActiveRecord::Base
 validates_associated_bubbling :account
end

注意:上面的代码是完全未经测试的,但如果它不能完全工作,希望它足以让您走上正确的道路

票数 3
EN

Stack Overflow用户

发布于 2011-03-03 12:28:24

validates_associated运行关联对象的类中指定的验证。父类级别的错误只是说‘我的孩子是无效的’。如果需要详细信息,可以在子对象上公开错误(在视图中的子窗体级别)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3668018

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档