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
?
- Reduces boilerplate code.
- Keeps your classes clean by offloading certain method calls to other objects.
- Improves code readability by making clear what methods are being delegated.
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
?
- It makes organizing and modularizing code easier and cleaner.
- Simplifies working with
included
blocks and dependencies within modules. - Allows you to share behavior in a more structured and reliable way, especially for complex mixins.
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?
alias_method_chain
has been deprecated becauseprepend
is more flexible and aligns better with Ruby’s object model.prepend
provides a cleaner, more idiomatic way to modify method behavior.
Conclusion
Rails’ ActiveSupport
core extensions to Module
provide developers with powerful tools to streamline and improve their code.
delegate
helps simplify delegation and reduces boilerplate, making code more maintainable.concern
provides a structured way to create reusable, modular code, improving organization and reducing duplication.alias_method_chain
, while deprecated, introduced important concepts around method chaining, now replaced withprepend
for a more modern approach.