hash ['key'] для hash.key в Ruby - PullRequest
       34

hash ['key'] для hash.key в Ruby

45 голосов
/ 18 ноября 2009

У меня есть хеш

foo = {'bar'=>'baz'}

Я хотел бы позвонить foo.bar #=> 'baz'

Моя мотивация - переписать запрос activerecord в необработанный SQL-запрос (используя Model # find_by_sql). Это возвращает хеш со значениями предложения SELECT в качестве ключей. Однако мой существующий код основан на точечной нотации object.method. Я хотел бы сделать минимальный переписать код. Спасибо.

Редактировать: кажется, что у Lua есть эта функция:

point = { x = 10, y = 20 }   -- Create new table
print(point["x"])            -- Prints 10
print(point.x)               -- Has exactly the same meaning as line above

Ответы [ 5 ]

81 голосов
/ 18 ноября 2009
>> require 'ostruct'
=> []
>> foo = {'bar'=>'baz'}
=> {"bar"=>"baz"}
>> foo_obj = OpenStruct.new foo
=> #<OpenStruct bar="baz">
>> foo_obj.bar
=> "baz"
>>
35 голосов
/ 18 ноября 2009

То, что вы ищете, называется OpenStruct . Это часть стандартной библиотеки.

22 голосов
/ 10 сентября 2010

Хорошее решение:

class Hash
  def method_missing(method, *opts)
    m = method.to_s
    if self.has_key?(m)
      return self[m]
    elsif self.has_key?(m.to_sym)
      return self[m.to_sym]
    end
    super
  end
end

Примечание: в этой реализации есть только одна известная ошибка:

x = { 'test' => 'aValue', :test => 'bar'}
x.test # => 'aValue'

Если вы предпочитаете поиск символов, а не поиск строк, то поменяйте местами два условия «если»

6 голосов
/ 18 ноября 2009

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

Если вы добавите это определение, вы расширите Hash для обработки всех неизвестных методов как поиска хеша:

class Hash
  def method_missing(n)
    self[n.to_s]
  end
end

Имейте в виду, что это означает, что вы никогда не увидите ошибок, если вызовете неправильный метод для хэша - вы просто получите то, что вернет соответствующий поиск в хэше.

Вы можете значительно уменьшить проблемы отладки, которые это может вызвать, только помещая метод в определенный хеш - или столько хешей, сколько вам нужно:

a={'foo'=>5, 'goo'=>6}
def a.method_missing(n)
   self[n.to_s]
end

Другое наблюдение состоит в том, что когда система вызывает method_missing, она дает вам аргумент Symbol. Мой код преобразовал его в String. Если ваши хеш-ключи не являются строками, этот код никогда не вернет эти значения - если вы вводите символы вместо строк, просто замените n на n.to_s выше.

4 голосов
/ 15 июня 2015

Для этого есть несколько драгоценных камней. Это мой недавний драгоценный камень hash_dot и несколько других драгоценных камней с похожими названиями, которые я обнаружил, когда выпустил свой на RubyGems, включая dot_hash .

HashDot позволяет использовать синтаксис с точечной нотацией, в то же время обращая внимание на проблемы с NoMethodErrors, устраняемые @avdi. Это быстрее и более проходимо, чем объект, созданный с помощью OpenStruct.

require 'hash_dot'
a = {b: {c: {d: 1}}}.to_dot
a.b.c.d => 1

require 'open_struct'
os = OpenStruct.new(a)
os.b => {c: {d: 1}}
os.b.c.d => NoMethodError

Он также поддерживает ожидаемое поведение при вызове не методов.

a.non_method => NoMethodError

Пожалуйста, не стесняйтесь отправлять улучшения или ошибки в HashDot.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...