Ruby 在chef中相同属性文件中的其他属性中使用属性值

Ruby 在chef中相同属性文件中的其他属性中使用属性值,ruby,chef-infra,Ruby,Chef Infra,注意:我这里的示例是为了显示我的问题的上下文,而不是真实世界的示例 我的attributes/default.rb文件中有以下示例: 接下来,我将其传递给一个模板,如下所示: template '/home/vagrant/php_test.txt' do source node['url'] % {version: node['version']} source 'php_test.txt.erb' owner 'vagrant' group 'vagrant'

注意:我这里的示例是为了显示我的问题的上下文,而不是真实世界的示例

我的attributes/default.rb文件中有以下示例:

接下来,我将其传递给一个模板,如下所示:

template '/home/vagrant/php_test.txt' do
    source node['url'] % {version: node['version']}
    source 'php_test.txt.erb'
    owner 'vagrant'
    group 'vagrant'
    mode '0755'
    variables(
        php: node[:php]
    )
end
然后我引用模板中的值,如下所示:

PHP Version : <%= @php[:version] %>
PHP Repository : <%= @php[:repository] %>

PHP Extension List:
<% @php[:extensions].each do |extension| %>
<%= "#{extension}" %>
<% end %>

PHP Options List
<% @php[:options].each do |option, value| %>
<%= "#{option}: #{value}" %>
<% end %>
一切正常;然而,我的DRY ist看到了所有的7.3,并说,嘿,为什么不在列表中每个扩展的值中引用version的值呢?因此,我在attributes/default.rb文件中尝试以下方法:

这至少有两个问题。首先,它没有达到我的预期。当我在模板中循环数组时,每个值都作为字符串打印,而不是插值。其次,它打破了这里提到的厨师最佳实践:

那么,在另一个属性的总体中使用一个属性的值的最佳方法是什么

考虑到这一点,我可以想到两种选择:

使用延迟插值,如下所示: 我的问题是,我不太明白建议的概念是如何工作的,因为我的红宝石技能不太符合标准。p> 存储不带php后缀的扩展,然后在配方中循环它们,并将php、版本字符串和扩展连接到每个扩展的单个值中。将这些存储在传递给模板的新数组中。
是否有其他方法来实现这一点;可能是通过强制php{node[:php][:version]}属性在模板中插值?

我不知道Chef,但是阅读最佳实践页面,通过延迟插值导出属性是正确的方法。这应该相当简单:

extensions: [
  "php%{version}",
  "php%{version}-common",
  "php%{version}-gd",
  # ...
]
然后,稍后渲染时:

<% @php[:extensions].each do |extension| %>
<%= extension % @php %>
<% end %>
由于@php变量有一个:version键,如果该字符串包含占位符%{version},则在呈现时会将其替换为每个扩展字符串的值

您还可以更明确地这样做:

# Create a hash with the one key:
<%= extension % {version: @php[:version]} %>

# Or, just create a hash by slicing out just the attribute you care about
<%= extension % @php.slice(:version) %>

rubocop建议的另一种方法是使用技术上相同但更具声明性的格式:格式php-%{version},{version:1.2.3}。我更喜欢格式,但厨师长文档使用了%,所以我选择了。你能告诉我厨师长文档的位置吗?AFAIK厨师大量使用rubocop+一些厨师特定规则/修改的烹饪风格。嘿,我刚从OP的帖子中删除了链接。如果厨师更喜欢格式,那么格式应该是:首先,非常感谢您花这么多时间在如此详细的回复上。我真的很感激,解释也很清楚。这三种方法我都试过了。我相信这就是答案;但是,使用您提供的任何选项,Chef在模板中给了我一个错误:Chef::Mixin::template::TemplateError:找不到键{node[:php][:version]}。也就是说,变量确实正确编译:哈希显示在已编译的资源中。第一部分显示key:variables{:php=>{version=>7.3…所以我有点困惑。再次感谢您的回答!
extensions: [
  "php%{version}",
  "php%{version}-common",
  "php%{version}-gd",
  # ...
]
<% @php[:extensions].each do |extension| %>
<%= extension % @php %>
<% end %>
"test: %{bang}" % {baz: "bin", bang: "bar"}
=> "test: bar"
# Create a hash with the one key:
<%= extension % {version: @php[:version]} %>

# Or, just create a hash by slicing out just the attribute you care about
<%= extension % @php.slice(:version) %>