Ruby 在chef中相同属性文件中的其他属性中使用属性值
注意:我这里的示例是为了显示我的问题的上下文,而不是真实世界的示例 我的attributes/default.rb文件中有以下示例: 接下来,我将其传递给一个模板,如下所示: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'
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) %>