【发布时间】:2011-07-20 20:41:30
【问题描述】:
我有一个接受参数的方法,该参数可以是类数组/集合对象或哈希。该方法的要点如下:
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方法,但Set 没有响应to_ary。实现此方法的对象本质上应该是数组,我同意 Set 本质上不是数组。见Consequences of implementing to_int and to_str in 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]。此时,调用者的工作是要求适当的类,而不是你。
标签: ruby mongodb types set duck-typing