Rails ActiveRecord: Skip validations for associations

activerecord, associations, ruby-on-rails, ruby-on-rails-3, validation

Solution

Try that

class Author < ActiveRecord::Base
  has_many :books, :validate => false
  validates_presence_of :email
  after_save :save_invalid_books

  def save_invalid_books
    books.each do |b|
      b.save(false)
    end
  end
end

As far as I understand, the validate => false only allows you to save author without being stopped by an invalid book, but to save the association you need a valid book as you will change the author_id key. You can't change rails internals, but you can still trick it, by saving the author without validation, and then updating each book and forcing save (with save(false)) right after.

Of course this code can be enhanced in many ways, as it's probably not necessary to save all books each time for a start, but you get the idea.

Problem

I'm re-asking this question because the code and example is wrong (it actually works in the case shown). Given these models: ``` class Author < ActiveRecord::Base has_many :books validates_presence_of :email end class Book < ActiveRecord::Base belongs_to :author validates_presence_of :title end ``` We can skip validations when creating a Book: ``` b = Book.new b.save(:validate => false) ``` But if we retrieve the invalid Book from the database and assign it to the association in Author, we aren't allowed to save Author: ``` a = Author.new a.email = "foo" a.books = Book.all a.save! ``` This is the error: ActiveRecord::RecordInvalid: Validation failed: Books is invalid How do we skip validations for the associated Book models without skipping them for Author? Note that saying `has_many :books, :validate => false` in Author doesn't help: the association is silently discarded with the Author is saved.

Original source