【发布时间】:2018-02-22 05:00:43
【问题描述】:
我在尝试修改厨师食谱时遇到了一个奇怪的问题。我有一个包含大量哈希的属性。对于这些子哈希中的每一个,我想在其中的“标签”哈希中添加一个新的键/值。在我的配方中,我为每个大散列创建一个“标签”局部变量,并将标签散列分配给该局部变量。
我想对标签哈希添加修改,但修改必须在编译时完成,因为该值取决于存储在输入 json 中的值。我的第一次尝试是这样做:
tags = node['attribute']['tags']
tags['new_key'] = json_value
但是,这导致了一个规范错误,表明我应该使用 node.default 或等效的属性分配函数。所以我尝试了:
tags = node['attribute']['tags']
node.normal['attribute']['tags']['new_key'] = json_value
虽然我没有遇到规范错误,但新的键/值没有固定。
此时,我达到了“将东西扔到墙上”的阶段,并使用了 hash.merge 函数,我曾经认为它在功能上与 hash['new_key'] 相同,用于添加单个键/值对:
tags = node['attribute']['tags']
tags.merge({ 'new_key' => 'json_value' })
这最终奏效了,但我不明白为什么。这两种方法有什么功能上的区别,导致一种方法被视为对原始厨师属性的修改,而不是另一种?
【问题讨论】:
-
我从未使用过 Chef,但请记住
[]是一种可以被覆盖的方法,因此可能 Chef 使用的并不是真正的 Hash,而是使用类似接口的东西。 -
听起来很可能。我假设我最初的理解适用于标准 Ruby 是否正确?
-
node不是Hash。node是Chef::Node[]方法使您可以访问Chef::Attribute也不是Hash但更接近它是Mash这是Chefs 的子类Hash。为什么第一个版本不起作用我无法解释,因为[]=(arg)是作家。此外,为什么merge确实有效也没有任何意义,因为它不是破坏性的(意味着它创建一个副本并修改副本,使原件保持不变)本质上[]=实际上类似于merge!
标签: ruby hash chef-infra