How do I pass a hash with hidden_field or hidden_field_tag

Here's what I have in my view:

<% form_tag( :action => :update_cart ) do %>   <% for item in @cart.items %>     <p>       <%= hidden_field(:items, item.id =>item.quantity ) %>       <%=h item.name %>       <%= text_field_tag( :updated_quantity, item.quantity, :size => 1 ) %>       <%=h item.price %>     </p>   <%end %>   <%= submit_tag( "Update" ) %> <% end %>

This is part of the params hash this code has created: Parameters: {"items"=>{"727"=>"", "5131"=>"", "642"=>""}}

It is concatenating item.id and item.quantity into the keys of the hash instead of one being the key and the other being the value. I want to produce a hash called "items" that has a key value pairs that look like this. Parameters: {"items"=>{"72"=>"7", "51"=>"31", "64"=>"2"}}

In my :update_cart action I need to access this hash so I can get the quantity of each item by referencing it's id in the hash.

Thanks!

You may want to store that info in the session hash instead of hidden in the form.

You need to generate inputs like: <input name='items[72]' value='7'> <input name='items[51]' value='31'>

Either just generate the HTML, eiter use the helper: <%= text_field "items", item.id, :value =>ite.quantity %>

Dmitry

Thanks for the help guys. That put me in the right direction.

As I have read hashes don't guarantee that the key value pairs will be the same every time. Is this correct?

This is blowing up what I'm trying to do. The keys in my params hash that my form is sending out has a different value each time. It's like the values are playing musical chairs with their associates keys.

Here's the part of my params hash I'm speaking of: The nested keys are the ids of objects in a shopping cart and the values are each one's quantity. {"items"=>{"72"=>"1", "51"=>"0", "62"=>"0", "64"=>"1"}

What's the fix for this?

Thanks

You will got back exactly the same thing you've generated (unless you've messed it with javascript)

So if you generate: <input name='items[72]' value='7'> <input name='items[51]' value='31'>

Then you should always get: {"items"=>{"72"=>"7", "51"=>"31"}. So check if you've generated the right html.

Dmitry

Hi Dmitry.

Here's the form that generated the params hash I'm having issues with.

<% form_tag(:action => :update_cart) do %>     <% for item in @cart.items %>      <p>        <%=h item.name %>        <%= text_field "items", item.id, :value =>item.quantity, :size => 1 %>        Price: <%=h item.price %>        Total Price:<%=h item.price * item.quantity%>      </p>     <%end %>     <%= submit_tag( "Update" ) %>    <% end %>

Thanks for the help!

Yep, that should work, or you want to say that if you enter some value into the textbox (eg 10) for the item 71 you've got something different from 5 on the server?

Each time I submit the form each key will have a different value. NOTE: I am not entering new content into the text fields, simply resubmitting what's already there. The values just get randomly reassigned to different keys each time. The order of the Keys never change though.

Here's what my log is showing me after clicking submit three times: It's even worse with more items in the cart. Parameters: {"items"=>{"72"=>"3", "51"=>"2", "64"=>"1"}} Parameters: {"items"=>{"72"=>"3", "51"=>"1", "64"=>"2"}} Parameters: {"items"=>{"72"=>"3", "51"=>"2", "64"=>"1"}}

Thanks!

Are you sure your /page/ is being consistently generated? Have you used 'view source' to confirm the values in the form are as you think they should be, each time?

If so, perhaps post the relevant part of the form markup.

Yep, post the relevant generated HTML.

Here's the relevant html:

Thanks for the help guys.

<table class="center">

  <form action="/stores/51/update_cart" method="post"><div style="margin:0;padding:0"><input name="authenticity_token" type="hidden" value="XXX" /></div>

   <tr>       <td width=350>Chrome Watch</td>       <td width=55><input id="items_72" name="items[72]" size="1" type="text" value="3" /></td>       <td width=55>Price: 255</td>       <td width=100>Total Price:765</td>   </tr>   <tr>       <td width=350>Bling band Watch</td>       <td width=55><input id="items_64" name="items[64]" size="1" type="text" value="2" /></td>       <td width=55>Price: 200</td>       <td width=100>Total Price:400</td>   </tr>   <tr>       <td width=350>Augustus Cuff Watch</td>       <td width=55><input id="items_51" name="items[51]" size="1" type="text" value="1" /></td>       <td width=55>Price: 150</td>       <td width=100>Total Price:150</td>   </tr> </table

<table class="center">

this table tag should be inside the form tag, but that's unlikely to cause this problem. And of course you should quote all attribute values, and validate your markup to be on the safe side.

Other than that, I don't see any reason for this to be unreliable on submission, unless there's some JavaScript tweaking it on the fly.

But I'm still wondering if it's getting generated identically each time.

Oh, and what client/browser are you using when you see these errors? Are you sure you're not throwing JS errors? Hopefully you're using Firefox with Firebug installed...

And after you submit it you will get {"items"=>{"72"=>"3", "51"=>"2", "64"=>"1"}}. It's just impossible to get anything else there :slight_smile:

If you are getting something else look at the HTML again, and check what values were there. Considering the code you've posted either item.quantity is a non-deterministic method, either there is some stupid bug somewhere.

Thanks guys.

I think I see where the problem is now.

Inside the update_cart action I have a loop that is running through params[:items] and assigning the values to multiple @cart.item properies. Apparently my looping construct is reorganizing the info in a way other than the params[:items] specified. Once the loop is ran it re-renders the update_cart.html.erb view that sent params[:items] out in the first place with the newly modified @cart.item values.

Woops. I should have picked up on that before.

Maybe you guys have some thoughts on how to fix my "sloppy" loop construct below?

def update_cart i = 0 @cart = find_cart # A Session based Cart instance   params[:items].each do |k, v|     @cart.items[i].quantity = "#{v}".to_i     i += 1   end end

Thanks again!

without seeing the rest of the cart code, this is just a guess, but shouldn't @cart.items[i].quantity = "#{v}".to_i be @cart.items[k].quantity = "#{v}".to_i

FWIW,

Thanks for all the help guys!

This ended up being the working loop construct that solved the issue.

  def update_cart       @cart = find_cart       # Loop thru the existing cart_item instances and assign the new incoming       # quantity to each one based on the params hash.       @cart.items.each do |item|         item_quantity = params[:items]["#{item.id}"].to_i         if item_quantity == 0           @cart.items.delete(item)         else           item.quantity = item_quantity         end       end       redirect_to :action => "index_cart"     end