ActiveModel: Disable failing validation when associated models fail
Does Rails3 always run validates_associated
against all models by default?
In a simple setup like this
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 new post with an attached comment fails because the comment is invalid.
a = Post.new
a.comments << Comment.new
a.errors
=> {:comments=>["is invalid"]}
If validates_associated
always runs, then why is it there (to change :message
?) and how do I turn it off? I have tried validates_associated :comments, :unless => proc{true}
but it doesn't do anything.
I simply want a model to save, try to save each associated record if each is valid, but not fail itself if an associated model is invalid.
EDIT: This is closer to what I'm trying to do
# 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..
There are more models that follow the same structure as Game, like Book, Movie. If WikipediaParagraph.paragraph == nil
then Game fails validation. I would prefer if Game saved and WikipediaParagraph didn't, but has_one :wikipedia_paragraph, :validate => false
makes both save, without it neither save.
I was hoping for something more elegant than using
self.build_wikipedia_paragraph
self.wikipedia_paragraph = nil unless self.wikipedia_paragraph.valid?
for every has_one/many
but now I realize its probabl开发者_如何学运维y not possible.
Check out the documentation http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_many. It shows that a has_many association is validated by default when the parent object is saved. You can set it to false like this:
class Post < ActiveRecord::Base
has_many :comments, :validate => false
end
I suppose validates_associated
could come in handy if you aren't validating an association by default and wanted to handle it yourself. The whole situation is a bit confusing, so I hope that this helps.
Your validations enforce the business logic of your application. If you always want the Post object to save, regardless of the state of the associated comments, you can save posts, and comments independently. This would allow you to iterate over a collection of comments, and try to save each on, continuing if there is an error
post = Post.new
post.valid? # true
comments.each do |comment|
comment.save # some will some wont
end
I know this doesn't exactly fix your issue as you have describe it, but it may be good to think about why you want to disable validations on an association. The problem with :validate => false on the has_many call is that it will always save without validation, which may not be what you intend.
Is there a more orthodox way to solve this issue while keeping validations present?
精彩评论