Oleg Pasko
Oleg Pasko

Reputation: 2911

Rails 3.2: multiple nested data from one model

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:

Upvotes: 0

Views: 129

Answers (1)

Andr&#233;s
Andr&#233;s

Reputation: 624

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 :)...

Upvotes: 1

Related Questions