Wes Wes -4 years ago 144
Ruby Question

Rails - Iterate Through Params

I have a params which I pass that looks like this:

{"utf8"=>"✓",
"authenticity_token"=>"xx==",
"item_0"=>{"0"=>["address_1"], "1"=>["model 1"], "2"=>["ABC"], "3"=>["Off"], "4"=>["Status"]},
"item_1"=>{"0"=>["address_2"], "1"=>["model 1"], "2"=>["DEF"], "3"=>["On"], "4"=>["Status"]},
"item_2"=>{"0"=>["address_3"], "1"=>["model 1"], "2"=>["GHI"], "3"=>["On"], "4"=>["Status"]}}


How do I iterate over this param to get the values of each item? I know I can grab each item individually, but when submitting dynamic form data, I won't know the exact number of items that are in the params. How can I get around that problem?

Answer Source

To keep only keys that you want, you could use Hash#keep_if to do something like this:

hsh = {"utf8"=>"✓",
       "authenticity_token"=>"xx==",
       "item_0"=>{"0"=>["address_1"], "1"=>["model 1"], "2"=>["ABC"], "3"=>["Off"], "4"=>["Status"]},
       "item_1"=>{"0"=>["address_2"], "1"=>["model 1"], "2"=>["DEF"], "3"=>["On"], "4"=>["Status"]},
       "item_2"=>{"0"=>["address_3"], "1"=>["model 1"], "2"=>["GHI"], "3"=>["On"], "4"=>["Status"]}}

hsh.keep_if {|k, v| k=~ /item_/ }

and that would return:

{"item_0"=>{"0"=>["address_1"], "1"=>["model 1"], "2"=>["ABC"], "3"=>["Off"], "4"=>["Status"]}, 
"item_1"=>{"0"=>["address_2"], "1"=>["model 1"], "2"=>["DEF"], "3"=>["On"], "4"=>["Status"]},
"item_2"=>{"0"=>["address_3"], "1"=>["model 1"], "2"=>["GHI"], "3"=>["On"], "4"=>["Status"]}}

You can loop through a Hash with each_pair. Each pair takes to arguments e.g. |k, v| representing the key/value pair. From there you can do as you'd like with the hash. Since your hash is nested, I drew up this example:

hsh = {"item_0"=>{"0"=>["address_1"], "1"=>["model 1"], "2"=>["ABC"],"3"=>["Off"], "4"=>["Status"]},
       "item_1"=>{"0"=>["address_2"], "1"=>["model 1"], "2"=>["DEF"], "3"=>["On"], "4"=>["Status"]},
       "item_2"=>{"0"=>["address_3"], "1"=>["model 1"], "2"=>["GHI"], "3"=>["On"], "4"=>["Status"]}}

> hsh.each_pair {|k, v| v.each_pair {|j, w| puts w } }
address_1
model 1
ABC
Off
Status
address_2
model 1
DEF
On
Status
address_3
model 1
GHI
On
Status

Here's a link to the docs for Hash#each_pair.

There's a number of methods to loop through hashes. For example, each_key and each_value, which work pretty much as named.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download