Puppet模板中的Ruby实例变量(erb)

时间:2012-06-22 10:44:32

标签: ruby erb puppet

我不明白我在Puppet模板(erb)中编写的这段Ruby代码的行为。它必须与我忽略但无法找到的实例变量的某些属性相关。

在Puppet端,可以在文件site.pp中声明(和初始化)变量$ local_users。在下面显示的模板代码中,if语句检查它是否先前已初始化。

<% if @local_users -%>
  <%= fail('local_users has to be an array') unless local_users.class == Array -%>
<% else -%>
  <% local_users = [ "root" ] -%>
  <%# some code to add more users to the array -%>
<% end -%>
<% local_users.uniq.each do |user| -%>
  <%= user %>
<% end -%>

如果未在site.pp文件中声明$ local_users(else分支),则此代码可以正常运行。如果声明它(如果是分支),则在尝试应用Puppet清单时失败:

Failed to parse template sendmail/local-users.erb: undefined method `uniq' for nil:NilClass at /usr/share/puppet/modules/sendmail/manifests/config.pp:39

(第39行是调用模板的地方:content => template('sendmail/sendmail.mc.erb'),

问题是在循环中local_users变量不被识别为Array。我解决了问题,只是在if分支处声明了一个局部变量:

<% if @local_users -%>
  <%= fail('local_users has to be an array') unless local_users.class == Array -%>
  <% local_users = @local_users -%>
<% else -%>

但在if分支内部是一个数组,因为local.users.class == Array返回true(此时我也可以使用方法local_users.uniq而没有问题)。此外,我尝试使用if local_users(没有@)并在if分支内部local_users仍然是一个数组,但是在循环中仍然失败。

以下是我的问题:

  1. 如何解释这种行为?为什么local_users变量是if分支中的一个数组而不是循环?
  2. 我的解决方法是正确的还是有更好的方法来做到这一点?

1 个答案:

答案 0 :(得分:0)

因为在Ruby中nil是一个具有自己的类(NilClass)的对象,因此(尝试使用irb):

nil.respond_to? :class
# => true

声明local_users.class == Array返回false

local_user是视图的本地变量,而@local_user是该视图后面的控制器的实例变量。

有两种不同的东西,这就是为什么你必须将local_user分配给@local_user,以便在你调用nil时没有local_users.uniq

顺便问一下,你为什么要使用local_users而不是简单地使用@local_users并移动控制器上的所有逻辑?