如何在Ruby中将数组传递到erb模板并进行迭代?

16

我需要一些有关erb模板的帮助,我似乎无法理解如何传递一个数组并遍历它。 我的问题是这样的。 我想传递几个数组:

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"],                                                                                                                

对于一个模板,它会迭代数组中的每个项目并将其打印出来:

auto <%= device %> inet static                                                                                                                                        
address <%= ipaddr %>
netmask <%= netmask %>
broadcast <%= broadcast %>
gateway <%= gateway %>
到目前为止,我所能想到的是需要对 device.each |device| puts device 进行处理,但我不知道语法应该是什么样子的。 我相信你可以从这些片段中了解我想做什么,然后你可能会明白条目需要分开而不是插值。 如果您能提供任何帮助,将不胜感激。我知道我应该在irb中尝试一些东西并从中找出答案,这就是我现在正在阅读的内容。
谢谢!

这个问题更适合在 Stack Overflow 上提问。 - gravyface
版主会处理的,我已经投票关闭/移动到那里了。希望会有更多人参与讨论。 - gravyface
3个回答

31

在Ruby中使用each的基本语法如下:

array.each do |item_from_array| BLOCK

所以如果你只有一个数组,你可以像这样做:

(为了清晰起见,我会在垂直条内使用不同的名称)
<% device.each do |dev| %>
  auto <%= dev %> inet static
<% end %>

不过这将首先迭代所有设备,然后再转到您的ipaddr数组。我猜您希望它们依次为auto、address、netmask等。在这种情况下,最好使用更“传统”的索引,并通过N次循环,像这样:

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

当然,你需要考虑你的数组的最大大小以及如果一个数组包含比其他数组少的条目时该怎么办。你可以通过执行以下操作找到所有数组的最大大小:[device,address,netmask,broadcast].map{|a| a.length}.max

并且你可以像这样跳过特定的数组:<% if idx < address.length %> address <%= address[idx] %><% end %>


这个有效,并且正是我要找的。谢谢!在<% for idx in (0..1) $>这一行上有一个语法错误,但是除非我更改6个字符否则我无法编辑它。 - matt
1
第一个例子应该是:<% device.each do |dev| %> 自动 <%= dev %> inet 静态 <% end %> - jamtur01
@nocache 这个问题很老了,但是感谢您包含“.each”示例,即使它并没有直接回答OP的问题,但这正是我所需要的! - Mark_Eng

5

针对初学者的ERB模板

基础代码:

require 'erb'
ERB.new(template).result binding_for_template

templatebinding_for_template是什么?

模板

仅指模板内容。你可以通过File.read(path)从文件中读取它。

用于模板的绑定

绑定将某个特定位置的执行上下文封装起来,并保留该上下文以供将来使用。

如何使用?很简单:

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

这将返回一个绑定了所有六个数组的绑定对象(为了一致性,我将 hwaddrnetwork 改为数组)。

遍历数组

通常的方法是使用 each 方法,就像这样:

<%- devices.each do |d| %>
  auto <%= d %> inet static
<%- end %>

但如果您想将所有内容放在一行中,还有其他方法,例如devices.join ' '将使用空格将所有字符串连接在一起。


1

你应该阅读文档。引用:

# Managed by Class['ntp']
<% servers_real.each do |server| -%>
server <%= server %>
<% end -%>

# ...

这段代码将遍历数组中的每个条目,并在服务器语句之后打印它,因此,例如,从Debian模板生成的字符串最终将包含类似于以下内容的块:
# 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

3
如果您只使用一个变量,并且顺序不重要,则此方法有效。我正在尝试做一些更复杂的事情。 - matt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接