Question: Two levels of nested attributes and strong parameters

Question

Two levels of nested attributes and strong parameters

Answers 0
Added at 2016-12-30 12:12
Tags
Question

I've ported a Rails app from Rails 3 to Rails 4 and most things work now, except for a problem with two levels of nested attributes:

  • I have ProductGroups, Variants and Prices.
  • Each ProductGroup has one or more variants. One of them is the master variant.
  • Each variant has many prices (one for each region).

I have a controller that updates ProductGroups. When the ProductGroup is updated, the master variant is updated at the same time. And prices in the master variant are also updated.

Here's a test that describes what's expected to happend:

test "should update master variant" do
    login_as accounts(:johnny_admin)

    p = ProductGroup.find product_groups(:toothbrush).id
    assert_equal "10123", p.artno
    assert_equal "10123", p.master_variant.artno

    puts(p.master_variant.prices.to_a.to_s)

    post :update,
         id: product_groups(:toothbrush),
         p: 'setup',
         product_group: {
           master_variant_attributes: {
             artno: "20222",
             supplier_artno: "1010",
             prices_attributes: { "0": { price: "55", id: prices(:toothbrush_price_se).id } }
           }
         }

  assert_response :redirect
  assert_redirected_to edit_admin_product_group_path(p, :p => 'setup')

  p = ProductGroup.find product_groups(:toothbrush).id
  assert_equal "20222", p.artno
  assert_equal "20222", p.master_variant.artno
  assert_equal "1010", p.master_variant.supplier_artno

  price = Prices.find prices(:toothbrush_price_se).id
  assert_equal 55, price.price
end

But it fails with this error:

# Running:

.......[#<Price id: 510149407, variant_id: 630858089, region_id: 102782309, price: #<BigDecimal:55d2732f50a8,'0.95E2',9(18)>, created_at: "2016-12-30 11:14:28", updated_at: "2016-12-30 11:14:28">, #<Price id: 524805804, variant_id: 630858089, region_id: 960235695, price: #<BigDecimal:55d27339c510,'0.1E2',9(18)>, created_at: "2016-12-30 11:14:28", updated_at: "2016-12-30 11:14:28">]
E

Finished in 1.279989s, 6.2501 runs/s, 20.3127 assertions/s.

  1) Error:
Admin::ProductGroupsControllerTest#test_should_update_master_variant:
ActiveRecord::RecordNotFound: Couldn't find Price with ID=510149407 for Variant with ID=
    app/controllers/admin/product_groups_controller.rb:150:in `update'
    test/functional/admin/product_groups_controller_test.rb:103:in `block in <class:ProductGroupsControllerTest>'

As you can see in the debug output, there is a price with ID 510149407 for that variant. And why is the ID of the variant empty?

I'm totally stuck.

Here's the permits for ProductGroup that I'm using:

  def product_group_params
    prices_attributes = { :prices_attributes => [ :id, :price ] }
    master_variant_attributes = { :master_variant_attributes => [
      :unit, :vat, :artno, :width, :height, :depth,
      :description, :in_stock, :in_stock_verified_at,
      :status, :supplier_id, :supplier_artno,
      :alt_supplier_id, :alt_supplier_artno,
      :supplier_price, :alt_supplier_price,
      :supplier_reduction, :alt_supplier_reduction,
      :supplier_carriage_percentage, :alt_supplier_carriage_percentage,
      :our_expenses, :percentage_markup, :taric_code_id,
      :reduction_group_id, :vendor_id, :vendor_artno, :is_expired,
      :show_price, :reorder_point,
      :place_of_storage_a, :place_of_storage_b, :place_of_storage_c,
      prices_attributes
    ] }

    params.require(:product_group).permit(:updated_by,
                                          :title, :description, :license_code, :fixme,
                                          master_variant_attributes,
                                          :notes, :vat, :artno, :unit,
                                          :width, :height, :depth, :in_stock, :published, :reorder_point,
                                          :current_version, :changelog, :price_by_start_cost_and_per_unit,
                                          :start_cost_variant_id, :unit_cost_variant_id,
                                          :category_ids => [])
  end

Here's how ProductGroup relates to the master variant:

  has_one :master_variant,
          -> { where(is_master: true, deleted_at: nil) },
          :class_name => "Variant",
          :foreign_key => 'product_group_id',
          :dependent => :destroy,
          :autosave => true
  accepts_nested_attributes_for :master_variant

Here's how Variant relates to Prices:

  has_many :prices, -> { order('region_id') }, :dependent => :destroy
  accepts_nested_attributes_for :prices

I will gladly post any other excerpts from the code if it is of any help, but I'm not sure what could be of interest right now.

Any hints would be much appreciated!

Answers to

Two levels of nested attributes and strong parameters

Source Show
◀ Wstecz