Ruby 2 Modules Mixins

Ruby Modules are similar to classes in that they hold a collection of methods, constants, and other module and class definitions. Modules are defined much like classes are, but the module keyword is used in place of the classkeyword. Unlike classes, you cannot create objects based on modules nor can you subclass them; instead, you specify that you want the functionality of a particular module to be added to the functionality of a class, or of a specific object. Modules stand alone; there is no "module hierarchy" of inheritance. Modules is a good place to collect all your constants in a central location.
Modules serve two purposes:
  • First they act as namespace, letting you define methods whose names will not clash with those defined elsewhere. The examples p058mytrig.rb, p059mymoral.rb, p060usemodule.rb illustrates this.
  1. # p058mytrig.rb  
  2. module Trig  
  3.   PI = 3.1416  
  4.   # class methods  
  5.   def Trig.sin(x)  
  6.     # ...  
  7.   end  
  8.   def Trig.cos(x)  
  9.     # ...  
  10.   end  
  11. end  
  12.   
  13. # p059mymoral.rb  
  14. module Moral  
  15.   VERY_BAD = 0  
  16.   BAD         = 1  
  17.   def Moral.sin(badness)  
  18.     # ...  
  19.   end  
  20. end  
  21.   
  22. # p060usemodule.rb  
  23. require_relative 'p058mytrig'  
  24. require_relative 'p059mymoral'  
  25. Trig.sin(Trig::PI/4)  
  26. Moral.sin(Moral::VERY_BAD)  
  • Second, they allow you to share functionality between classes - if a class mixes in a module, that module's instance methods become available as if they had been defined in the class. They get mixed in. The program p061mixins.rb illustrates this.
  1. # p061mixins.rb  
  2. module D  
  3.   def initialize(name)  
  4.     @name =name  
  5.   end  
  6.   def to_s  
  7.     @name  
  8.   end  
  9. end  
  10.   
  11. module Debug  
  12.   include D  
  13.   # Methods that act as queries are often  
  14.   # named with a trailing ?  
  15.   def who_am_i?  
  16.     "#{self.class.name} (\##{self.object_id}): #{self.to_s}"  
  17.   end  
  18. end  
  19.   
  20. class Phonograph  
  21.   # the include statement simply makes a reference to a named module  
  22.   # If that module is in a separate file, use require to drag the file in  
  23.   # before using include  
  24.   include Debug  
  25.   # ...  
  26. end  
  27.   
  28. class EightTrack  
  29.   include Debug  
  30.   # ...  
  31. end  
  32.   
  33. ph = Phonograph.new("West End Blues")  
  34. et = EightTrack.new("Real Pillow")  
  35. puts ph.who_am_i?  
  36. puts et.who_am_i?  
Observe how we use require or loadrequire and load take strings as their arguments.

require 'motorcycle' or load 'motorcycle.rb'

include takes the name of a module, in the form of a constant, as in include Stuff.

The include method accepts any number of Module objects to mix in:
include Enumerable, Comparable

Although every class is a module, the include method does not allow a class to be included within another class.
Some more examples:
  1. #  p062stuff.rb  
  2. #  A module may contain constants, methods and classes.  
  3. #  No instances  
  4.   
  5. module Stuff  
  6.   C = 10  
  7.   def Stuff.m(x)  # prefix with the module name for a class method  
  8.     C*x  
  9.   end  
  10.   def p(x)        # an instance method, mixin for other classes  
  11.     C + x  
  12.   end  
  13.   class T  
  14.     @t = 2  
  15.   end  
  16. end  
  17. puts Stuff::C     # Stuff namespace  
  18. puts Stuff.m(3)   # like a class method  
  19. x = Stuff::T.new  
  20. # uninitialized constant error, if you try the following  
  21. # puts C  
  22.   
  23. #------------  
  24.   
  25. # p063stuffusage.rb  
  26. require_relative 'p062stuff'     # loads Stuff module from Stuff.rb  
  27.                     # $: is a system variable -- contains the path for loads  
  28. class D  
  29.   include Stuff     # refers to the loaded module  
  30.   puts Stuff.m(4)  
  31. end  
  32.   
  33. d = D.new  
  34. puts d.p(5)         # method p from Stuff  
  35. puts $:             # array of folders to search for load  
  36. $: << "c:/"         # add a folder to the load path  
  37. puts $:  
  38. puts Stuff.m(5)     # Stuff class methods not called from D object  
Remember that you can mix in more than one module in a class. However, a class cannot inherit from more than one class. Class names tend to be nouns, while module names are often adjectives.
IN RAILS: The Rails source code makes heavy use of modules, in particular the technique of reopening the definition bodies of both classes and modules.