Modules in Ruby are a way to group related methods, constants, and classes together.
They are similar to classes but cannot be instantiated. Modules are primarily used for namespacing and mixins.
What You’ll Learn
1. What Are Modules?
A module in Ruby is a collection of methods and constants. Modules serve two main purposes:
- Namespacing: Avoiding name collisions by grouping related code.
- Mixins: Adding shared functionality to classes using include or extend.
2. Defining and Using Modules
Syntax
module ModuleName # Methods and constants end
Example: Basic Module
module Greetings
def self.say_hello
puts "Hello!"
end
end
# Accessing module method
Greetings.say_hello # Output: Hello!
3. Including Modules (Mixins)
Including a module allows its methods to be added as instance methods to a class.
Syntax
class ClassName include ModuleName end
Example: Adding Instance Methods
module Greetings
def say_hello
puts "Hello from a module!"
end
end
class Person
include Greetings
end
person = Person.new
person.say_hello # Output: Hello from a module!
4. Extending Modules
Extending a module adds its methods as class methods.
Syntax
class ClassName extend ModuleName end
Example: Adding Class Methods
module Greetings
def say_hello
puts "Hello from a module!"
end
end
class Person
extend Greetings
end
Person.say_hello # Output: Hello from a module!
5. Using Modules for Namespacing
Modules can be used to group related classes or methods, avoiding name collisions in large projects.
Example: Namespacing
module MathTools
class Calculator
def add(a, b)
a + b
end
end
end
calc = MathTools::Calculator.new
puts calc.add(5, 3) # Output: 8
6. Practical Examples
6.1 Using Constants in Modules
Modules can define constants that are accessible with the :: operator.
module Settings DEFAULT_LANGUAGE = "English" end puts Settings::DEFAULT_LANGUAGE # Output: English
6.2 Multiple Modules in a Class
A class can include multiple modules, allowing it to inherit behaviors from several sources.
module Greetings
def greet
puts "Hello!"
end
end
module Farewell
def say_goodbye
puts "Goodbye!"
end
end
class Person
include Greetings
include Farewell
end
person = Person.new
person.greet # Output: Hello!
person.say_goodbye # Output: Goodbye!
6.3 Using prepend
The prepend keyword adds module methods before the methods defined in the class.
module Greetings
def greet
puts "Hello from the module!"
end
end
class Person
prepend Greetings
def greet
puts "Hello from the class!"
end
end
person = Person.new
person.greet # Output: Hello from the module!
6.4 Mixing in Enumerable
The Enumerable module provides useful methods like map, select, and reduce.
class CustomCollection
include Enumerable
def initialize(elements)
@elements = elements
end
def each(&block)
@elements.each(&block)
end
end
collection = CustomCollection.new([1, 2, 3, 4])
puts collection.map { |x| x * 2 }.inspect # Output: [2, 4, 6, 8]
6.5 Using extend for Specific Objects
You can use extend to add module methods to a single object.
module Greetings
def greet
puts "Hello from an extended module!"
end
end
person = Object.new
person.extend(Greetings)
person.greet # Output: Hello from an extended module!
6.6 Module Aliases and Refinements
Modules can alias methods or refine behavior for specific use cases.
Alias Example
module Greetings
def say_hello
puts "Hello!"
end
alias greet say_hello
end
class Person
include Greetings
end
person = Person.new
person.greet # Output: Hello!
Refinements
module StringExtensions
refine String do
def shout
upcase + "!!!"
end
end
end
using StringExtensions
puts "hello".shout # Output: HELLO!!!
6.7 Combining Namespaces and Mixins
module Utility
module MathTools
def add(a, b)
a + b
end
end
module StringTools
def reverse_string(str)
str.reverse
end
end
end
class Calculator
include Utility::MathTools
end
class TextProcessor
include Utility::StringTools
end
calc = Calculator.new
puts calc.add(5, 7) # Output: 12
text = TextProcessor.new
puts text.reverse_string("Ruby") # Output: ybuR
7. Best Practices for Using Modules
- Use for Shared Behavior: Use modules to define methods that multiple classes can share.
- Avoid Excessive Nesting: Deeply nested modules can make your code harder to read.
- Prefer Mixins for Reusability: Use include for instance methods and extend for class methods.
- Keep Methods Focused: Group related methods together within a module.
- Leverage Namespacing: Use modules to avoid name collisions in large projects.
8. Summary
Key Concepts
- Modules are collections of methods and constants that cannot be instantiated.
- Use include for instance methods, extend for class methods, and prepend to prioritize module methods.
- Modules help organize code and avoid name conflicts through namespacing.
Examples in Context
Ruby modules are a powerful tool for organizing code, sharing behaviors across classes, and creating clean, reusable components.
