2

I have a class hierarchy as follows:

class Tree
  def initialize(id, value)
    @id, @value = id, value
  end
end

class Entity < Tree

  include Mongoid::Document

  def initialize(id, value)
    # Do some stuff...
    super(id, value)
  end

end

However, calling superinside the Entity#initialize method calls the initialize method located in Mongoid::Document, instead of the one in the parent class Tree.

How can I call the Tree#initialize method from the body of Entity#initialize, after the Mongoid::Document module has been included?

user2398029
  • 6,699
  • 8
  • 48
  • 80

1 Answers1

4

That's how Ruby works. When you include a Module ruby implicitly creates an anonymous class and places it above current in the method lookup queue.

Also calling Entity.ancestors will show Mongoid::Document in the list.

There's a great book I can recommend: Metaprogramming Ruby by Paolo Perotta

Also here's a forum thread on a similar topic explaining super stuff

Update:

If avoiding to call the module constructor is what you want here's a possible trick

class Entity < Tree

  def initialize(id, value)
    # Do some stuff...
    # initialize first
    super(id, value)
    # and after that - extend
    extend Mongoid::Document
  end

end

This method is not running self.included on the module. If you need this functionality to remain, still not runnin module's initializer the eigenclass can be used in the init:

class Entity < Tree

  def initialize(id, value)
    # Do some stuff...
    # initialize first
    super(id, value)
    # and after that - include into eigenclass
    class << self
      include Mongoid::Document
    end
  end

end
Alexey Kharchenko
  • 1,032
  • 5
  • 10