CodeX
Published in

CodeX

Modules in Ruby

The one that cannot be instantiated like the Class!

Prerequisite

To better understand this topic, I would recommend that you have a solid knowledge of Classes in Ruby.

Definition

Module is a collection of constants, methods, classes, and variables in a container.

Topics covered in this article

It's similar to a Class but the key difference is that modules cannot be instantiated like the Classes.

# module begins
module Test
# end of scope
end

A module is initiated by module keyword followed by ‘module_name’, Testwith an initial letter as an uppercase, because they’re constants. And finally ending its scope by end keyword.

Nested modules

Yes! Modules can be nested too, just as nested classes or nested methods.

We can directly access the inner module Inner, by calling its parent module Outer followed by a double colon operator :: followed by name of the inner module. (Line #9)

We can also reopen the module just like we can reopen Rubys’ built-in classes or our own defined classes, and directly access the inner module, as shown in line #12. This style benefits the programmer to reduce the number of indentations from 2 lines to 1.

Constants in a Module

We access constants of a module by giving module_name, Test, followed by double colon operator, ::, followed by constant_name, Module_constant.

The Module_constant is a constant object which is available to be accessed by the methods, classes, and modules defined inside the module Test. However, the constant is not accessible outside the scope of the module Test.

Methods in a Module

Defining & accessing both instance and module methods is similar to how we do for the Classes.

Since we cannot instantiate a Module as a Class, accessing instance methods will be later discussed in this article in section Mixin.

Class in a Module

Just as we can access constants from the Module, we can access classes outside the Module's scope.

Why use a Module instead of a Class?

For these 2 reasons :

  1. Namespace
  2. Mixin

Let’s discuss it:

Namespace

Namespace is a way of bundling logically related objects together. It allows classes or modules with conflicting names to co-exist while avoiding collisions.

An example of this is the Rails module.

Here Application class is defined within the scope of a Rails Module.

As the Application class is a pretty common class name that we could encounter in another gem, so to avoid clashing of similar names, the Application class is encapsulated in the Rails module.

This means that class Rails::Application will never clash with an Application class or Other_gem::Application class defined anywhere else.

Mixin

Mixin is a facility in which a module can be called in another module or class by using include, prepend and extend keywords.

Include:

Here, we create a class Klass outside the scope of the module Mod, and we make Mod modules’ instance methods available as an instance to the class Klass.

When we call .ancestors method to the Class Klass, it gives a list of classes and modules that Class Klass descends from.

Before we call include, the class Klass directly descends from Object, but after include call, the class Klass now directly descends from Module Mod.

The include keyword adds methods of the declared module to the class it's declared in as instance methods.

Or in other words:

The include keyword makes the module a parent of the class it's declared in an ancestor chain.

Therefore, when we call an instance method to the class Klass, they find an instance method in their parent Module Mod and gives output.

The module methods, however, are only available to module Mod itself.

Now what if we include 2 different modules with the same ‘method_name’ in a single class?

The 2nd module imported directly descends from 1st module.

So when we call method_1 it will first look if it’s available in class Klass, then it will go 1 step up the hierarchy to module Mod_2 to find the method, it finds it there and gives output.

If we remove the method_1 from Mod_1 this wouldn’t give any different output because it never goes there to find the method, however, if we remove method_1 from Mod_2 then it will find method_1 in Mod_1 and give its output.

prepend

The prepend keyword makes the module a child of the class it's declared in an ancestor chain.

Or,

The class where prepend keyword is declared is a parent of the declared module.

Therefore, when I give a method that is both available in module and class, it will first look in the module as its first member in the ancestor chain.

extend

The extend keyword adds instance methods of the declared module to the class it's declared in as class methods.

Or,

The extend keyword makes instance methods of the module an instance method to the singleton class of the class where extend is declared in.

In other words,

The extend keyword brings instance methods of a Module, Mod, as a singleton method of class Klass.

Klass.singleton_methods  
# => [:method_1]

The ancestor chain of the class Klass isn’t affected, but of the singleton class...

p Klass.singleton_class.ancestors[#<Class:Klass>, Mod, #<Class:Object>, #<Class:BasicObject>, Class, Module, Object, Kernel, BasicObject]

The module Mod is a parent of a singleton class Class:Klass. So when we call Klass.method_1, we are accessing method_1 from singleton class, Class:Klass.

Access module from different file

I have explained this in detail in this article.

Any suggestions or edits in this article are always welcome! Thank you!

My previous article: A Class in Ruby
My next article: An Enumerable Module in Ruby

--

--

--

Everything connected with Tech & Code. Follow to join our 900K+ monthly readers

Recommended from Medium

Hello World!!! of Kubernetes [Part 2]

Tech 101: How To Run Metabase On An EC2 Instance

Why Your Code Is A Graph

Chill Out: A Simple Cooldown System in Unity

How to install an SSL Certificate on Ubuntu?

Hack The Box | Mango Write-Up

Part-1: Turtle in Python. Don’t worry… it’s not slow.

Part 9: Buy Crypto with Fiat

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Juzer Shakir

Juzer Shakir

Rails | Ruby | Javascript | SQL | https://juzershakir.github.io/

More from Medium

Passing a Nested Array of Objects to a Controller to Update Associated Records in Rails

Object Calisthenics in Ruby

Introduction to Ruby on Rails

Ruby and Ruby on Rails