Introduction
In Rails, helpers, presenters, and decorators are design patterns for organizing view logic, making views cleaner and more maintainable. All three extend the functionality of models and controllers, but they are slightly different in their way.
Let’s walk through examples of using a helper, presenter, and decorator to handle the same task: displaying a user’s full name and their formatted signup date.
Scenario:
The User model has first_name, last_name, and created_at attributes. We want to display the full name and formatted signup date in a view.
Using Helper
1. Model
class User < ApplicationRecord
# attributes: first_name, last_name, created_at
end
2. Helper
module UserHelper
def full_name(user)
"#{user.first_name} #{user.last_name}"
end
def date_format(user)
user.created_at.strftime("%Y-%m-%d")
end
end
3. Controller
def show
@user = User.find(params[:id])
end
4. View
<%= date_format(@user) %>
<%= full_name(@user) %>
Using Presenter
app/presenters/users_presenter.rb
1. Presenter
class UsersPresenter
def initialize(user)
@user = user
end
def full_name
"#{@user.first_name} #{@user.last_name}"
end
def sign_up_date
@user.created_at.strftime("%Y-%m-%d")
end
end
2. Controller
def show
@user = User.find(params[:id])
@user_presenter = UsersPresenter.new(@user)
end
3. View
<%= @user_presenter.full_name %>
<%= @user_presenter.sign_up_date %>
Using a Decorator (with Draper Gem)
app/decorators/user_decorator.rb
1. Decorator
class UserDecorator < Draper::Decorator
delegate_all
def full_name
"#{object.first_name} #{object.last_name}"
end
def sign_up_date
object.created_at.strftime("%Y-%m-%d")
end
end
2. Controller
def show
@user = User.find(params[:id]).decorate
end
3. View
<%= @user.full_name %>
<%= @user.sign_up_date %>
Comparison of Use Cases
Helper
- Best for simple, reusable logic that doesn’t need to maintain state.
- Can become cluttered if used for too much or complex logic.
- Example: Simple formatting methods.
Presenter
- Handles more complex view logic, often combining data from multiple models.
- Keeps views and controllers clean by encapsulating logic.
- Example: Displaying a profile with data from related models.
Decorator
- Best for extending model functionality in a modular and reusable way.
- Example: Adding view-specific methods while keeping model logic focused on business rules.
When to Use Which
Use Helper when:
1. Simple, Reusable Logic
- For repetitive tasks across multiple views.
- Example: Formatting a date, generating reusable HTML.
2. No Need for State
- When logic doesn’t need instance variables or state.
- Example: Displaying a user’s role.
Use Presenter when:
1. Complex View Logic
- Encapsulating complex view logic involving multiple models.
- Example: User profile combining related data.
2. Clean Views
- Keeps views tidy by moving logic into a dedicated object.
Use Decorator when:
1. Dynamic Behavior
- When you want to dynamically extend model instances.
- Example: Applying decorators conditionally by context.
2. View-Specific Enhancements
- Offloads view-specific methods without polluting the model.
Conclusion
Each approach has strengths. Helpers are great for simple, reusable logic, Presenters encapsulate complex view logic and multiple models, and Decorators extend model instances with view-specific methods. Choose the pattern that matches the complexity and structure of your application’s view logic.