What’s a Mixin?
A mixin can basically be thought of as a set of code that can be added to one or more classes to add additional capabilities without using inheritance. In Ruby, a mixin is code wrapped up in a module that a class can include or extend. In fact, a single class can have many mixins.
When a class can inherit features from more than one parent class, the class is supposed to show multiple inheritance.
Ruby does not support multiple inheritance directly but Ruby Modules have another wonderful use. At a stroke, they pretty much eliminate the need for multiple inheritance, providing a facility called a mixin.
module A def a1 end def a2 end end module B def b1 end def b2 end end class Sample include A include B def s1 end end samp=Sample.new samp.a1 # From module A samp.a2 # From module A samp.b1 # From module B samp.b2 # From module B samp.s1 # Instance method
In the example above, the object of the class Sample is able to call the methods of the module A as well as module B. Hence, we get the multiple inheritance.
Include vs Extend
Modules can either be included or extended depending on whether the methods will be added as instance methods or class methods, respectively.
# Include the Module module Calculator def add(x,y) x + y end end class A include Calculator def calculate add(2,3) end end p = A.new puts p.calculate # Puts 5
In the example above a Calculator module is defined which sums up two integers via the add method. The A class includes the Calculator module which will add its methods as instance methods to the A class. It’s worth noting that everything defined in the module is added to the class including methods (public, protected, private), attributes (e.g. attr_accessor :name) and constants.
If instead we wanted to provide a add via a class method I’d use the extend method as shown below.
# Extend the Module module Calculator def add(x,y) x + y end end class A extend Calculator end puts A.add(4,5) # Puts 9
It’s also possible to mixin a module to a single instance at runtime as shown in the following example.
# Extending the Module at the runtime class B; end b = B.new b.extend Calculator puts b.add(5,2)
Another common pattern is to define a module that will mixin instance and class methods.
module AcmeModel def self.included(base) base.extend(ClassMethods) end def brand "acme" end module ClassMethods def all # get all of the AcmeModel instances  end end end class Widget include AcmeModel end w = Widget.new w.brand # "acme" is the output, Widget.all # invoke the class method that was added
In this example the AcmeModel provides an instance method named brand. More importantly it overrides the included class method, provided by the Module class. The included method is a callback that gets invoked whenever the module is included by antoher class or module. At that point we extend the class that included the AcmeModel, the Widget class in this example, with the ClassMethods module.
Lastly, you should also know that your module can override the extended class method which acts as callback when the module is extended.