Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails ActiveRecord: Skip validations for associations

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.

like image 293
David Phillips Avatar asked Dec 09 '22 12:12

David Phillips


1 Answers

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.

like image 81
Arnaud Avatar answered Dec 27 '22 17:12

Arnaud