Mongoid 嵌入式集合对 :find 的响应
Mongoid embedded collection response to :find
我正在将序列化数据发送到 class,它需要访问可能嵌入也可能未嵌入的 Mongoid 文档。
对于嵌入式文档,我接受可变数量的参数,我 reduce
获取嵌入式文档。
代码非常简单:
def perform(object, *arguments)
@opts = arguments.extract_options!
@object = arguments.reduce(object){|object, args| object.public_send(*args)}
# [...]
我使用 public_send
因为据我所知我只需要调用 public 方法。
但是,当我尝试访问嵌入式文档时,我得到了一些非常奇怪的结果,其中 @object
是一个枚举数。
经过一些调试后,我发现对于任何根文档 object
和嵌入式集合 items
,我有:
object.items.public_send(:find)
# => #<Enumerator: ...>
object.items.send(:find) # or __send__
# => nil
我调用public_send
或send
!
调用的方法完全不一样
- 怎么可能?
- 正常吗?这是一个错误吗?
public_send
似乎调用了 Array
(Enumerable
)的 find
方法,但 send
(或 __send__
)调用了 find
Mongoid 的方法
编辑:简单的可重现案例:
require 'mongoid'
class User
include Mongoid::Document
field :name, type: String
embeds_many :groups
end
class Group
include Mongoid::Document
field :name, type: String
embedded_in :user
end
Mongoid.load_configuration({
sessions: {
default: {
database: 'send_find',
hosts: [
'localhost:27017'
]
}
}
})
user = User.create(name: 'john')
user.groups.create(name: 'g1')
user.groups.create(name: 'g2')
puts "public_send :find"
puts user.groups.public_send(:find).inspect
# => #<Enumerator: [#<Group _id: 5530dea57735334b69010000, name: "g1">, #<Group _id: 5530dea57735334b69020000, name: "g2">]:find>
puts "send :find"
puts user.groups.send(:find).inspect
# => nil
puts "__send__ :find"
puts user.groups.__send__(:find).inspect
# => nil
好的,经过几个小时的调试,发现其实是Mongoid的一个bug
关系不是数组,而是围绕数组的代理,它将大多数方法委托给数组。
由于 public_send
也被委托,但 send
和 __send__
没有委托,因此行为不一样。
有关详细信息,请参阅我的 pull request 和相关的提交。
我正在将序列化数据发送到 class,它需要访问可能嵌入也可能未嵌入的 Mongoid 文档。
对于嵌入式文档,我接受可变数量的参数,我 reduce
获取嵌入式文档。
代码非常简单:
def perform(object, *arguments)
@opts = arguments.extract_options!
@object = arguments.reduce(object){|object, args| object.public_send(*args)}
# [...]
我使用 public_send
因为据我所知我只需要调用 public 方法。
但是,当我尝试访问嵌入式文档时,我得到了一些非常奇怪的结果,其中 @object
是一个枚举数。
经过一些调试后,我发现对于任何根文档 object
和嵌入式集合 items
,我有:
object.items.public_send(:find)
# => #<Enumerator: ...>
object.items.send(:find) # or __send__
# => nil
我调用public_send
或send
!
- 怎么可能?
- 正常吗?这是一个错误吗?
public_send
似乎调用了 Array
(Enumerable
)的 find
方法,但 send
(或 __send__
)调用了 find
Mongoid 的方法
编辑:简单的可重现案例:
require 'mongoid'
class User
include Mongoid::Document
field :name, type: String
embeds_many :groups
end
class Group
include Mongoid::Document
field :name, type: String
embedded_in :user
end
Mongoid.load_configuration({
sessions: {
default: {
database: 'send_find',
hosts: [
'localhost:27017'
]
}
}
})
user = User.create(name: 'john')
user.groups.create(name: 'g1')
user.groups.create(name: 'g2')
puts "public_send :find"
puts user.groups.public_send(:find).inspect
# => #<Enumerator: [#<Group _id: 5530dea57735334b69010000, name: "g1">, #<Group _id: 5530dea57735334b69020000, name: "g2">]:find>
puts "send :find"
puts user.groups.send(:find).inspect
# => nil
puts "__send__ :find"
puts user.groups.__send__(:find).inspect
# => nil
好的,经过几个小时的调试,发现其实是Mongoid的一个bug
关系不是数组,而是围绕数组的代理,它将大多数方法委托给数组。
由于 public_send
也被委托,但 send
和 __send__
没有委托,因此行为不一样。
有关详细信息,请参阅我的 pull request 和相关的提交。