Using Modules in Ruby
Tags: ruby, beginners, codenewbie, tutorial
Published: 2020-11-10 05:31:41

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/aboubggm38vfsi5uq074.png)

Welcome back dear friends, dear readers, coders, and enthusiasts!
  
Welcome to our next article where we present the preciousness of our beloved Ruby PL. This time we are going to look through the “Modules” topic in Ruby. We will also strengthen our learning by showing some examples of how to use Modules in Ruby.
  
....................................................
  
# What are the Modules?
  
In short, a Module is a way to gather classes, methods, and constants under one roof. To expand the topic a bit wider, this gives us two widely used methodologies in programming.
  
1. **Collection** — *otherwise named as a ‘namespace’, gives us an opportunity to gather classes, methods, and constants under a single roof.*
  
2. **Mixin** — *a mechanism to include a ready module into another class and use its content (methods, values, constants) as its own. Thus we can expand the possibilities of that class.*
  
After mentioning its advantages in general, let’s dive deeper into it and look at the above-mentioned items in detail. We will also provide explanations with code examples where possible.
  
....................................................
  
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/93ei1qugi25jv74nidl6.jpeg)
  
# 1. Collection
  
Imagine such a situation. You decided to collect together operators, functions, and all the related data into one place. Why should we not make it a module?
  
```
module Trig
   PI = 3.1416 # A Constant  
   
   Trig.sin(x)
      #...
   end   
   
   Trig.cos(x)
      #...
   end
   ...
   ...
end
```
  
We can use the above-defined methods and constants somewhere else. Let’s use this module to perform trigonometric calculations. Here is an example:
  
```
radius = 6

# Here we call a constant named 'PI' from module 'Trig'
area = Trig.PI*radius**2 # PI*R^2 formula

# Let's calculate sine and cosine of the angle.
# Here we call 'sin' and 'cos' methods from
# 'Trig' module.

angle = 45
sine = Trig.sin(angle)
cosine = Trig.cos(angle)
```
  
If these examples are a bit easy for you, we can take a look at more complex ones. Now, let’s take a look at a module that comprises several classes in it.
  
You decided to develop a ‘Customer’ class. It has a few properties and methods. Depending on the context, a customer can act differently. So let’s write a class that has a bit different methods and properties depending on the type of customer in a particular situation, and place them in different modules.
  
```
module Bank
   class Customer # A bank customer.
      attr_accessor :balance, first_name, last_name
  
      def put_cash(sum)
         puts "#{sum} amount of cash was put."
      end      

      def withdraw(sum)
         puts "#{sum} amount was withdrawn."
      end
   end
end

module Shop
   class Customer # A shop customer
      attr_accessor :products

      def pay_for_products
         products.each do |product|
            puts "#{product} bought."
         end
      end
      ...
      ...
   end
end
```
  
I hope you paid attention to how we separated the issues and placed two different customers in two different modules. Both of the modules have ‘Customer’ class, but they behave differently. In other words, they have different methods and properties. If we have defined both classes in the same namespace, we would have had a conflict. And that would be a name conflict at least, not to mention the others. Ruby would not have allowed us to write the same-named class within the same namespace. So we just place them in different modules and no conflicts comes up.
  
Now we can easily call and use the ‘Customer’ class and its methods in the following examples:
  
```
# Example - 1
bank_customer = Bank::Customer.new
bank_customer.balance = 25
bank_customer.first_name = "John"
bank_customer.last_name = "Brown"
bank_customer.withdraw(50)

# Example - 2
shop_customer = Dukan::Customer.new
shop_customer.products = ["apple", "fig", "bread", "milk"]
shop_customer.pay_for_products
```
  
As you see in the examples above, by placing classes, modules, and constants into different modules we can avoid name conflicts and have them being used within the right context.
  
Now let’s take a look at how we can use them as Mixins.
  
...................................................
  
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/f94yvaaerlzstg6z5vtl.jpeg)
  
# 2. Mixins
  
### Example A : Class relationships
  
There is a bit complex relationship matter called ‘inheritance’ in the programming world. It is a case when a class is a child/subclass of another one, that we call as ‘parent’. This way a child class possesses the features and methods of a parent class. Here is an example of this:
  
