2015-04-14 3 views
0

Я создаю клиент для REST API, который возвращает JSON так:Могу ли я создавать методы из вызова Ruby REST API?

2.1.5 :006 > system = api.system 
=> {"DatabaseVersion"=>5, "Name"=>"Orthanc", "Version"=>"0.8.6"} 

мне интересно, если есть способ, чтобы преобразовать эти ключи JSON в методы, чтобы я мог назвать что-то вроде

version = api.system.version 

И получили бы значение этого ключа JSON:

=> "0.8.6" 

Очевидно, что я мог бы жёстко каждый JSON ключ элемента в качестве способа в клиенте, извлекая значение в качестве pecific ключ с чем-то вроде:

api.system["Version"] 

Но мне интересно, если это может быть сделано программно для каждого ключа/значения, которое принимается без предварительного знания ключей/значений, которые будут возвращены

ответ

1

OpenStruct приходит на помощь:

▶ os = OpenStruct.new({ 
▷ "DatabaseVersion"=>5, 
▷ "Name"=>"Orthanc", 
▷ "Version"=>"0.8.6" 
▷ }) 
▶ os.DatabaseVersion 
#⇒ 5 
0

редактировать:

Как указывалось @mudasobwa , уже существует стандартная реализация, с классом, который использует method_missing и внутренний объект Hash ...

По-видимому, это поведение очень понравилось многим и нашло путь к стандартной библиотеке.

см. Документацию по адресу OpenStruct.

помнить, чтобы требовать применения с использованием: требуют «» ostruct

оригинальный пост:

Я думаю, что вы могли бы искать решение, основанное на method_missing.

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

Вот быстрый грязный патч:

class Hash 

    def method_missing(name, *args, &block) 
    # getter for symbole 
    return self[name] if self.has_key? name 
    # getter for String 
    return self[name.to_s] if self.has_key? name.to_s 
    # setter for adding or editing hash keys, 
    # using the shortcut hash.key = value. 
    if name.to_s[-1] == '=' && name.to_s.length > 1 
     self.[]=(name.to_s[0..-2], *args) 
     self.[]=(name.to_s[0..-2].to_sym, *args) 
     return *args 
    end 
    # nothing happened? move it up the chain for default behavior. 
    # (assumes Hash doesn't handle missing methods). 
    super 
    end 

end 

Это будет вести себя как «на лету» добытчика и сеттер. Обратите внимание, что getter будет работать только для существующих свойств и что числа не поддерживаются (только строки и символы).

Также обратите внимание, что символы и строки будут унифицированы - если невозможно использовать символ и строку для разных значений, используя эти приемники/сеттеры. Кроме того, символы будут иметь приоритет.

Лично я бы, вероятно, отказался от такого решения удобства или отказался от подклассификации класса Hash. Я не слишком ухожен с патчами обезьян.

+1

Пожалуйста, никогда не используйте 'method_missing', если вы не можете доказать, что нет другого способа добиться желаемого поведения. Это приводит к штрафам за производительность, почти незаметному коду и внезапным ошибкам. Обработка хэшей определенно не является областью применения. – mudasobwa

+0

@mudasobwa, я вообще согласен - но я не вижу способа создать желаемое поведение без использования этой функции ... и опция 'method_missing' существует по какой-то причине. Например, OpenStruct использует 'method_missing' для реализации этой же функции. – Myst

+0

Я никогда не говорил, что «' method_missing »плохо,« я сказал «не делай этого сам». Как вы [заметили] (https://github.com/rubysl/rubysl-ostruct/blob/2.0/lib/ rubysl/ostruct/ostruct.rb # L175-L188), реализация OpenStruct делает много вещей, таких как проверки и т. д. Недостаточно просто перезаписать 'method_missing'. Например. опуская «reply_to?», один разрывает поиск рубина. В конце концов, 'OpenStruct' выполняет _defines methods_, а не вызывает' method_missing' по каждому запросу. – mudasobwa

Смежные вопросы