2

我有一个接受参数的方法,该参数可以是类似数组/集合的对象或哈希。该方法的要点如下:

def find(query = {})
  if Array === query or Set === query
    query = {:_id => {'$in' => query.to_a}}
  end
  mongo_collection.find(query)
end

该方法将接受一组 ID 对象并将其转换为 MongoDB 的哈希条件。

上面代码有两个问题:

  1. 如果标准库不需要“设置”,它将失败。我不想仅仅为了执行检查而要求依赖。
  2. 我不想进行严格的类型比较。我想接受任何类似数组或类似集合的值,并将其转换为带有to_a.

您将如何执行此检查?需要记住的一些注意事项:

  1. 我可以检查to_ary方法,但 Set 不响应to_ary. 实现此方法的对象本质上应该是数组,我同意 Set 本质上不是数组。请参阅在 Ruby 中实现 to_int 和 to_str 的后果
  2. 我无法检查,to_a因为哈希响应它
  3. Array 和 Set 通用但 Hash 不通用的方法是:

    [:&, :+, :-, :<<, :collect!, :flatten!, :map!, :|]
    

我决定用这样的东西:

query = {:_id => {'$in' => query.to_a}} if query.respond_to? :&

因为交集很可能是一个类似集合的对象的运算符。但我不确定这一点。

4

4 回答 4

4

这是我的看法:

if not Hash === query and query.respond_to? :to_a

我只是检查to_a,这是我感兴趣的唯一方法,但还要确保它不是 Hash 对象。我正在对哈希使用严格的类型检查,但这只是因为这是最不可能作为一个完全独立的类传递的对象,它基本上是一个哈希。

于 2011-07-20T21:06:55.120 回答
1

尝试找出查询是否类似于 Hash 怎么样?

def find(query = {})
  query = {:_id => {'$in' => query.to_a}} unless query.respond_to?(:has_key?)
  mongo_collection.find(query)
end

如果对象响应 has_key? ,则可以合理地预期该对象将是一个 Hash 或 Hash。

于 2011-07-21T03:07:02.700 回答
0

检查是否定义了 Set 将解决您的第一个问题。其次,您可以检查查询类的祖先以查看 Array 是否在其中,但这可能不会捕获所有“类似数组”的对象。我可能不会检查是否存在测试数组的方法,因为您正在测试名称,而不是行为。Arel 特别响应(或在它被弃用之前)&,但这种类型的对象不会像你想要的那样工作。

于 2011-07-20T20:56:13.127 回答
0

个人认为...

def find(query = {})      
  mongo_collection.find(query_formatter(query))
end

def query_formatter(query)
  if query.respond_to?(:to_a) && !query.kind_of?(Hash)
    {:_id => {'$in' => query.to_a}}
  else
    query
  end
end
于 2011-07-20T22:30:21.027 回答