DEV Community

Germán Alberto Gimenez Silva
Germán Alberto Gimenez Silva

Posted on • Originally published at rubystacknews.com on

Enhancing Ruby Applications with Module#included

December 31, 2024

Ruby’s flexibility and metaprogramming capabilities allow developers to write clean, reusable, and dynamic code. One often overlooked feature is the Module#included callback. Understanding and leveraging this can add a new dimension to your Ruby applications.


Do you need more hands for your Ruby on Rails project?

Fill out our form! >>


What is Module#included?

Module#included is a callback that Ruby invokes when a module is included in another class or module. By overriding this method, you can perform custom operations whenever your module is included.

This feature provides an opportunity to dynamically modify the including class, add functionality, or enforce constraints. Think of it as a hook that fires every time the module is mixed in.


Syntax and Basic Usage

Here’s the simplest form of overriding Module#included:

module ExampleModule
  def self.included(base)
    puts "#{self} has been included in #{base}"
  end
end

class MyClass
  include ExampleModule
end
Enter fullscreen mode Exit fullscreen mode

Output:

ExampleModule has been included in MyClass
Enter fullscreen mode Exit fullscreen mode

When MyClass includes ExampleModule, the included method is triggered, printing a message to the console.


Adding Dynamic Behavior

One powerful application of Module#included is to dynamically extend the including class with additional methods or functionality. Let’s explore this:

module Trappable
  def self.included(base)
    puts "#{self} was included in #{base}"
    base.extend(ClassMethods)
  end

  module ClassMethods
    def greet
      puts "Hello from #{self}!"
    end
  end
end

class MyClass
  include Trappable
end

MyClass.greet
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • When Trappable is included, the included method extends the MyClass with a module ClassMethods, adding the greet class method.
  • MyClass.greet prints a message, showcasing how ClassMethods became part of MyClass dynamically.

Best Practices and Considerations

  1. Avoid Overuse : Use Module#included sparingly to keep your code simple and maintainable. Overriding callbacks excessively can lead to unexpected behavior.
  2. Call super if Needed : If your module’s parent class also implements included, ensure you call super to retain its behavior.
  3. Encapsulate Logic : Use helper modules or methods to keep the included method clean and readable.
  4. Document Side Effects : Clearly document any changes the module makes to the including class, especially if it dynamically adds methods or modifies behavior.

Real-World Applications

  • Dynamic Mixins : Add specific functionality to classes at runtime based on business logic.
  • Namespace Injection : Automatically include or extend related modules in the including class.
  • Constraint Enforcement : Ensure the including class satisfies certain conditions (e.g., implementing specific methods).

Example:

module Validator
  def self.included(base)
    unless base.respond_to?(:validate)
      raise "#{base} must implement a `validate` method"
    end
  end
end

class Validatable
  include Validator

  def self.validate
    puts "Validation logic here."
  end
end
Enter fullscreen mode Exit fullscreen mode

Conclusion

The Module#included callback is a powerful tool in the Ruby metaprogramming toolkit. It allows developers to go beyond traditional module inclusion, enabling dynamic and context-aware behavior. When used judiciously, it can lead to more flexible and expressive code.

By understanding how and when to use Module#included, you can enhance your Ruby applications and make your modules smarter and more adaptable.


What are your thoughts on using Module#included_? Have you encountered any interesting use cases? Let’s discuss!_

Image of Quadratic

AI, code, and data connections in a familiar spreadsheet UI

Simplify data analysis by connecting directly to your database or API, writing code, and using the latest LLMs.

Try Quadratic free

Top comments (0)

AWS Q Developer image

Your AI Code Assistant

Automate your code reviews. Catch bugs before your coworkers. Fix security issues in your code. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE