How do you pass an array to an erb template in ruby and have it iterated over?

matt picture matt · Aug 16, 2011 · Viewed 37.1k times · Source

I need some help with erb templates, I can't seem to get my head around passing an array and then iterating over it. My problem is this. I want to pass a few arrays: `

device      => ["eth0", "br0"],
ipaddr      => ["192.168.12.166", "192.168.12.199"],
netmask     => ["255.255.255.0", "255.255.255.0"], 
hwaddr      => '',
network     => '',
gateway     => ["192.168.12.254", "192.168.12.204"],                                                                                                                

To a template that iterates over each item in the array and prints it out:

auto <%= device %> inet static                                                                                                                                        
address <%= ipaddr %>
netmask <%= netmask %>
broadcast <%= broadcast %>
gateway <%= gateway %>

As far as I can get so far is figuring out that I need to do something with device.each |device| puts device, but I don't know what the syntax is supposed to look like. I believe you can tell what I'm trying to do from these snippets, and then you might understand that the entries need to be seperate, and not interpolated. Any help you can offer would be appreciated. I know I should be trying things out in irb and figuring them out from there, which is what I'm reading up on now.

Thanks!

Answer

nocache picture nocache · Aug 16, 2011

the basic syntax for using each in ruby is something like this:

array.each do |item_from_array| BLOCK

so if you only had one array then you could just do something like this: (I would use a different name inside the vertical bars for clarity)

<% device.each do |dev| %>
  auto <%= dev %> inet static
<% end %>

However that would iterate over all of your devices first, before moving on to your ipaddr array. I'm guessing you want them each in turn auto, address, netmask, etc. In that case you'd be better off using a more 'traditional' index and looping through N times, like this:

<% for idx in (0..1) %>
  auto <%= device[idx] %> inet static
  address <%= address[idx] %>
  netmask <%= netmask[idx] %>
  broadcast <%= broadcast[idx] %>
<% end %>

Of course you need to think about what your maximum size of array is, and what to do if an array contains less entries than the others. You can find the maximum size of all the arrays by doing something like this: [device,address,netmask,broadcast].map{|a| a.length}.max

and you can skip over a particular array like this: <% if idx < address.length %> address <%= address[idx] %><% end %>