Roger
Roger

Reputation: 43

Rails Has Many Forms

I'm having a bit of trouble getting forms for a has_many association to work for a shopping basket. The view is displaying the basket and has a table row for each item. Each row contains a text field so that the user can set the quantity.

The problem is that only the first item row quantity is being passed through in params, even if the second item's quantity has changed too.

Can anyone help please?

Thanks, Roger


The output of params in the debugger is below, only one line_item is being passed through.

(rdb:2624) e params 
{"commit"=>"Recalculate", 
"authenticity_token"=>"7TKnhmbBPFiKLzVqTipzH8PDyCrOnKiFixGQ37XDGNY=", 
"_method"=>"put", "utf8"=>"✓", "action"=>"update", "id"=>"4", 
"line_item"=>{"quantity"=>"3", "id"=>"6"}, "controller"=>"baskets"}

app/controllers/basket_controller.rb

class BasketsController < ApplicationController
  def update  
    begin
      @basket = Basket.find(params[:id])
      # Can't do anything here yet since the correct parameters aren't being passed through.
    rescue ActiveRecord::RecordNotFound
      logger.error "..."
    end

    redirect_to basket_path
  end
end

app/views/baskets/show.html.erb

<%= form_for @basket do |f| %>
<table id="items">
  <thead>
    <tr>
      <th>Name</th>
      <th>Quantity</th>
      <th>Price</th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <% @basket.line_items.each do |item| %>
      <%= form_for item do |g| %>
      <tr class="<%= cycle('alternate', '') %>">
        <td><%= item.product.name %></td>
        <td>
          <span class="decrement-quantity"><b>-</b></span>
          <%= g.text_field :quantity %>
          <span class="increment-quantity"><b>+</b></span>
        </td>
        <td class="price"><%= number_to_currency(item.total_price) %></td>
      </tr>
      <% end %>
    <% end %>
      <tr class="totals">
        <td>Total</td>
        <td><%= @basket.total_quantity %></td>
        <td class="price"><%= number_to_currency(@basket.total_price) %></td>
        <td></td>
      </tr>
  </tbody>
</table>
<%= f.submit 'Recalculate' %>
<% end %>

Upvotes: 2

Views: 1833

Answers (2)

ardavis
ardavis

Reputation: 9895

I would checkout Railscasts: Complex Forms Part 1. After you watch that, you may be interested in watching Parts 2 & 3.

Ryan Bates covers using fields_for in an understandable and easy to learn fashion.

Upvotes: 2

smathy
smathy

Reputation: 27971

You're just creating a new form within the other form. Rails doesn't do anything magical just because you nest one form within another - which is what's causing the issue you're seeing.

The way to handle this situation is to use the fields_for helper and nested_attributes_for - see NestedAttributes for more information too.

Upvotes: 2

Related Questions