0
0
Rubyprogramming~15 mins

Module methods in Ruby - Deep Dive

Choose your learning style9 modes available
Overview - Module methods
What is it?
Module methods in Ruby are functions defined inside a module that can be called on the module itself or included in classes. Modules are like containers for methods and constants but cannot be instantiated like classes. Module methods help organize reusable code that can be shared across different parts of a program without inheritance.
Why it matters
Without module methods, Ruby programs would have more repeated code and less organized structure. They allow developers to group related functions together and share them easily, making code cleaner and easier to maintain. This reduces bugs and saves time when building larger applications.
Where it fits
Before learning module methods, you should understand Ruby classes, methods, and basic object-oriented programming. After mastering module methods, you can explore advanced topics like mixins, namespaces, and metaprogramming in Ruby.
Mental Model
Core Idea
Module methods are reusable functions grouped inside a module that can be called directly or mixed into classes to share behavior without inheritance.
Think of it like...
Think of a module as a toolbox filled with tools (methods). You can use the tools directly from the box or take some tools and add them to your own toolbox (class) to use them there.
┌───────────────┐
│   Module      │
│ ┌───────────┐ │
│ │ method_a  │ │
│ │ method_b  │ │
│ └───────────┘ │
└─────┬─────────┘
      │ include
      ▼
┌───────────────┐
│    Class      │
│ ┌───────────┐ │
│ │ method_a  │ │
│ │ method_b  │ │
│ └───────────┘ │
└───────────────┘
Build-Up - 7 Steps
1
FoundationWhat is a Ruby module?
🤔
Concept: Introduce the basic idea of a module as a container for methods and constants.
In Ruby, a module is a way to group methods and constants together. Unlike classes, you cannot create objects from modules. They are used to organize code and share functionality between classes. Here's a simple module: module Greetings def hello "Hello!" end end
Result
You have a module named Greetings that holds a method hello.
Understanding modules as containers helps you see how Ruby organizes reusable code without creating objects.
2
FoundationDefining module methods
🤔
Concept: Learn how to define methods inside a module and how they behave by default.
Methods inside a module are instance methods for classes that include the module. They are not callable directly on the module unless defined specially. Example: module Greetings def hello "Hello!" end end # You cannot call Greetings.hello directly here.
Result
Methods inside modules are not module methods by default; they become instance methods when included.
Knowing that module methods are not automatically callable on the module itself clarifies how Ruby treats methods inside modules.
3
IntermediateCreating module methods with self.
🤔Before reading on: do you think defining a method with self. inside a module makes it callable on the module itself or only when included? Commit to your answer.
Concept: Learn how to define methods that belong to the module itself, called module methods or singleton methods.
To make a method callable directly on the module, prefix it with self. inside the module: module Greetings def self.hello "Hello from module!" end end Now you can call: Greetings.hello # => "Hello from module!"
Result
The method hello is now a module method and can be called directly on Greetings.
Understanding self. inside modules unlocks how to create functions that act like static methods in other languages.
4
IntermediateUsing module methods as mixins
🤔Before reading on: do you think module methods defined with self. are included as instance methods when a module is included in a class? Commit to your answer.
Concept: Explore how module methods behave when a module is included in a class and how to share module methods as instance methods.
When you include a module in a class, only the instance methods (without self.) are added to the class. Module methods defined with self. are NOT included as instance methods. module Greetings def self.module_method "Module method" end def instance_method "Instance method" end end class Person include Greetings end Person.new.instance_method # works # Person.new.module_method # error
Result
Only instance_method is available to Person instances; module_method is not.
Knowing the difference prevents confusion about which methods are shared when including modules.
5
IntermediateUsing extend to add module methods
🤔Before reading on: do you think using extend with a module adds its instance methods as class methods or instance methods? Commit to your answer.
Concept: Learn how to add module methods as class methods using extend.
Using extend adds the module's instance methods as methods on the object or class itself. module Greetings def hello "Hello from extend!" end end class Person extend Greetings end Person.hello # => "Hello from extend!"
Result
Person class now has hello as a class method via extend.
Understanding extend helps you add behavior to classes or objects without inheritance.
6
AdvancedCombining module methods and mixins
🤔Before reading on: do you think a module can provide both instance methods and module methods simultaneously? Commit to your answer.
Concept: Explore how to define both instance methods and module methods in the same module for flexible reuse.
You can define instance methods normally and module methods with self. inside the same module: module Greetings def self.module_hello "Hello from module method" end def instance_hello "Hello from instance method" end end class Person include Greetings end Greetings.module_hello # works Person.new.instance_hello # works
Result
Module provides both callable module methods and instance methods when included.
Knowing this pattern allows you to design modules that serve multiple roles cleanly.
7
ExpertUsing module_function for dual behavior
🤔Before reading on: do you think module_function makes a method private, public, or both? Commit to your answer.
Concept: Learn about module_function which creates a module method and also makes the method available as a private instance method when included.
module_function copies instance methods as module methods and makes the original instance methods private. module Greetings def hello "Hello!" end module_function :hello end Greetings.hello # works class Person include Greetings def greet hello # works because hello is private instance method end end Person.new.greet # => "Hello!"
Result
hello is both a module method and a private instance method when included.
Understanding module_function reveals a powerful Ruby feature for flexible method sharing and encapsulation.
Under the Hood
Ruby modules are objects of class Module that hold method definitions. When you define a method with self. inside a module, Ruby creates a singleton method on the module object itself. Including a module copies its instance methods into the target class's method lookup chain. Using extend adds the module's instance methods as singleton methods on the target object or class. module_function duplicates instance methods as module methods and makes the originals private to control visibility.
Why designed this way?
Ruby's module system was designed to provide flexible code reuse without the complexity of multiple inheritance. The separation between instance methods and module methods allows clear control over how methods are shared. module_function was introduced to support both direct module calls and mixin usage with encapsulation. This design balances simplicity, power, and clarity.
┌───────────────┐
│   Module      │
│ ┌───────────┐ │
│ │ instance  │ │
│ │ methods   │ │
│ └───────────┘ │
│ ┌───────────┐ │
│ │ singleton │ │
│ │ methods   │ │
│ └───────────┘ │
└─────┬───┬─────┘
      │   │
 include│   │extend
      ▼   ▼
