哈希覆盖哈希的问题

3

我有一些yml配置文件,结构不同且层次深入,我想提取密码(这些密码位于不同的级别)并将它们存储在一个yml文件中,该文件位于git仓库之外。让我展示一个例子

config1.yml

a:
  b:
    c: 1
    password: secret
    ...
  d: 2
  ...

我希望用''替换secret,并提取密码到另一个yml文件中,该文件应如下所示:

config1_passwords.yml

a:
  b:
    password: secret

有没有办法将不含密码的 config1.yml 与包含密码的 config1_passwords.yml 合并以获得正确的配置结构?

因此,基本上在哈希(解析的 yml 文件)方面,我想要做以下操作:

{ :a => { :b => { :c => 1, :password => '' }, :d => 2 } }
{ :a => { :b => { :password => 'secret' } } } 
# =>
{ :a => { :b => { :c => 1, :password => 'secret' }, :d => 2 } }

感谢建议

已编辑 另一个示例

{ :a => { :b => { :c => 1, :d => { :password1 => '' }, :password2 => '' } } }
{ :a => { :b => { :d => { :password => 'secret' }, :password2 => 'secret2' } } }
# =>
{ :a => { :b => { :c => 1, :d => { :password => 'secret' }, :password2 => 'secret2' } } }

使用 { :a => { :b => { :c => 1, :password => '' }, :d => 2 } }{ :a => { :b => { :password => 'secret' } } } ,您想要得到的结果是 { :a => { :b => { :c => 1, :password => 'secret' }, :d => 2 } }。我说得对吗? - Arup Rakshit
是的,但结构可能不同,而且不同级别可能有多个密码。第二个哈希只包含密码,无论它有多深,所以我需要一个通用解决方案。 - Rustam Gasanov
3个回答

4
Rails 3有一个deep_merge功能,可以完美地实现你想要的功能。
a = { :a => { :b => { :c => 1, :d => { :password1 => '' }, :password2 => '' } } }
b = { :a => { :b => { :d => { :password1 => 'secret' }, :password2 => 'secret2' } } }
a.deep_merge(b)
# -> {:a=> {:b=> {:c=>1, :d=>{:password1=>"secret"}, :password2=>"secret2"}}}

注意:我将a[:a][:b][:d]更改为包含:password1而不是:password

2

不要认为可以使用Ruby的一行代码来完成这个任务。但是一个简单的递归函数可能会做到。

def recurse_merge_password! conf_hash, pw_hash
  pw_hash.keys.each do |k|
    next unless conf_hash.has_key?(k)
    case
      when k == :password
        conf_hash[:password] = pw_hash[:password]
      when conf_hash[k].is_a?(Hash) && pw_hash[k].is_a?(Hash)
        recurse_merge_password! conf_hash[k], pw_hash[k]
    end
  end
end

h1 = { :a => { :b => { :c => 1, :password => '' }, :d => 2 } }

h2 = { :a => { :b => { :password => "secret" } } }

recurse_merge_password! h1, h2

puts h1.inspect

=> {:a=>{:b=>{:c=>1, :password=>"secret"}, :d=>2}}

如果您有数组和其他结构需要遍历,那么改进这一点就由您来完成。请注意,我已经使其直接在配置文件中进行修改。

2

看起来你想要某种哈希深度合并。它在 ActiveSupport 中可用(Rails 的一部分):

# You can omit this require statement if you're running Rails.
require "active_support/core_ext/hash/deep_merge"

a = { a: { b: { c: 1, d: { password1: "" }, password2: "" } } }
b = { a: { b: { d: { password1: "secret" }, password2: "secret2" } } }

a.deep_merge(b)
#=> { a: { b: { c: 1, d: { password1: "secret"}, password2: "secret2" } } }

如果您不希望依赖ActiveSupport,请查看实现


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接