使用切片!在变量上修改填充变量的节点属性

Using slice! on a variable is modifying the node attribute that populated the variable

在 OpsWorks Stacks 中,我使用自定义 JSON 字段设置了图层属性:

{
  "layer_apps" : [
    "app_manager"
  ]
}

属性的 app_ 部分是工作流所必需的。有时,我需要暂时删除食谱中的 app_ 部分。为此,我使用 slice!:

node['layer_apps'].each do |app_name|

  install_certs_app_name = app_name
  install_certs_app_name.slice!('app_') # 'app_manager' => 'manager'
  # snip
end

然而,一旦完成此操作,即使 app_name 未被直接修改,每个 node['layer_apps'] 属性都会被切片,这将继续到后续的食谱并导致失败。我预期的行为是 slice! 会修改 app_name,而不是当前的 node['layer_apps'] 属性。认为 app_name 是属性的 link 而不是它自己的变量,我尝试将它的值分配给一个单独的变量(install_certs_app_name 和其他食谱中的类似),但行为仍然存在.

这是 Ruby/Chef 中的预期行为吗?有没有更好的方法从属性中排除 app_ 前缀?

当您将 app_name 分配给 install_certs_app_name 时,您仍然引用同一个对象。为了创建新对象,您可以这样做:

install_certs_app_name = app_name.dup

已创建具有相同值的新对象。并且切片 install_certs_app_name 不会影响 app_name 这种方式。

app_name 直接修改。这就是方法后爆炸 ! 的原因...这样您就知道该方法改变了对象。

app_nameinstall_certs_app_name引用同一个对象。

请注意 sliceslice! 都是 return "app_" 但是 bang 对象通过删除切片文本来改变调用者。

如果你这样做了

结果 = install_certs_app_name.slice!('app_') 结果 ==> 应用程序_ 放 install_certs_app_name --> 经理

尝试(而不是)

  install_certs_app_name = app_name.dup
  install_certs_app_name.slice!('app_')

所以你有两个独立的对象。

或者,

  install_certs_app_name = app_name.sub('app_', '')

如果你想要一个变量切片,你会得到非破坏性版本:

str.slice 而不是 str.slice!

这些通常被称为 Bang 方法,并在适当的位置替换变量。
下面是 .downcase 方法的示例。这与 .slice.

的原理相同

编辑:
但是,由于 .slice returns 部分已被删除,您可以删除 app_-部分 .sub,例如

"app_manager".sub("app_",'') #=> "manager"