如何检测类似数组或类似集合的值,同时避免类型检查
我有一个方法,它接受一个参数,该参数可以是类似数组/集合的对象,也可以是哈希。该方法的要点如下:
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 本质上不是数组。请参阅在 Ruby 中实现 to_int 和 to_str 的后果 - 我无法检查
to_a
因为 Hash 会响应它 Array 和 Set 通用但 Hash 不通用的方法是:
[:&, :+, :-, :<<, :collect!, :flatten!, :map!, :|]
我决定采用这样的方法:
query = {:_id => {'$in' => query.to_a}} if query.respond_to? :&
因为交集可能是类似集合的对象所具有的运算符。但我对此并不确定。
I have a method which accepts an argument which can be an Array/Set-like object, or a Hash. The gist of the method is something like:
def find(query = {})
if Array === query or Set === query
query = {:_id => {'$in' => query.to_a}}
end
mongo_collection.find(query)
end
The method will accept a set of ID objects and turn it into a hash condition for MongoDB.
Two problems with above code:
- It will fail if 'set' is not required from standard library. I don't want to require the dependency just to perform a check.
- I don't want to do strict type comparisons. I want to accept any array- or set-like value and cast it to an array of values with
to_a
.
How would you perform this check? Some considerations to have in mind:
- I could check for
to_ary
method, but Set doesn't respond toto_ary
. Objects that implement this method should fundamentally be arrays, and I agree that Set isn't fundamentally an array. See Consequences of implementing to_int and to_str in Ruby - I can't check for
to_a
since Hash responds to it Methods that are common to Array and Set, but not to Hash are:
[:&, :+, :-, :<<, :collect!, :flatten!, :map!, :|]
I decided to go with something like this:
query = {:_id => {'$in' => query.to_a}} if query.respond_to? :&
since intersection is likely an operator a set-like object would have. But I'm not sure about this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这是我的看法:
我只是检查
to_a
,这是我唯一感兴趣的方法,但也确保它不是 Hash 对象。我对哈希使用严格的类型检查,但这只是因为这是最不可能作为完全独立的类传递的对象,而该类本质上是哈希。Here's my take:
I'm just checking for
to_a
, which is the only method I'm interested in, but also ensuring that it's not a Hash object. I'm using strict type checking for Hash, but only because this is the least likely object to be passed as a completely separate class that's fundamentally a hash.尝试找出查询是否类似于哈希怎么样?
如果对象响应 has_key?,则可以合理地预期该对象将是 Hash 或类似 Hash 的对象。
How about trying to find out if the query is Hash like?
It is reasonable to expect that the object will be a Hash or Hash like if it responds to has_key?.
检查 Set 是否已定义将解决您的第一个问题。对于第二个,您可以检查查询类的祖先以查看数组是否在其中,但这可能无法捕获所有“类似数组”的对象。我可能不会检查是否存在测试数组的方法,因为您正在测试名称,而不是行为。 Arel 特别响应(或在它被弃用之前所做的) &,但这种类型的对象不会像您希望的那样工作。
Checking to see if Set is defined would solve your first issue. For the second, you could possibly check the ancestors of the class of query to see if Array is in them, but that probably won't catch all "array-like" objects. I probably wouldn't check for the existence of methods to test for arrayness, as you are testing names, not behavior. Arel in particular responds to (or did before it was deprecated) &, but this type of object wouldn't work like you wanted it to.
我个人认为...
Personally I'm thinking...