Skip to main content

Ruby on Rails Part 3 - Modules and mixins

 Ruby on Rails Part 3 - Modules and mixins

Table of content

  1. Modules
  2. Inside a module method
  3. require vs include vs extend
  4. Mixins
  5. Accessing variable
  6. Class vs instance methods

Modules

A Module is a collection of methods, constants, and class variables. Modules are defined as a class, but with the module keyword instead of class keyword. The name of a module must start with a capital letter.

You cannot inherit modules using the i.e. you cannot create a subclass of a module. You cannot create an objects of a module.
 Modules are used for namespaces and as mixins.


All the classes are modules, but all the modules are not classes.  A class can use namespaces, but they cannot use mixins like modules.

The syntax for declaring a module is :

module Module_name
    # statements to be executed
end 
 
 
module ModuleName # Create a module
C = 10; # Module constant
# Method name must be preceded by the module name, this is a module method
def ModuleName.methodName
puts "Inside a module method!"
end
end

puts ModuleName::C # This is how to use a module Constant
ModuleName.methodName # calling the methods of the module 
 

 Output 

 
$ ruby module_example.rb
10
Inside a module method!
 

Inside a module method

We can define a method with def keyword inside a module i.e. def method_name then it is considered as an instance method. We cannot access instance method directly using MODULE_NAME. use of the dot operator as he cannot make the instance of the module. 

To access the instance method defined inside the module, we have to include the module inside a class and then use the class instance to access that method. Below example illustrate 
this concept. 


We include the module in the class. In this case, the 
module works like a namespace. 


 
module SomeModule
def inst_method
puts "Inside instance method of module"
end

def SomeModule.moduleMethod
puts "Inside class method of module"
end
end

class SomeClass
include SomeModule # include a module in a class
def instSomeClassMethod
puts "Inside class method"
end
end
obj = SomeClass.new
obj.instSomeClassMethod # class instance method can be called using the object
obj.inst_method # module instance method can be called using the ONLY object
SomeModule.moduleMethod # Module method can only be called using module name
 

Output

 
$ ruby module_methods.rb
Inside class method
Inside instance method of module
Inside class method of module
$
 

require vs include vs extend
1. include: is used to include modules in a class at instance level. In short, you need to create an object of the class to access the module’s method. Multiple modules can be included using comma separated statements.
2. extend: is used to include modules in a class at class/static level. In short, you don't need to create an object of the class to access the module’s method. These methods can be 
directly accessed using class name.
3. require: is similar to import statement in Java. It’s used to add dependent modules to your code.

Let us assume below two modules in headerfile.rb


# This is a seperate file named headerFile.rb
module ModuleName
I = 10
def ModuleName.methodName
puts "Inside headerFile >> ModuleName.methodName"
end
end

module ModuleName2
I = 10
def ModuleName2.methodName
puts "Inside headerFile >> ModuleName2.methodName"
end
end 
 

The headerFile.rb module is included in mutiple_modules.rb file as below.


# This is the main file multiple_modules.rb

require './headerFile.rb'         # added headerFile.rb using require
class ClassName
include ModuleName, ModuleName2 # inclue modules from headerFile.rb to this class

def classMethod
ModuleName2.methodName      # calling the module method in the class
end
end

obj = ClassName.new
obj.classMethod

 Output

 
$ ruby multiple_modules.rb
Inside headerFile >> ModuleName2.methodName
 

Mixins   

Ruby does not support multiple inheritance directly and instead uses a facility called mixin.

Mixins in Ruby allows modules to access instance methods of another using the include keyword.

In OOP languages, a mixin (or mix-in) is a class that contains methods for use by other classes/modules without the need to inherit from others.

Mixins are an example of has-a relationship and not is-a relationship.


module Base_1
def a1
puts 'This is Base one.'
end
end
module Base_2
def a2
puts 'This is Base two.'
end
end
module Base_3
@val
def a3
puts 'This is Base three.'
end
end
# include all 3 modules in below class
class SubClass
include Base_1
include Base_2
include Base_3
def display
puts "Three modules have been included"
end
end

obj = SubClass.new
obj.display
obj.a1
obj.a2
obj.a3
 

Output

 
$ ruby mixin_example.rb
Three modules have been included
This is Base one.
This is Base two.
This is Base three.
 