```
# Define a class for animals.
class Animal
   attr_accessor :name, :category  
 
   def make_noise
      puts 'Making noise...'
   end   

   def move
      puts 'Moving...'
   end
end
```
  
The next classes to be defined are somewhat part of, or subpart of an ‘Animal’ class. And they will possess the features and methods of an ‘Animal’ class. So, let’s define classes ‘Fish’ and ‘Bird’ and make them as child classes of an ‘Animal’ class. ‘Ruby’ PL makes it this way:
  
```
# 'Fish' class
class Fish < Animal
   ...
end

# 'Bird' class
class Bird < Animal
   ...
end
```
  
Now we can call methods of an ‘Animal’ class and use its properties from within ‘Fish’ and ‘Bird’ classes.
  
```
a_fish = Fish.new
a_fish.name = 'Ariel'
a_fish.make_noise # 'Making noise...'

a_bird = Bird.new
a_bird.name = 'Dove'
a_bird.move # 'Moving...'
```
  
### Example B : Mixins
  
Now, getting inspired by the examples above, let’s write something a bit different. A film, an advertisement, a clip are all Videos. We can ‘play’ them and ‘pause’ them all.
  
Besides that, we can download them onto our PC or mobile device. Suppose we can download only video, only audio, or both at the same time. We have ‘Download’ module for this.
  
So let’s define ‘Video’ and ‘Download’ modules for this purpose.
  
```
# 'Video' module
module Video
   def play
      puts 'Playing ...'
   end   

   def pause
      puts 'Paused...'
   end
end

# 'Download' module
module Download
   def download_video
      puts 'Downloading only video...'
   end
   
   def download_audio
      puts 'Downloading only audio...'
   end   

   def download_both
      puts 'Download audio & video...'
   end
end
```
  
Now let’s define other 3 classes and make methods of ‘Video’ and ‘Download’ modules available to them.
  
```
# 'Film' class
class Film
   attr_accessor :title
   include Video
   include Download
end

# 'Advertisement' class
class Advertisement
   include Video
   include Download
end

# 'Clip' class
class Clip
   include Video
   include Download
end
```
  
Now we can use features of ‘Video’ and ‘Download’ modules after making them available within those lately defined classes. Here is an example:
  
```
# 'Film' class
silence = Film.new
silence.title= 'The Silence of Lambs'
silence.play  # 'Playing ...'
silence.download_both # Download audio and video

# 'Advertisement' class
cola_ad = Advertisement.new
cola_ad.play  # 'Playing ...'
cola_ad.download_audio # Download only audio

# 'Clip' class
drake_clip = Clip.new
drake_clip.play  # 'Playing ...'
drake_clip.download_video # Download only video
```
  
So we defined ‘Video’ and ‘Download’ as modules, and not classes. Lately, we made their features available to the other three classes. We used ‘include’ keyword for that.
   
### Differences between Example A and Example B
  
The relationship between a Parent and a Child class is very important in programming. We implement it with a mechanism called ‘inheritance’ and avoid writing excess code. Thus we support DRY (Don’t Repeat Yourself).
  
Both ‘A’ and ‘B’ examples are doing almost the same thing but there are few differences between them. A Ruby class can not inherit from multiple classes at the same time. In other words, a class can not have multiple parent classes at the same time. So we could not inherit from ‘Video’ and ‘Download’ classes at the same time. For this reason, we implemented ‘Video’ and ‘Download’ as modules and used them as Mixins in ‘Film’, ‘Advertisement’, and ‘Clip’ classes.
  
.................................................

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/z0824cxud8eu265h3noq.jpeg)
  
# Conclusion
  
And now, we introduced our beloved Ruby PL closer and learned how to implement Modules in it. Besides that, we learned in which cases we should implement something as a Class or as a Module.
  
One of the famous modules in Ruby PL are ‘Enumerable’ and ‘Comparable’ modules. By including these modules into your custom classes, you add comparison and numerating functionality to your own classes. This way you can compare two instances of your own class and iterate through its elements if it is a type of collection.
  
Hope to meet you soon in the next article, dear friends.
Stay healthy, wealthy, and wise!