3 Must-Know Module Extensions in ActiveSupport

In this post, we’ll explore some of the most useful core extensions in Rails that enhance how developers work with modules: delegate, concern, and the deprecated but still important alias_method_chain. These tools simplify method delegation, modularize code, and modify method behavior. While alias_method_chain is no longer in use, understanding its history is helpful for maintaining legacy code. We’ll break down how each of these methods works and why they’re valuable, especially when writing cleaner, more efficient Rails applications.

1. Module#delegate

One of the most widely used extensions in Rails is Module#delegate. This method allows you to delegate method calls from one object to another, which is useful when you’re designing classes that need to delegate certain responsibilities to their internal objects.

The delegate method simplifies the delegation process, which otherwise would require manually defining methods that call another object’s methods.

Here’s how delegate works:

Without delegate:

1
2
3
4
5
6
7
8
9
10
11
12
13
class Invoice
  def initialize(customer)
    @customer = customer
  end

  def customer_name
    @customer.name
  end

  def customer_address
    @customer.address
  end
end

With delegate:

1
2
3
4
5
6
7
8
9
class Invoice
  attr_reader :customer

  delegate :name, :address, to: :customer

  def initialize(customer)
    @customer = customer
  end
end

In the second example, instead of manually writing methods to delegate name and address to the customer object, the delegate method does it for you. This keeps your code DRY (Don’t Repeat Yourself) and more readable.

Why use delegate?

2. Module#concern

Another powerful extension provided by ActiveSupport is Module#concern. This helps when organizing and modularizing code through mixins. While Ruby modules can be used to share behavior across classes, concern provides a better structure and solves common issues related to dependencies or initialization sequences in modules.

With concern, you can easily split related methods, validations, or callbacks into separate, reusable modules that can be included in multiple classes.

Example without concern:

1
2
3
4
5
6
7
8
9
10
11
12
13
module Trackable
  def track_changes
    puts "Tracking changes..."
  end

  included do
    after_save :track_changes
  end
end

class Order < ApplicationRecord
  include Trackable
end

This works, but it can become messy when you need to manage more callbacks, validations, or dependency methods. You may run into issues with load order or dependencies.

With concern:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module Trackable
  extend ActiveSupport::Concern

  included do
    after_save :track_changes
  end

  def track_changes
    puts "Tracking changes..."
  end
end

class Order < ApplicationRecord
  include Trackable
end

The ActiveSupport::Concern module ensures that your included block is executed at the correct time, preventing problems with module inclusion order. It also helps by offering a consistent structure for defining reusable logic that involves both instance methods and class-level logic.

Why use concern?

3. Module#alias_method_chain (Deprecated, but Important to Know)

Module#alias_method_chain was a widely used method in previous versions of Rails to extend or enhance the behavior of existing methods. Although it has been deprecated in favor of using Module#prepend and super, understanding this method is still useful when maintaining legacy codebases or learning about Rails’ history.

alias_method_chain allowed developers to wrap additional behavior around a method, effectively creating a “before” or “after” chain.

Example of alias_method_chain:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class User
  def name
    "John Doe"
  end

  def name_with_prefix
    "Mr. " + name_without_prefix
  end

  alias_method_chain :name, :prefix
end

user = User.new
puts user.name  # Output: "Mr. John Doe"

Here, alias_method_chain wraps the name method with extra logic (a prefix). The original method name is aliased to name_without_prefix, and the enhanced version name_with_prefix is added in its place.

Post-Rails 5 Alternative: Since alias_method_chain has been deprecated, Rails now encourages using Module#prepend and super to achieve similar behavior.

Using prepend:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class User
  def name
    "John Doe"
  end
end

module NamePrefixer
  def name
    "Mr. " + super
  end
end

User.prepend NamePrefixer

user = User.new
puts user.name  # Output: "Mr. John Doe"

By using prepend, the NamePrefixer module is added to the inheritance chain before the original User class, allowing us to call super to invoke the original name method.

Why avoid alias_method_chain today?

Conclusion

Rails’ ActiveSupport core extensions to Module provide developers with powerful tools to streamline and improve their code.