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:
I have an object which is populated with my data.
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
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.
精彩评论