3

我得到了一些具有不同结构的 yml 配置文件,我想提取密码(位于不同级别)并将它们存储在 git repo 之外的 yml 文件中。让我举个例子

config1.yml

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

我希望替换secret''提取一个通行证到一个不同的 yml 文件,如下所示:

config1_passwords.yml

a:
  b:
    password: secret

有没有办法在config1.yml没有密码的情况下合并config1_passwords.yml以获得正确的配置结构?

所以基本上就哈希(解析的 ymls)而言,我想做以下事情:

{ :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' } } }
4

3 回答 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.

于 2013-05-03T14:45:04.670 回答
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}}

如果您有可能需要遍历的数组和其他结构,则取决于您对此进行改进。注意我让它修改了配置。

于 2013-05-03T14:43:48.470 回答
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,请查看实现

于 2013-05-03T14:44:24.037 回答