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!