┌───────────────┐
│    Class      │
│ instance meth │
│ singleton meth│
└───────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does defining a method with self. inside a module make it available as an instance method when included? Commit to yes or no.
Common Belief:Defining a method with self. inside a module makes it available as an instance method when included.
Tap to reveal reality
Reality:Methods defined with self. are module singleton methods and are NOT included as instance methods.
Why it matters:Assuming self. methods become instance methods leads to errors when calling those methods on instances.
Quick: Does module_function make a method public or private when included? Commit to your answer.
Common Belief:module_function makes the method public when included in a class.
Tap to reveal reality
Reality:module_function makes the method private when included, but also creates a public module method.
Why it matters:Misunderstanding this causes confusion about method visibility and unexpected NoMethodError exceptions.
Quick: Does extend add instance methods as instance methods or class methods? Commit to your answer.
Common Belief:extend adds module methods as instance methods to the class.
Tap to reveal reality
Reality:extend adds the module's instance methods as singleton methods (class methods) to the class or object.
Why it matters:Confusing extend with include leads to methods not being found where expected.
Quick: Can modules be instantiated like classes? Commit to yes or no.
Common Belief:Modules can be instantiated to create objects like classes.
Tap to reveal reality
Reality:Modules cannot be instantiated; they are only containers for methods and constants.
Why it matters:Trying to instantiate modules causes runtime errors and misunderstanding of Ruby's object model.
Expert Zone
1
module_function creates a copy of the method as a module method and makes the original instance method private, which can affect method lookup and visibility in subtle ways.
2
Using extend on an object adds methods only to that single object, enabling per-object behavior changes without affecting other instances.
3
Modules can be used as namespaces to avoid name clashes, which is a common pattern in large Ruby applications.
When NOT to use
Avoid using module methods when you need stateful behavior tied to individual objects; in such cases, use classes with instance variables. Also, do not use module_function if you want the included methods to remain public instance methods. For complex inheritance hierarchies, prefer classes or mixins carefully to avoid method conflicts.
Production Patterns
In production Ruby code, modules are widely used as mixins to share behavior across unrelated classes. Module methods often serve as utility functions or namespaces. The module_function pattern is common in libraries to provide both direct module calls and mixin capabilities. Extend is used to add class-level behavior dynamically, such as adding scopes in ActiveRecord models.
Connections
Static methods in other languages
Module methods with self. behave like static methods in languages like Java or C#.
Understanding module methods helps grasp how Ruby handles functions that belong to a container rather than instances, similar to static methods elsewhere.
Namespaces in software design
Modules act as namespaces to group related code and avoid name collisions.
Recognizing modules as namespaces clarifies their role beyond just method sharing, improving code organization.
Mathematical sets
Modules group methods like sets group elements, allowing shared membership without duplication.
Seeing modules as sets helps understand how methods can be shared or combined without inheritance, similar to set unions.
Common Pitfalls
#1Trying to call a module method defined without self. directly on the module.
Wrong approach:module Greetings def hello "Hi" end end Greetings.hello # error: undefined method
Correct approach:module Greetings def self.hello "Hi" end end Greetings.hello # works
Root cause:Not understanding that methods without self. are instance methods, not module methods.
#2Expecting module methods defined with self. to be available as instance methods when included.
Wrong approach:module Greetings def self.hello "Hi" end end class Person include Greetings end Person.new.hello # error
Correct approach:module Greetings def hello "Hi" end end class Person include Greetings end Person.new.hello # works
Root cause:Confusing module singleton methods with instance methods.
#3Using module_function but expecting included methods to be public.
Wrong approach:module Greetings def hello "Hi" end module_function :hello end class Person include Greetings end Person.new.hello # error: private method
Correct approach:module Greetings def hello "Hi" end end class Person include Greetings end Person.new.hello # works
Root cause:Not knowing module_function makes instance methods private when included.
Key Takeaways
Modules in Ruby group methods and constants but cannot be instantiated like classes.
Module methods defined with self. are callable directly on the module, acting like static methods.
Including a module adds its instance methods to a class, but not its module methods.
Using extend adds module instance methods as class methods to the target object or class.
module_function creates both a module method and a private instance method, enabling flexible sharing.