Как я могу превратить один объект во что-то перечисляемое в ruby - PullRequest
2 голосов
/ 17 сентября 2008

У меня есть метод, который может вернуть либо один объект, либо коллекцию объектов. Я хочу иметь возможность запустить object.collect для результата этого метода, независимо от того, является ли он единственным объектом или коллекцией. Как я могу это сделать?

profiles = ProfileResource.search(params)
output = profiles.collect do | profile |
    profile.to_hash
end

Если профили - это один объект, я получаю исключение NoMethodError при попытке выполнить сбор для этого объекта.

Ответы [ 9 ]

6 голосов
/ 17 сентября 2008

Вот один лайнер:

[*ProfileResource.search(params)].collect { |profile| profile.to_hash }

Хитрость заключается в том, что сплат (*) превращает как отдельные элементы, так и перечислимые в списки аргументов (в данном случае в новый оператор массива)

6 голосов
/ 17 сентября 2008

Осторожно с подходом flatten, если search () вернул вложенные массивы, это может привести к неожиданному поведению.

profiles = ProfileResource.search(params)
profiles = [profiles] if !profiles.respond_to?(:collect)
output = profiles.collect do |profile|
    profile.to_hash
end
1 голос
/ 17 сентября 2008
profiles = [ProfileResource.search(params)].flatten
output = profiles.collect do |profile|
    profile.to_hash
end
0 голосов
/ 19 сентября 2008

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

Итак. Вы МОЖЕТЕ смешать Enumerable с вашим классом и дать ему пустышку, которая работает ....

class YourClass
  include Enumerable

  ... really important and earth shattering stuff ...

  def each
    yield(self) if block_given?
  end
end

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

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

Конечно, лучше всего изменить реализацию поиска таким образом, чтобы она возвращала массив независимо от того, сколько элементов возвращается.

0 голосов
/ 17 сентября 2008

Вы также можете использовать метод Kernel # Array.

profiles = Array(ProfileResource.search(params))
output = profiles.collect do | profile |
    profile.to_hash
end
0 голосов
/ 17 сентября 2008

Сначала вы можете проверить, отвечает ли объект на метод "collect", используя "pofiles.respond_to?"

С Программирование Ruby

obj.respond_to? ( aSymbol, includePriv = false) -> true или ложь

Возвращает true, если obj отвечает на данный метод. Частные методы включается в поиск только если необязательный второй параметр оценивается как правда.

0 голосов
/ 17 сентября 2008
profiles = ProfileResource.search(params)
output = Array(profiles).collect do |profile|
    profile.to_hash
end
0 голосов
/ 17 сентября 2008

Если коллекция является массивом, вы можете использовать эту технику

profiles = [*ProfileResource.search(params)]
output = profiles.collect do | profile |
    profile.to_hash
end

Это гарантирует, что ваши профили всегда будут массивом.

0 голосов
/ 17 сентября 2008

В методе search класса ProfileResource всегда возвращайте коллекцию объектов (обычно массив), даже если она содержит только один объект.

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