开发者

Ruby: How to prefix Namespaces in hash

I am in a situation where I need to find out the level of the hash and apply a namespace for all elements in that level.

This is the scenario:

  1. I have an object which is populated with my data.

  2. Next I convert the object to hash.

    #convert Object to Hash
    def my_hash
      Hash[instance_variables.map { |var| [var[1..-1].to_sym, instance_variable_get(var)] }]
    end
    
  3. Finally I would like to loop thru the hash and apply a different Namespace to my nested hash.

    • Unfortunately I wasn't able to find a good solution to do this with savon gem directly:

      soap.body = request_object.my_hash
      
    • I will inspect each element and try to find the nested level in classify method recursively: (this requires some more magic)

      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)
      

It should look like this, The source hash:

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

Output (where mes and data are two Namespaces):

{'mes:UserTicket'=>'123','mes:ImpersonationUsername'=>'dave','mes:开发者_如何学JAVATicketSettings'=>{'data:ResourceId'=>'abcd','data:ClientIp'=>'0','data:Username'=>'bobby'}}


Here's an approach where you pass in a list of identifiers associated with each level of nesting:

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

If you're using a recursive algorithm you have the opportunity to modify the scope of what's being applied with each level you dig down.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