Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding the `include` statement behavior for "subsequent" mixin modules

I am trying to understand the include statement behavior when used in multiple Mixins. That is, I have these statements:

class Article < ActiveRecord::Base
  include DoubleIncludedModule
  include AModule

  # ...
end

module AModule
  include DoubleIncludedModule

  # ...
end

module DoubleIncludedModule
  # ...
end

How many times will be the DoubleIncludedModule included in the Article class? That is, since the "subsequent" inclusion of the DoubleIncludedModule (first in the Article class and then in AModule included by the Article class itself), will be the "double inclusion" issue automatically handled by Ruby or will the DoubleIncludedModule (wrongly) included two times?

Of course, I would like to include the DoubleIncludedModule module only one time. How can I make that (maybe by using some Ruby on Rails methods) the proper way?

like image 673
Backo Avatar asked Sep 26 '12 04:09

Backo


1 Answers

I'll answer with an example:

module A
  def self.included base
    puts "A included in #{base}"
  end
end

module B
  include A

  def self.included base
    puts "B included in #{base}"
  end
end

class C
  include A
  include B
end

p C.ancestors

prints

A included in B
A included in C
B included in C
[C, B, A, Object, Kernel, BasicObject]

As we can see, A is included only once into C. Though technically it was included twice since it was included into B which was also included into C. Does this matter? Probably not. Each still only occurs once in the ancestor chain, and any methods would've been overridden with equivalent implementations—i.e., essentially a no-op. Unless you're doing something exotic with the included hook, you're unlikely to notice anything.

like image 150
Andrew Marshall Avatar answered Oct 14 '22 03:10

Andrew Marshall