Ruby modules are collections of methods and constants. Although they appear similar to classes, they (1) do not contain variables, (2) cannot create instances and (3) cannot have subclasses.
Like a Toolbox
Modules are more like a toolbox full of neat tools and supplies. If you wanted to build a house, you might use one set of tools and supplies, whereas building electronics may require another set of tools and supplies. Modules are a way to organize your tools and supplies into useful receptacles so you don’t need to physically create or gather the necessary tools and supplies for every project.
When you think of a module like a set of tools and supplies to be used for various tasks, it’s easy to understand why modules contain constants but not variables. Including a variable in a module doesn’t make sense. If a tool or supply has to be modified before it can be used for a house vs. a computer, it probably shouldn’t be in the toolbox for house or computer. Instead, it would make more sense store that tool or supply separately.
Preexisting Modules
Ruby has its own set of preexisting modules, or toolkits, that are useful for building many things. Two commonly used modules are the Date and Math modules. For example, if we wanted to know today’s date, we could use the Date module as follows: puts Date.today.
Creating Modules
Sometimes you need to create new tools and supplies for a project, and you can do so by creating a new module. Modules are created in a similar manner to classes, exceptclass is replaced by module. The module name is in CamelCase.
module ModuleName end
Namespacing
Namespacing is the term used to describe a module’s purpose – to separate methods (tools) and constants (supplies) into named spaces. Going back to our toolbox example, the named space for tools to build a home might be the standard toolkit and the named space for tools to build a computer may be the electronics toolkit. If these were coded, they would be module StandardToolkit and module ElectronicsToolkit.
Scope Resolution
The scope resolution operator is ::. This is used to define the scope of a constant. Using the above example:
def StandardToolkit SUPPLY1 = "wood" SUPPLY2 = "nails" end def ElectronicsToolkit SUPPLY1 = "metal" SUPPLY2 = "glass" end
If SUPPLY1 is used in our program, how do we know which supply we’re talking about? We define the scope of SUPPLY1 with the :: as follows: StandardToolkit::SUPPLY1 or ElectronicsToolkit::SUPPLY1. This way, there is no confusion as to which supply is being used.
Including Modules
Some modules are already included in Ruby. To include others, we have to manually include them with require ‘module’. In the above example, to use the Date module, we would need to include require ‘date’ above our code.
If we want to include a module within a class, we do so slightly differently with include Module. If you recall from Ruby Classes, a class can only inherit the attributes of one class. Ruby does not allow for inheritance from more than one class. However, including a module within a class is allowed. This is called:
Mixin
Mixin is what happens when a class and a module are mixed together. This allows us to customize a class without having to manually code its attributes, and allows for additional customization where a class has already inherited the attributes of another class. This is best understood through an example:
module StandardToolkit def nails puts "The number of nails needed for this project is #{@nails}." end end class Chair include StandardToolkit attr_accessor :corners def initialize(corners) @corners = corners @nails = @corners * 4 end end class Table include StandardToolkit attr_accessor :corners def initialize(corners) @corners = corners @nails = @corners * 6 end end kitchen_chair = Chair.new(6) kitchen_table = Chair.new(4) dining_table = Table.new(8) night_table = Table.new(4) kitchen_chair.nails kitchen_table.nails dining_table.nails night_table.nails
The output for this code is:
The number of nails needed for this project is 24. The number of nails needed for this project is 16. The number of nails needed for this project is 48. The number of nails needed for this project is 24.
As you can see, each class included the module StandardToolkit and was able to call the nails method to tell us how many nails are needed for each chair and table.
Include vs. Extend
In the above example, we usedinclude to mix the module’s methods at the instance level. This applies the tools in the module StandardToolkit to instances (objects) of the class Chair and the class Table.
If we were to use extend Module, the module Standard Toolkit would be mixed at the class level and its methods would be class methods. See Ruby Classes for more information about instance methods vs. class methods.
- PM Career Story - April 28, 2022
- How to Transition into Product Management - December 26, 2017
- What I’ve Learned in My First Few Months as a Product Manager - October 14, 2015
Comments