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

时间:2015-03-24 18:23:40

标签: ruby yaml

是否有内置机制来更新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"}}

2 个答案:

答案 0 :(得分:0)

如果您使用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"}的值"prop",但不会"something"

答案 1 :(得分:0)

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

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"}}

再次感谢您的回复。如果有人有其他想法或想法,我们总是很乐意学习更好的方法。