Ruby: Как добавить префикс пространства имен в хэш - PullRequest
1 голос
/ 05 августа 2011

Я нахожусь в ситуации, когда мне нужно выяснить уровень хэша и применить пространство имен для всех элементов на этом уровне.

Это сценарий:

  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
      
    • Я проверю каждый элемент и попытаюсь найти вложенный уровень в методе классификации рекурсивно: (для этого требуется больше магии)

      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)
      

Это должно выглядеть так, Источник хеша:

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

Вывод (где mes и data - это два пространства имен):

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

1 Ответ

0 голосов
/ 05 августа 2011

Вот подход, при котором вы передаете список идентификаторов, связанных с каждым уровнем вложенности:

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

Если вы используете рекурсивный алгоритм, у вас есть возможность изменить область применения того, что применяется с каждым уровнем, который вы копаете.

...