Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

jquery - Rails 3.2 has_many through form submission

I have a has_many :through form where I can't get an extra attribute to post to the database. I'm fouling up the parameter name somewhere. I can get the foreign keys to post but I have another attribute that I'm trying to track in the join table. Keep in mind this is a 100% ajax based form. Here's what I know

Edit: After researching similar issues, I understand I'm supposed to build the form attributes, but the code I've found doesn't work for some reason. Here are some resources.

http://railsforum.com/viewtopic.php?id=20203

Rails 3, nested multi-level forms and has_many through

What I don't understand is that attaching the product_ids is built into rails. Those values post. Why is it hard to attach the quantity_shipped attribute to that array?

Models and Relationships
  Shipment  has_many :products :through => :product_shipments
  Product   has_many :shipments :through => :product_shipments
  ProductShipments belongs_to :shipment,  belongs_to :product

ProductShipments table
  t.integer    :shipment_id  
  t.integer    :product_id
  t.integer    :qty_shipped  <-- This is the Problem Child

This partial is looped through a few times displaying all the products from a certain vendor. It generates an array for the product_ids and another for the product_shipments quantities.

_product_shipments.html.erb.

<div id="product_shipments_container">
<h3>Assign Products to Ship</h3>
<ul class="product_shipments" id="product_shipments">
  <% Product.by_client(@client_id).each do |product| %>
    <%= content_tag_for :li, product, :value => product.id do %>
      <%= hidden_field_tag("shipment[product_ids][]", product.id) %>
      <%= product.product_name %><%= text_field_tag("product_shipments[qty_shipped]")%> <--This is where the issue lies
    <% end %>
  <% end %>
</ul>
</div>

This is the relevant POST data when the form is submitted

"product_ids"=>["1", "3"]}, "product_shipments"=>{"qty_shipped"=>["32", "23"]}

This is sql that is sent to the database

INSERT INTO `product_shipments` (`product_id`, `qty_shipped`, `shipment_id`) 
VALUES (1, NULL, 155)
INSERT INTO `product_shipments` (`product_id`, `qty_shipped`, `shipment_id`)
VALUES (3, NULL, 155)

Here is the action in my controller

def create
 @shipment = Shipment.new(params[:shipment])

 @product_shipments = @shipment.product_shipments.build(params[:product_shipments])

[:qty_shipped]) <- not correct, but it's what i got so far if @shipment.save respond_with @shipment, :location => shipments_url else flash[:notice]= "Not saved" end end

Here's the last issue I'm having.

TypeError (can't convert Symbol into Integer):
  app/controllers/shipments_controller.rb:24:in `[]'
  app/controllers/shipments_controller.rb:24:in `create'

GOT IT. After making the changes with the correct answer below. I was able to correct the controller to the following

@product_shipments = @shipment.product_shipments.build(params[:product_shipments])
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Your 'create' action can be as simple as

def create
  @shipment = Shipment.new(params[:shipment])

  if @shipment.save
    # success
  else
    # failure
  end
end

if you use nested attributes to create shipment_products through the new shipment record. To do this, add the following to the Shipment model

class Shipment
  attr_accessible :shipment_products_attributes
  accepts_nested_attributes_for :shipment_products
end

By using fields_for in the view, this will allow a shipment to accept params[:shipment][:shipment_products_attributes] and pass these on to its shipment_products.

In your new action, you could do something like

def new
  @shipment = Shipment.new
  # collect the ids of the products you want to create shipment products for
  @shipment.shipment_products.build([{:product_id=> ...},{:product_id=> ...}, ...])
end

so that in the form you could do something like

<%= form_for @shipment, :remote => true do |f|%>
  ...
  ...
  <ul>
    <%= f.fields_for :shipment_products do |sp_f| %>
      <li>
        <%= sp_f.text_field :qty_shipped %>
        <%= sp_f.hidden_field :product_id %>
      </li>
    <% end %>
  </ul>
<% end %>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...