【问题标题】:Hash overriding a hash哈希覆盖哈希
【发布时间】:2013-05-03 14:04:41
【问题描述】:

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

config1.yml

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

我希望将 secret 替换为 '' 并提取到另一个 yml 文件,如下所示:

config1_passwords.yml

a:
  b:
    password: secret

有没有办法将没有密码的config1.ymlconfig1_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' } } }

【问题讨论】:

  • { :a => { :b => { :c => 1, :password => '' }, :d => 2 } }{ :a => { :b => { :password => 'secret' } } } 你想要{ :a => { :b => { :c => 1, :password => 'secret' }, :d => 2 } }。我说的对吗?
  • 是的,但结构可能不同,并且不同级别可能有多个密码。第二个哈希将只包含密码,不管它有多深,所以我需要一个通用的解决方案

标签: ruby-on-rails ruby hash yaml


【解决方案1】:

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

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

    【讨论】:

      【解决方案3】:

      看来您想要某种哈希深度合并。它在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,请查看implementation

      【讨论】:

        猜你喜欢
        • 2014-02-17
        • 1970-01-01
        • 1970-01-01
        • 2017-05-02
        • 1970-01-01
        • 2019-10-04
        • 2019-03-21
        • 2011-05-27
        • 1970-01-01
        相关资源
        最近更新 更多