0

I'm pretty close on this one but caught up on a minor detail. I am trying to update a has_many :through relationship. When I submit the edit form I am unable to extract the appropriate attribute that I want to update. The loop that updates the qty shipped is not updated that field with the correct value. How can I extract only the qty_shipped attribute from the params[:product_shipments] hash?

This is the contents of my params[:product_shipments] hash that the update action is working with

"product_shipments"=> {"82"=>{"qty_shipped"=>"234"},
                       "83"=>{"qty_shipped"=>"324"},
                       "84"=>{"qty_shipped"=>"324"}}, 
                       "commit"=>"Update Shipment", "id"=>"250"}

Which has all the information I need to update the shipment because the @shipment.product_shipments loop limit the update to only the shipment_id applicable. My problem is that this is the following sql called by update action

ProductShipment Load (0.3ms)  SELECT `product_shipments`.* FROM `product_shipments` WHERE `product_shipments`.`shipment_id` = 250
BEGIN
UPDATE `product_shipments` SET `qty_shipped` = 1 WHERE `product_shipments`.`id` = 82
COMMIT
BEGIN
UPDATE `product_shipments` SET `qty_shipped` = 1 WHERE `product_shipments`.`id` = 83
COMMIT
BEGIN
UPDATE `product_shipments` SET `qty_shipped` = 1 WHERE `product_shipments`.`id` = 84
COMMIT

And here is the update action that produces the above sql:

def update
  @shipment = Shipment.find(params[:id])
  @shipment.update_attributes(params[:shipment])

  @shipment.product_shipments.each do |shipment|
    shipment.update_attributes(:qty_shipped=> params[:product_shipments])
  end

  respond_with @shipment, :location => shipments_url
end

Using rbates nested_forms gem is not preferred because I want to figure this out for the purposes of learning how rails works.

<%= hidden_field_tag("product_shipments[][#{product_shipment.id}]") %>
<%= hidden_field_tag("product_shipments[][product_id]", product_shipment.id) %>
<%= text_field_tag "product_shipments[][qty_shipped]", product_shipment.qty_shipped,:class => 'shipment_qty_field'%>&nbsp<%=@product.product_name %>
ctilley79
  • 2,151
  • 3
  • 31
  • 64

1 Answers1

1
@shipment.product_shipments.each do |product_shipment|
   product_shipment.update_attributes(:qty_shipped => params[:product_shipments][product_shipment.id][:qty_shipped])
end

You shouldn't have to do all this, just use Nested Forms. This is Rails!

http://railscasts.com/episodes/196-nested-model-form-part-1

Your params should look like this

{:product_shipments => { 79 => { :qty_shipped => 450 }, 80 => { :qty_shipped => 35 } }, :shipment_id => 1 }

To get that you should name your fields like this

<input name="product_shipments[79][qty_shipped]" value="450" />
<input name="product_shipments[80][qty_shipped]" value="35" />

To generate that,

<% @shipment.product_shipments.each do |product_shipment| %>
  <%= text_field_tag "product_shipments[#{product_shipment.id}][qty_shipped]", product_shipment.qty_shipped || 0 %>
<% end %>
SMathew
  • 3,993
  • 1
  • 18
  • 10
  • getting the following: NoMethodError (undefined method `[]' for nil:NilClass): – ctilley79 Jul 05 '12 at 18:43
  • You should setup the fields and their names in the form to account for this. `form_for @shipment do |f| @shipment.product_shipments.each do |product_shipment| text_field_tag "product_shipments[#{product_shipment.id}][qty_shipped]", product_shipment.qty_shipped end end` All of this is automatically taken care of when you use nested forms in rails. – SMathew Jul 05 '12 at 18:56
  • Using Ryan's gem is not an option. I've edited the question to include the contents of the params hash as well as some analysis of what I've discovered. It seems that passing the shipment_id is unneccesary because that's what shipment.update_attributes already includes. I've tried it without that but still get the same error as my first comment. – ctilley79 Jul 05 '12 at 23:02
  • It's not the shipment.id that's used. it's the product_shipment.id, I will edit the answer in a moment so it's not confusing. You do need this id in the fields so you can determine which value goes to which product_shipment even though all product_shipments belong to shipment. – SMathew Jul 05 '12 at 23:13
  • NoMethodError (undefined method `[]' for nil:NilClass – ctilley79 Jul 05 '12 at 23:32
  • can i see what the params look like now? Copy and paste this exactly as you see in your log file – SMathew Jul 05 '12 at 23:35
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/13491/discussion-between-smathew-and-ctilley79) – SMathew Jul 05 '12 at 23:39
  • Ok. take one last look as I think we're close. I edited what I was able to achieve with the post parameters. It seems structured exactly as you have shown. seem to still be getting a null value for qty_shipped when the update_attributes line is reached in the controller. – ctilley79 Jul 06 '12 at 01:08
  • Ok, I am sorry, missed a little detail `params[:product_shipments][product_shipment.id.to_s][:qty_shipped]` the id should be a string – SMathew Jul 06 '12 at 01:34
  • `"product_shipments[][#{product_shipment.id}]"` if you do that, `[]` it will become an array and you won't know which value belongs to which product_shipment – SMathew Jul 06 '12 at 01:39