Ruby Modules


Modules are a way of grouping together methods, classes, and constants. Modules give you two major benefits.

Modules define a namespace, a sandbox in which your methods and constants can play without having to worry about being stepped on by other methods and constants.

Syntax:

      module Identifier
         statement1
         statement2
         ...........
      end
      

Module constants are named just like class constants, with an initial uppercase letter. The method definitions look similar, too: module methods are defined just like class methods.

As with class methods, you call a module method by preceding its name with the module.s name and a period, and you reference a constant using the module name and two colons.

Example:

      # Module defined in trig.rb file
      
      module Trig
      	VERSION = '2.0.3'
      	PA = 5.4321
      	def self.magic(x)
          x + PA
      	end
      end
      

We can define one more module with same function name but different functionality:

      # Module defined in moral.rb file
      
      module Moral
      	VERSION = '3.5.1'
      	PE = 1.2345
      	BAD = 2
      	VERY_BAD = 5
      	def self.magic(badness)
          badness + PE
      	end
      end
      

Like class methods, whenever you define a method in a module, you specify the module name followed by a dot and then the method name.

 

Ruby require Statement:

The require statement is similar to the include statement of C and C++ and the import statement of Java. If a third program wants to use any defined module, it can simply load the module files using the Ruby require statement:

Syntax:

      require filename
      

Here it is not required to give .rb extension along with a file name. Allowing you to require even C extensions, etc.

Example:

      require 'trig.rb'
      require 'moral'
      puts '======='
      puts Trig.magic(31)
      puts Moral.magic(53)
      puts '======='
      puts Trig.magic(Moral::BAD)
      puts Moral.magic(Trig::PA)
      puts '======='
      puts Moral::VERSION
      puts Trig::VERSION
      puts '======='
      

This will produce following result:

      =======
      36.4321
      54.2345
      =======
      7.4321
      6.6666
      =======
      3.5.1
      2.0.3
      =======
      

IMPORTANT: Here both the files contain same function name. So this will result in code ambiguity while including in calling program but modules avoid this code ambiguity and we are able to call appropriate function using module name.

 

Ruby include Statement:

You can embed a module in a class. To embed a module in a class, you use the include statement in the class:

Syntax:

      include modulename
      

If a module is defined in separate file then it is required to include that file using require statement before embeding module in a class.

Example:

Consider following module written in Week.rb file.

      module Week
         FIRST_DAY = "Sunday"
         def self.weeks_in_month
            puts "You have four weeks in a month"
         end
         def self.weeks_in_year
            puts "You have 52 weeks in a year"
         end
      end
      

Now you can include this module in a class as follows:

      require "Week"
      
      class Decade
      	include Week
      	@@no_of_yrs=10
      	def no_of_months
          puts Week::FIRST_DAY
          number=@@no_of_yrs * 12
          puts number
      	end
      end

      d1=Decade.new
      puts Week::FIRST_DAY
      Week.weeks_in_month
      Week.weeks_in_year
      d1.no_of_months
      

This will produce following result:

      Sunday
      You have four weeks in a month
      You have 52 weeks in a year
      Sunday
      120
      

There is another way to add a module to your class: the extend statement.

      require "Week"
      
      class Decade
      extend Week
         .
         .
         .
      end
      

The include statement causes all the methods in the module to be added as instance methods, and also allows the constants to be accessed through the method. In contrast, the extend statement adds all the methods as class methods, and does nothing with the constants.

 

Mixins in Ruby:

When a class can inherit features from more than one parent class, the class is supposed to show multiple inheritance.

Ruby does not suppoprt mutiple 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.

Mixins give you a wonderfully controlled way of adding functionality to classes. However, their true power comes out when the code in the mixin starts to interact with code in the class that uses it.

Let us examine the following sample code to gain an understand of mixin:

      module BIG

        module A
          def a1
            puts 'a1'
          end
          def a2
            puts 'a2'
          end
        end
        
        module B
          def b1
            puts 'b1'
          end
          def b2
            puts 'b2'
          end
        end
        
        class Sample
        include A
        include B
        PI = 3.141592654
            def s1
                puts 's1'
            end
        end
    
        def c1
            mod_sample = Sample.new
            puts Sample::PI
            mod_sample.s1
        end

      end
      include BIG
      BIG::c1
      samp=BIG::Sample.new
      samp.a1
      samp.a2
      samp.b1
      samp.b2
      samp.s1
      

This will produce following result:

      3.141592654
      s1
      a1
      a2
      b1
      b2
      s1
      

Module BIG, consists of the modules A, B and C and the class Sample. Module A consists of the methods a1 and a2. Module B consists of the methods b1 and b2. Module C consists of the method c1. The class Sample includes both modules A and B. The class Sample can access all four methods, namely, a1, a2, b1, and b2. Therefore, you can see that the class Sample inherits from both the modules. Thus you can say the class Sample shows a mixin. And you can see that methods from the BIG module can call methods and access constants from the Sample class.