I'm new on a project and trying to add a feature to a system that already has a bunch of moving parts, most of which I don't believe are at all related to the functionality I'm trying to add.
I want to add fields to an ActiveAdmin/Formtastic form to allow users to create and update pricing schemes associated with products. Each product has one pricing scheme which can have many pricing tiers.
The fields show up on the form, but when I update the product object, the fee and max attributes in the pricing tier object aren't saved to the database
The ActiveAdmin form has a variable, pricing_scheme_object, which I created based off of this Stack Overflow Answer. The ActiveAdmin form looks like:
ActiveAdmin.register Product do
actions :all, except: [:destroy]
# menu parent, filters, and scopes, none of which are related
form html: {multipart: true} do |f|
f.inputs "Product" do
# unrelated code
pricing_scheme_object = [:pricing_scheme, f.object.pricing_scheme ||
PricingScheme.new]
f.inputs "Pricing Schemes", :for => pricing_scheme_object do |scheme|
scheme.has_many :pricing_tiers do |tier|
tier.input :fee, input_html: { class: 'pricing_scheme_column'}, size: 5
tier.input :max, input_html: { class: 'pricing_scheme_column'}, size: 5
end
end
# unrelated code
end
f.actions
end
# unrelated code
end
When I save a product I see the following on the server:
Started PUT "/admin/products/139" for 127.0.0.1 at 2013-03-20 12:50:43 -0700
Processing by Admin::ProductsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"FzyjTkrTF0LvB1K02kebSgqDQWad8c5/bpbIEhFgQpY=", "product"=>{"three_letter_acronym_id"=>"64", "name"=>"test pdf", "description"=>"<p>this is the pdf </p><div class=\"vimiumReset vimiumHUD\" style=\"right: 150px; opacity: 0; display: none; \"></div>", "status"=>"published", "way"=>"pdf", "custom_path"=>"", "pricing_scheme"=>{"pricing_tiers_attributes"=>{"1363809038085"=>{"fee"=>"30", "max"=>"10"}}}, "allocation_rule_number"=>"", "fulfillment_email"=>"", "fulfillment_username"=>"", "fulfillment_password"=>"[FILTERED]", "fulfillment_url"=>"", "shared_secret"=>"", "api_key"=>"", "callback_url"=>""}, "commit"=>"Update Product", "id"=>"139"}
Product Load (0.4ms) SELECT `products`.* FROM `products` WHERE `products`.`id` = 139 LIMIT 1
WARNING: Can't mass-assign protected attributes: pricing_scheme
(0.1ms) BEGIN
[paperclip] Saving attachments.
(0.1ms) COMMIT
Redirected to http://localhost:3000/admin/products/139
Completed 302 Found in 119ms (ActiveRecord: 0.0ms)
Started GET "/admin/products/139" for 127.0.0.1 at 2013-03-20 12:50:43 -0700
Processing by Admin::ProductsController#show as HTML
Parameters: {"id"=>"139"}
Product Load (0.3ms) SELECT `products`.* FROM `products` WHERE `products`.`id` = 139 LIMIT 1
ThreeLetterAcronym Load (0.4ms) SELECT `three_letter_acronym`.* FROM `three_letter_acronym` WHERE `three_letter_acronym`.`id` = 64 LIMIT 1
Rendered /Users/strand/.rvm/gems/ruby-1.9.3-p392/bundler/gems/active_admin-c3be25319bb6/app/views/active_admin/resource/show.html.arb (27.3ms)
Completed 200 OK in 144ms (Views: 29.0ms | ActiveRecord: 0.6ms)
The product looks like this:
# app/models/product.rb
class Product < ActiveRecord::Base
# … (probably unrelated code)
has_one :pricing_scheme, dependent: :destroy
accepts_nested_attributes_for :pricing_scheme, allow_destroy: true, reject_if: lambda { |a| a[:price].blank? }
# …
attr_accessible :unrelated_attributes,
:pricing_scheme_attributes,
:pricing_scheme_id
# …
end
The pricing scheme model is:
# app/models/pricing_scheme.rb
class PricingScheme < ActiveRecord::Base
attr_accessible :display_order, :label, :product_id, :max_quantity,
:min_quantity, :price, :category, :pricing_tiers_attributes
has_many :pricing_tiers
belongs_to :product
accepts_nested_attributes_for :pricing_tiers, :allow_destroy => true
def price_for(number)
# logic to determine the price for a number of products based on the pricing
# tiers associated with the pricing scheme.
end
end
The pricing tier looks like:
# app/models/pricing_tier.rb
class PricingTier < ActiveRecord::Base
attr_accessible :fee, :max, :base, :pricing_scheme_id
belongs_to :pricing_scheme
end
When I save the product, I would like to update or create the pricing scheme and any pricing tiers which are associated with it.
How do I do this?