如何将单个对象转换为红宝石中可枚举的对象

时间:2020-03-05 18:57:44  来源:igfitidea点击:

我有一个可以返回单个对象或者对象集合的方法。我希望能够在该方法的结果上运行object.collect,无论它是单个对象还是集合。我怎样才能做到这一点?

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

如果配置文件是单个对象,则在尝试对该对象执行collect时会收到NoMethodError异常。

解决方案

回答

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

回答

在ProfileResource类的search方法中,即使它仅包含一个对象,也总是返回对象的集合(通常是Array)。

回答

谨慎使用扁平化方法,如果search()返回嵌套数组,则可能会导致意外行为。

profiles = ProfileResource.search(params)
profiles = [profiles] if !profiles.respond_to?(:collect)
output = profiles.collect do |profile|
    profile.to_hash
end

回答

这是一个班轮:

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

诀窍是splat(*),它将单个元素和枚举数都转换为参数列表(在本例中为新数组运算符)

回答

如果集合是数组,则可以使用此技术

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

这样可以保证配置文件始终是一个数组。

回答

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

回答

我们可以先使用" pofiles.respond_to?"检查对象是否响应" collect"方法。

从Ruby编程

obj.respond_to?(
  aSymbol, includePriv=false ) -> true
  or false  
  
  Returns true if obj responds to the
  given method. Private methods are
  included in the search only if the
  optional second parameter evaluates to
  true.

回答

我们也可以使用Kernel#Array方法。

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

回答

另一种方法是认识到Enumerable要求我们提供每个方法。

所以。我们可以将Enumerable混合到班级中,并给每个虚拟人起作用。

class YourClass
  include Enumerable

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

  def each
    yield(self) if block_given?
  end
end

这样,如果我们从搜索中单独取回单个项目,则可枚举的方法仍将按预期工作。

这种方式的优点是,对它的所有支持都在类内部,而不是在必须多次重复的外部。

当然,更好的方法是更改​​搜索的实现,以使其无论返回多少项目都返回一个数组。