使用切片!在变量上正在修改填充变量的节点属性
Posted
技术标签:
【中文标题】使用切片!在变量上正在修改填充变量的节点属性【英文标题】:Using slice! on a variable is modifying the node attribute that populated the variable 【发布时间】:2018-01-20 09:25:47 【问题描述】:在 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
是属性的链接而不是它自己的变量,我尝试将其值分配给单独的变量(install_certs_app_name
和其他食谱中的类似),但行为仍然存在。
这是 Ruby/Chef 中的预期行为吗?有没有更好的方法从属性中排除 app_
前缀?
【问题讨论】:
【参考方案1】:app_name
正在被直接修改。这就是在方法后面加上 !
的原因...这样您就知道该方法会改变对象。
和app_name
和install_certs_app_name
引用同一个对象。
请注意,slice
和 slice!
都返回“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_', '')
【讨论】:
感谢@SteveTurczyn 的建议!我过去确实尝试过install_certs_app_name = app_name.slice('app_')
,但奇怪的是,ruby 似乎返回了被删除的字符串部分,而不是结果字符串。不过,我之前没见过.dup
,所以我会试一试。
是的,我的头在云端。slice
和 slice!
总是返回切片文本,所以 string = 'abc' ; result = string.slice('a')
和 string = 'abc'; result = string.slice!('a')
在这两种情况下 result
都会有“a”但在第二个示例中,string
中的对象被修改了。【参考方案2】:
如果你想要一个变量切片,你需要的是非破坏性版本:
str.slice
而不是str.slice!
这些通常被称为 Bang 方法,并在适当的位置替换变量。
下面是.downcase
方法的示例。这与.slice
的原理相同。
编辑:
但是,由于 .slice
返回已被剪切的部分,您可以像删除 app_
-part .sub
一样
"app_manager".sub("app_",'') #=> "manager"
【讨论】:
谢谢!我确实尝试了非破坏性方法,但 slice 似乎特别返回了被删除的字符串部分,而不是剩余的字符串。有没有合适的方法让非破坏性切片返回结果字符串? 哦,对了,让我用另一个选项更新我的答案。 确实如此!史蒂夫的答案得到了复选标记,因为我第一次尝试了他的答案,它适用于我的目的,但你的答案似乎更优雅。更改已接受的答案是一种失礼吗? 无需更改 - 我不是完全为了名誉而来 ;) 而且由于他的效果也很好,这很酷,尽管复制一个字符串来分割原件似乎有点奇怪。 “如果你想要一个变量切片”——你不能切片一个变量。变量在 Ruby 中不是对象,您只能在对象上调用方法。您可以对变量做两件事,切片不是其中之一:分配变量和取消引用变量。 “这些通常被称为 Bang 方法,并在适当的位置替换变量。” – Bang-methods 仅仅意味着有一对执行类似操作的方法,但一个比另一个更令人惊讶。它确实不就地替换变量。它改变了…所引用的对象【参考方案3】:当您将app_name
分配给install_certs_app_name
时,您仍然引用同一个对象。为了创建新对象,您可以这样做:
install_certs_app_name = app_name.dup
创建具有相同值的新对象。并且以这种方式对install_certs_app_name
进行切片不会影响app_name
。
【讨论】:
以上是关于使用切片!在变量上正在修改填充变量的节点属性的主要内容,如果未能解决你的问题,请参考以下文章