Above same example can be implemented in a hierarchical mixin.


module Base_1
def a1
puts 'This is Base one.'
end
end

module Base_2
include Base_1 # include Base_1 in Base_2
def a2
puts 'This is Base two.'
end
end

module Base_3
include Base_2 # include Base_3 in Base_3
def a3
puts 'This is Base three.'
end
end

class SubClass
include Base_3 # include Base_3 in SubClass
def display
puts "Three modules have been included"
end
end

obj = SubClass.new
obj.display
obj.a1
obj.a2
obj.a3
 

Output

 
$ ruby hierarchy_mixin.rb
Three modules have been included
This is Base one.
This is Base two.
This is Base three.
 

Accessing Variables

In Ruby, object methods are public by default, while data members is private.
 To access and modify data members we have the attr_reader and attr_writer. These attribute define the getter and setter methods for the data member.


 attr_accessor is a shortcut method when you need to do both attr_reader and attr_writer 

Below example illustrates the use attr_accessor.

 
class ClassName

attr_accessor :name # attr_accessor internally creates a getter and setter method
# It maps the variables to class's instance variable using the symbol :name

def initialize(name)
@name = name
end
end

obj = ClassName.new("Hello")
puts obj.name
obj.name = "SWE Crunch Team"
puts obj.name
 

 Output

 
$ ruby attribute_accessor.rb
Hello
SWE Crunch Team
 

Class vs Instance Methods  

A class method is defined using self. It is similar to static method in other languages
. These methods are called using class.

An instance method is defined without using self. These methods can only be called from an object.
 An instance method cannot be called from a class method and vice-versa


class ClassName
def instanceMethod
puts "Instance method"
end
def self.classMethod
puts "Class method"
end
end
obj = ClassName.new

obj.instanceMethod # instance methods can be called by instances (objects) only
ClassName.classMethod # class methods can only be called by the class only

 Output

 
$ ruby class_inst.rb
Instance method
Class method
 

 We cannot call class method from instance method and vice-versa. 

 
class ClassName
def instanceMethod
self.classMethod # This throws an error as you cannot call a class method from an instance method
end

def self.classMethod
instanceMethod # This throws an error as you cannot call an instance method from a class method
end
end

obj = ClassName.new
obj.instanceMethod
# ClassName.classMethod 
 

Output

 
$ ruby class_m_from_instance.rb
class_m_from_instance.rb:3:in `instanceMethod': undefined method `classMethod' for #<ClassName:0x00007ffa5711c160> (NoMethodError)
from class_m_from_instance.rb:12:in `<main>'
$
 

Calling instance method in a class method.

 
class ClassName
def instanceMethod
self.classMethod # This throws an error as you cannot call a class method from an instance method
end

def self.classMethod
instanceMethod # This throws an error as you cannot call an instance method from a class method
end
end

obj = ClassName.new
#obj.instanceMethod
ClassName.classMethod 
 

Output

 
$ ruby instance_m_from_class.rb
instance_m_from_class.rb:7:in `classMethod': undefined local variable or method `instanceMethod' for ClassName:Class (NameError)
from instance_m_from_class.rb:13:in `<main>'
 

Thank you folks. If you like this Ruby on Rails post, please do checkout my other post on  Django with Python 3 series, Ruby on Rails

Most viewed

Ruby on rails part 6 - Blocks , lambda, procs and closure

 Blocks , lambda, procs  and closure Table of content  1. Blocks 2. Lambda 3. Procs 4. Closure Blocks  Ruby blocks are little anonymous functions that can be passed into methods. Blocks are enclosed in a do-end statement or between brackets {} 
. Blocks can have multiple arguments
. The argument names are defined between two pipe | characters. Blocks are typically used with ‘each’ method which iterates over a list. Syntax of block using {} ['List of items'].each { | block arguments|  block body }  Syntax of block using do-end ['List of items'].each do | block arguments |      # block body end Example of block declared as do-end with each method.   [ 1 , 2 , 3 ].each do |num| puts num end     Output   $ ruby block_with_each.rb 1 2 3 $    Blocks can also be saved in variables or passed as argument to another function.   yield is a Ruby keyword that is used to call a block. When you use the yield keyword, the code inside the block will run. Example of saving a bl