У меня есть метод, который принимает аргумент, который может быть объектом типа Array/Set или Hash. Суть метода примерно такая:
def find(query = {})
if Array === query or Set === query
query = {:_id => {'$in' => query.to_a}}
end
mongo_collection.find(query)
end
Метод примет набор объектов ID и превратит его в хеш-условие для MongoDB.
Две проблемы с приведенным выше кодом:
- Это не удастся, если 'set' не требуется из стандартной библиотеки. Я не хочу требовать зависимость только для выполнения проверки.
- Я не хочу делать строгие сравнения типов. Я хочу принять любое значение, подобное массиву или набору, и привести его к массиву значений с помощью
to_a
.
Как бы вы выполнили эту проверку? Некоторые соображения, которые следует иметь в виду:
- Я мог бы проверить метод
to_ary
, но Сет не отвечает наto_ary
. Объекты, реализующие этот метод, должны быть массивами, и я согласен, что Set не является массивом. См. Последствия реализации to_int и to_str в Ruby - Я не могу проверить
to_a
, так как Hash отвечает на него Методы, общие для Array и Set, но не для Hash:
[:&, :+, :-, :<<, :collect!, :flatten!, :map!, :|]
Я решил пойти с чем-то вроде этого:
query = {:_id => {'$in' => query.to_a}} if query.respond_to? :&
поскольку пересечение, вероятно, является оператором, который будет иметь объект, подобный множеству. Но я не уверен в этом.
.to_a
к объекту и посмотрите, может ли он преобразоваться в массив. Если вам нужен хэш, вы, вероятно, захотите преобразовать его в массив, а затем создать хэш:Hash[*array.to_a.flatten]
. В этот момент работа вызывающей стороны состоит в том, чтобы требовать соответствующие классы, а не вас. - person the Tin Man   schedule 21.07.2011