Search code examples
mongoidmongoid3embedded-documents

Parent Object In Mongoid Embedded Relation Extensions


Given a simple embedded relationship with an extension like this:

class D
  include Mongoid::Document
  embeds_many :es do
    def m
      #...
    end
  end
end

class E
  include Mongoid::Document
  embedded_in :d
end

You can say things like this:

d = D.find(id)
d.es.m

Inside the extension's m method, how do access the specific d that we're working with?


Solution

  • I'm answering this myself for future reference. If anyone has an official and documented way of doing this, please let me know.


    After an hour or so of Googling and reading (and re-reading) the Mongoid documentation, I turned to the Mongoid source code. A bit of searching and guesswork lead me to @base and its accessor method base:

      embeds_many :es do
        def m
          base
        end
      end
    

    and then you can say this:

    d = D.find(id)
    d.es.m.id == id # true
    

    base is documented but the documentation is only there because it is defined using attr_reader :base and documentation generated from attr_reader calls isn't terribly useful. base also works with has_many associations.


    How did I figure this out? The documentation on extensions mentions @target in an example:

    embeds_many :addresses do
      #...
      def chinese
        @target.select { |address| address.country == "China"}
      end
    end
    

    @target isn't what we're looking for, @target is the array of embedded documents itself but we want what that array is inside of. A bit of grepping about for @target led me to @base (and the corresponding attr_reader :base calls) and a quick experiment verified that base is what I was looking for.