How do you pass an array to an erb template in ruby and have it iterated over?
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!
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 %>
ERB Templates for Dummies
Basic code:
require 'erb'
ERB.new(template).result binding_for_template
What are template
and binding_for_template
?
Template
Just the template content. You can read it from a file just with a File.read(path)
.
Binding for template
A binding
encapsulate the execution context at some particular place in the code and retain this context for future use.
How do you use it? Easy:
def binding_for_my_template
devices = ["eth0", "br0"]
ipaddrs = ["192.168.12.166", "192.168.12.199"]
netmasks = ["255.255.255.0", "255.255.255.0"]
hwaddrs = ['']
networks = ['']
gateways = ["192.168.12.254", "192.168.12.204"]
binding
end
That will return a binding with all six arrays (I changed hwaddr
and network
to arrays for consistency.
Iterating over arrays
The usual way is using the each
method, just like this:
<%- devices.each do |d| %>
auto <%= d %> inet static
<%- end %>
but there are other methods if you wanna put all in one line, for example devices.join ' '
will join all the strings with a space in between.
You should read the docs. Quoting:
# Managed by Class['ntp']
<% servers_real.each do |server| -%>
server <%= server %>
<% end -%>
# ...
This snippet will iterate over each entry in the array and print it after a server statement, so, for example, the string generated from the Debian template will end up with a block like this:
# Managed by Class['ntp']
server 0.debian.pool.ntp.org iburst
server 1.debian.pool.ntp.org iburst
server 2.debian.pool.ntp.org iburst
server 3.debian.pool.ntp.org iburst
精彩评论