Mongoid built-in collection answer: find

I am sending serialized data to a class that needs to access a Mongoid document that may or may not be embedded.

In the case of an inline document, I accept a variable number of arguments that I reduce

need to get the embedded document.

The code is pretty simple:

def perform(object, *arguments)
  @opts = arguments.extract_options!
  @object = arguments.reduce(object){|object, args| object.public_send(*args)}
  # [...]

      

I used public_send

because AFAIK I only need to call the public methods.

However, when I try to access an inline document, I have a very strange result when @object

is an enumerator.

After some debugging, I found that for any root document object

and inline collection items

, I have:

object.items.public_send(:find)
# => #<Enumerator: ...>
object.items.send(:find) # or __send__
# => nil

      

The method being called doesn't match at all when I call public_send

or send

!

  • How is this possible?
  • This is normal? This is mistake?

public_send

seems to be calling method find

Array

( Enumerable

) but send

(or __send__

) calling method find

for Mongoid


Edit: simple reproductive case:

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

      

+3


source to share


1 answer


Ok, after a few hours of debugging I found that this is actually a bug in Mongoid.

A relation is not an array, but a proxy around the array that delegates most of the methods to the array.



Since public_send

it was also delegated, but not send

also __send__

, the behavior was not the same.

See my pull request and associated commit for more information .

+1


source







All Articles