Ответ 1
>> require 'ostruct'
=> []
>> foo = {'bar'=>'baz'}
=> {"bar"=>"baz"}
>> foo_obj = OpenStruct.new foo
=> #<OpenStruct bar="baz">
>> foo_obj.bar
=> "baz"
>>
У меня есть хеш
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
>> require 'ostruct'
=> []
>> foo = {'bar'=>'baz'}
=> {"bar"=>"baz"}
>> foo_obj = OpenStruct.new foo
=> #<OpenStruct bar="baz">
>> foo_obj.bar
=> "baz"
>>
То, что вы ищете, называется OpenStruct. Это часть стандартной библиотеки.
Хорошее решение:
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'
Если вы предпочитаете поиск символов, а не поиск строк, замените два условия "если"
Вместо того, чтобы копировать все данные из хэша, вы можете просто добавить какое-то поведение в 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
выше.
Для этого есть несколько драгоценных камней. Там мой недавний драгоценный камень, 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.