Rails bug: accepts_nested_attributes_for is not updating my has_many association

て烟熏妆下的殇ゞ 提交于 2019-12-23 21:01:37

问题


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.


回答1:


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


来源:https://stackoverflow.com/questions/21634107/rails-bug-accepts-nested-attributes-for-is-not-updating-my-has-many-association

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!