0

How to create form and action for multiple nested attributes if:

LineItem:

has_many :item_options, :dependent => :destroy
has_many :product_options, :through => :item_options

ProductOption:

belongs_to :product
belongs_to :option
has_many :item_options
has_many :line_items, :through => :item_options

ItemOption:

attr_accessible :line_item_id, :product_option_id  
belongs_to :line_item, :foreign_key => "line_item_id"
belongs_to :product_option,:foreign_key => "product_option_id"

When I'm creating new LineItem, I need to create new ItemOption(s). This is my form:

        <%= form_for(LineItem.new) do |f| %>
        <%= f.hidden_field :product_id, value: @product.id %>
        <%= f.fields_for :item_options do |io| %>
            <% @product.options.uniq.each do |o| %>
              <%= o.name %>: 
              <%= io.collection_select :product_option_id, o.product_options.where(:product_id => @product.id), :id, :value %>
            <% end %>
        <%= f.submit %>
        <% end %>

When I'm clicking on Add To Cart, I've get:

ItemOption(#70296453751440) expected, got Array(#70296430421140)

When Adding accepts_nested_attributes_for :item_options to LineItem, my selects not diplayed :(

With

<%= select_tag "product_option_id", options_from_collection_for_select(o.product_options.where(:product_id => @product.id), :id, :value) %>
#item_options not created:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"/WM5/MqPn1yCxjKWoJQmjfko2pR4RiYV0S2KeTTpA3w=", "line_item"=>{"product_id"=>"1"}, "product_option_id"=>"5", "commit"=>"add"}

And last one, I've create action like this:

@line_item = LineItem.new(params[:line_item])
@line_item.item_options.build 
....

Where am I wrong? :( I'm totally confused. ps. similar question Rails 3.2 has_many through form submission This is form:

Community
  • 1
  • 1
Oleg Pasko
  • 2,831
  • 5
  • 35
  • 44

1 Answers1

1

Looks this line:

Parameters: {"utf8"=>"✓", "authenticity_token"=>"/WM5/MqPn1yCxjKWoJQmjfko2pR4RiYV0S2KeTTpA3w=", "line_item"=>{"product_id"=>"1"}, "product_option_id"=>"5", "commit"=>"add"}

The parameter product_option_id is outside line_item hash, and will be inside. Maybe you need write the select like this:

<%= select_tag "line_item[product_option_id]", options_from_collection_for_select(o.product_options.where(:product_id => @product.id), :id, :value) %>

I'm not sure, but maybe is this. Maybe I need more information, like the exact line where is failing.


Extra, the :foreign_key => "line_item_id" and :foreign_key => "product_option_id" are not necesary, because, the belongs_to model name is the same and will use these foreign_key. From api.

Specify the foreign key used for the association. By default this is guessed to be the name of the association with an “_id” suffix. So a class that defines a **belongs_to :person** association will use “person_id” as the default :foreign_key. Similarly, belongs_to :favorite_person, :class_name => "Person" will use a foreign key of “favorite_person_id”.


Edit

Sorry, the unknown attribute: product_option_id is because the attribute name is product_option_ids, and is an array, not a unique value. For a has_many relationship, the column name is collection_singular_ids, and the select should be:

<%= select_tag "line_item[product_option_ids][]", options_from_collection_for_select(o.product_options.where(:product_id => @product.id), :id, :value) %>

This should work, I think :)...

Andrés
  • 624
  • 7
  • 12
  • Tnx, but `unknown attribute: product_option_id` ... In params: `{"utf8"=>"✓", "authenticity_token"=>"ik5ad6KsTOD+b4e9ioenFqfXY1nojXdEGAeNAXlCN8E=", "line_item"=>{"product_id"=>"1", "product_option_id"=>"5"}, "commit"=>"Добавить в корзину"}` – Oleg Pasko Nov 05 '12 at 13:14
  • Maybe it's something like: `<%= select_tag "item_option[product_option_id]", options_from_collection_for_select(o.product_options.where(:product_id => @product.id), :id, :value) %>` But it's only one item_option, even have several in form :( Params: `"line_item"=>{"product_id"=>"1"}, "item_option"=>{"product_option_id"=>"4"}, ` – Oleg Pasko Nov 05 '12 at 14:02
  • This variant is better: `<%= select_tag "item_option[][product_option_id]", options_from_collection_for_select(o.product_options.where(:product_id => @product.id), :id, :value) %>`, than in params: `"line_item"=>{"product_id"=>"1"}, "item_option"=>[{"product_option_id"=>"1"}, {"product_option_id"=>"4"}]`. But still not saving ( – Oleg Pasko Nov 05 '12 at 14:05
  • You have the column in your `attr_accessible`?, like `attr_accessible :product_option_ids` or `attr_accesible :product_option_id`. **Edit**, late :P – Andrés Nov 05 '12 at 14:36