I have 2 models:
class Book < ActiveRecord::Base
has_many :book_versions
accepts_nested_attributes_for :book_versions, allow_destroy: true
validates_associated :book_versions
class BookVersion < ActiveRecord::Base
has_many :collection_items
has_many :collections, through: :collection_items
belongs_to :book
validates_presence_of :price, :isbn #<-- validates presence
Here are my params. Notice how I leave the price of book_version with name bb blank. This should be firing off the validates_presence_of :price validation in the BookVersion model (but it doesn't):
"book"=>{"title"=>"zzzzzz", "subtitle"=>"", "author_ids"=>[""], "illustrator_ids"=>[""], "award_ids"=>[""], "theme_ids"=>[""], "publication_date"=>"", "imprint_id"=>"1", "language_ids"=>[""], "eng_vers_id"=>"", "book_versions_attributes"=>{"0"=>{"book_id"=>"2848", "name"=>"alt", "isbn"=>"", "price"=>"", "famis_number"=>"", "famis_price"=>"", "weight_in_pounds"=>""}, "1"=>{"book_id"=>"2848", "name"=>"bb", "isbn"=>"123123123123", "price"=>"", "famis_number"=>"", "famis_price"=>"", "weight_in_pounds"=>"1.0", "inventory"=>"08", "id"=>"1030"},
When I do @book.update_attributes(params[:book]) in my controller, none of the book_versions update even though everything seems valid:
>> @book.update_attributes(params[:book])
=> true
>> @book.book_versions
=> [#<BookVersion id: 1030, book_id: 2848, name: "bb", isbn: "123123123123", inventory: "08", price: #<BigDecimal:7fc484885b80,'0.1122E2',18(18)>, famis_price: nil, famis_number: "", weight_in_pounds: #<BigDecimal:7fc4848861c0,'0.1E1',9(18)>, width: nil, height: nil, thickness: nil>, #<BookVersion id: 1031, book_id: 2848, name: "lb", isbn: "12312333333", inventory: "02", price: #<BigDecimal:7fc484886670,'0.2244E2',18(18)>, famis_price: nil, famis_number: "", weight_in_pounds: #<BigDecimal:7fc484886760,'0.1E1',9(18)>, width: nil, height: nil, thickness: nil>, #<BookVersion id: 1032, book_id: 2848, name: "hc", isbn: "111213213131", inventory: nil, price: #<BigDecimal:7fc4848869e0,'0.1212E4',9(18)>, famis_price: nil, famis_number: "", weight_in_pounds: #<BigDecimal:7fc484886d28,'0.1E1',9(18)>, width: nil, height: nil, thickness: nil>]
>> @book.book_versions.map(&:price)
=> [#<BigDecimal:7fc484885b80,'0.1122E2',18(18)>, #<BigDecimal:7fc484886670,'0.2244E2',18(18)>, #<BigDecimal:7fc4848869e0,'0.1212E4',9(18)>]
>> @book.book_versions.map(&:price).map(&:to_f)
=> [11.22, 22.44, 1212.0]
>> @book.save
=> true
>> @book.book_versions.map(&:price).map(&:to_f)
=> [11.22, 22.44, 1212.0] #<-- one of these should be `nil`.
What's going on? The form works perfectly fine when I am creating a Book with many BookVersions. However, it does not update or validate anything when I'm updating an existing book with existing book versions.
This is a continuation of my question here: ActiveRecord: validates_associated does not work when updating model?
UPDATE ====
Uh... I think it's a bug in rails? Look at what happens:
>> @book.update_attributes(params[:book])
=> true
>> @book.book_versions
=> [#<BookVersion id: 1030, book_id: 2848, name: "bb", isbn: "123123123123", inventory: "08", price: #<BigDecimal:7fc487ee9488,'0.1122E2',18(18)>, famis_price: nil, famis_number: "", weight_in_pounds: #<BigDecimal:7fc487ee9118,'0.1E1',9(18)>, width: nil, height: nil, thickness: nil>, #<BookVersion id: 1031, book_id: 2848, name: "lb", isbn: "12312333333", inventory: "02", price: #<BigDecimal:7fc487ee8f88,'0.2244E2',18(18)>, famis_price: nil, famis_number: "", weight_in_pounds: #<BigDecimal:7fc487ee8e98,'0.1E1',9(18)>, width: nil, height: nil, thickness: nil>, #<BookVersion id: 1032, book_id: 2848, name: "hc", isbn: "111213213131", inventory: nil, price: #<BigDecimal:7fc487ee8b50,'0.1212E4',9(18)>, famis_price: nil, famis_number: "", weight_in_pounds: #<BigDecimal:7fc487ee89c0,'0.1E1',9(18)>, width: nil, height: nil, thickness: nil>]
>> @book.update_attributes(params[:book])
=> false
But that is only when I use better errors and freeze the controller before update_attributes. When I actually put @book.book_versions in the controller right before I update the attributes and try running it, it still doesn't work.
So I figured it out with some hackery... For some reason you have to load them in memory first. In order to do this you have to perform some sort of function on the array of book versions. just calling book.book_versions is not enough:
@book.book_versions.sort_by(&:name) # this line is to load the book_versions, without it book_versions will not update!! it's a bug in rails I discovered
if @book.update_attributes(params[:book]) #<-- returns false finally
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With