Ruby:如何在哈希中为命名空间添加前缀

时间:2011-08-05 19:35:05

标签: ruby hash savon

我处于这样一种情况,我需要找出哈希的级别并为该级别中的所有元素应用命名空间。

这是情景:

  1. 我有一个用我的数据填充的对象。

  2. 接下来,我将对象转换为哈希。

    #convert Object to Hash
    def my_hash
      Hash[instance_variables.map { |var| [var[1..-1].to_sym, instance_variable_get(var)] }]
    end
    
  3. 最后,我想通过哈希循环,并将不同的命名空间应用于我的嵌套哈希。

    • 不幸的是我无法找到一个很好的解决方案来直接使用savon gem:

      soap.body = request_object.my_hash
      
    • 我将检查每个元素并尝试递归地在classify方法中找到嵌套级别:(这需要更多魔法)

      def classify(o)
        case o
          when Hash
            #Need to refactor this to prefix :data NS for nested hash, overwriting the default :mes NS. 
            h = {}
            o.each {|k,v| h[k] = classify(v)}
            h                 
          else
            o.class
        end 
      end
      soap.body = classify(request_object.my_hash)
      
  4. 看起来应该是这样,源哈希:

    {:UserTicket=>'123',:ImpersonationUsername=>'dave',:TicketSettings=>{:ResourceId=>'abcd',:ClientIp=>'0',:Username=>'bobby'}}
    

    输出(其中mes和数据是两个命名空间):

    {'mes:UserTicket'=>'123','mes:ImpersonationUsername'=>'dave','mes:TicketSettings'=>{'data:ResourceId'=>'abcd','data:ClientIp'=>'0','data:Username'=>'bobby'}}
    

1 个答案:

答案 0 :(得分:0)

这是一种传递与每个嵌套级别相关联的标识符列表的方法:

def classify(o, with)
  case o
    when Hash
      h = {}
      o.each {|k,v| h[:"#{with[0]}:#{k}"] = classify(v, with[1, with.length])}
      h                 
    else
      o.class
  end 
end

hash = {:UserTicket=>'123',:ImpersonationUsername=>'dave',:TicketSettings=>{:ResourceId=>'abcd',:ClientIp=>'0',:Username=>'bobby'}}

classify(hash, [ :mes, :data ])
# => {"mes:UserTicket"=>String, "mes:ImpersonationUsername"=>String, "mes:TicketSettings"=>{"data:ResourceId"=>String, "data:ClientIp"=>String, "data:Username"=>String}}

如果你正在使用递归算法,你有机会修改你所挖掘的每个级别所应用的范围。