更新 YAML 文件重复节点中的值 (Ruby)?

Update value in repeated node for YAML file (Ruby)?

是否有内置机制来更新 YAML 重复节点中给定 属性 的值?我知道枚举是一种解决方案,但想知道是否有更好的方法。

示例:

require 'yaml'

yml = <<-eos
  common: &default_settings
    prop: 'xyz'

  something:
    <<: *default_settings
eos


config = YAML.load(yml)
config['common']['prop'] = "zzz"

p config
# I'm surprised the output is
# {"common"=>{"prop"=>"zzz"}, "something"=>{"prop"=>"xyz"}}
#
# I was expecting
# {"common"=>{"prop"=>"zzz"}, "something"=>{"prop"=>"zzz"}}

如果您查看 object_id,您可以看到 "common""something" 有 2 个完全不同的 Hash 对象。这就是为什么更改一个对象,key 的 值不会影响另一个对象。

require 'yaml'

yml = <<-eos
  common: &default_settings
    prop: 'xyz'

  something:
    <<: *default_settings
eos

config = YAML.load yml
config  # => {"common"=>{"prop"=>"xyz"}, "something"=>{"prop"=>"xyz"}}
config['common'].object_id # => 73499930
config['something'].object_id # => 73499700

并且由于上述 事实,当您执行此 config['common']['prop'] = "zzz" 时,它只会修改散列 {"prop"=>"xyz"},即 [=17] 的值=],而不是 "something".

我找到了问题的解决方案:

require 'yaml'

yml = <<-eos
  common: &default_settings
    prop: 'xyz'

  something:
    <<: *default_settings
eos


parsed = YAML.parse(yml) # => #<Psych::Nodes::Document>

parsed.each do |n|
  if n.respond_to?('anchor') && n.anchor == "default_settings"
    n.children.each do |n|
      if n.style == 2
        n.value = 'zzz'
      end
    end if n.children
  end
end


p parsed.to_ruby
#{"common"=>{"prop"=>"zzz"}, "something"=>{"prop"=>"zzz"}}

再次感谢您的回复。如果有人有额外的想法或想法,总是乐于学习更好的方法。