ActiveModel:在关联模型失败时禁用验证失败

时间:2011-07-13 20:04:15

标签: ruby-on-rails validation activerecord activemodel validates-associated

默认情况下,Rails3是否始终针对所有型号运行validates_associated

在像这样的简单设置中

class Post < ActiveRecord::Base
    has_many :comments
end

class Comment < ActiveRecord::Base
    belongs_to :post

    def validate
        errors.add_to_base("its always invalid")
    end
end

附有评论的新帖子失败,因为评论无效。

a = Post.new
a.comments << Comment.new
a.errors
    => {:comments=>["is invalid"]}

如果validates_associated始终运行,那么它为什么会出现(更改:message?),如何将其关闭?我尝试了validates_associated :comments, :unless => proc{true},但它没有做任何事情。

我只想要一个模型来保存,如果每个相关记录都有效,则尝试保存每个相关记录,但如果关联模型无效则不会自动失败。


编辑:这更接近我正在尝试做的事情

# t.string :name
class Game < ActiveRecord::Base
    has_one :wikipedia_paragraph
    has_one :ign_rating

    def name=(_name)
        ret = super
        self.build_wikipedia_paragraph
        self.build_ign_rating
        ret
    end
end


# t.text :paragraph
class WikipediaParagraph < ActiveRecord::Base
    belongs_to :game

    validates_presence_of :paragraph

    def game=(_game)
        ret = super
        self.paragraph = Wikipedia.find(self.game.name)
        ret
    end
end

class IgnRating..

有更多模型遵循与游戏相同的结构,如书籍,电影。如果WikipediaParagraph.paragraph == nil则游戏未通过验证。我希望如果Game保存并且WikipediaParagraph没有,但has_one :wikipedia_paragraph, :validate => false同时保存,没有保存。

我希望比使用

更优雅
self.build_wikipedia_paragraph
self.wikipedia_paragraph = nil unless self.wikipedia_paragraph.valid?

对于每个has_one/many,但现在我意识到它可能不可能。

2 个答案:

答案 0 :(得分:3)

查看文档http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_many。它显示在保存父对象时默认验证has_many关联。您可以将其设置为false,如下所示:

class Post < ActiveRecord::Base
    has_many :comments, :validate => false
end

如果您没有默认验证关联并希望自己处理它,我认为validates_associated可以派上用场。整个情况有点令人困惑,所以我希望这会有所帮助。

答案 1 :(得分:0)

您的验证会强制执行您的应用程序的业务逻辑。如果您始终希望保存Post对象,则无论相关注释的状态如何,您都可以单独保存帖子和注释。这将允许您迭代一组注释,并尝试保存每个注释,如果出现错误则继续

post = Post.new
post.valid? # true

comments.each do |comment|
  comment.save # some will some wont
end

我知道这并没有像你描述的那样完全修复你的问题,但考虑你为什么要禁用关联的验证可能会很好。问题:validate =&gt;对has_many调用的错误是它将始终保存而不进行验证,这可能不是您想要的。

在保持验证的同时,是否有更正统的方法来解决这个问题?