Decorators
They wrap an object and extend its functionality without modifying the object itself.
The problem
Say you have the following view.
<p>Name: <%= @company.name.titleize %></p>
<p>Email: <%= @company.email_private? 'Private' : @company.email %></p>
<p>Sign Up At: <%= @company.sign_up_at.strftime('%d. %m. %Y.') %></p>
It's bad because the view should not care about how to display the data, it should just display it.
The Decorator object
class CompanyDecorator < SimpleDelegator
def display_name
name.titleize
end
def protected_email
return "Private" if email_private?
email
end
def formatted_sign_up_at
sign_up_at.strftime("%d %b %Y")
end
end
The implementation
Nice, let's see how the controller looks now.
class CompanyController < ApplicationController
def show
company = Company.find(params[:id])
@decorated_company = CompanyDecorator.new(company)
end
end
Now, the view
<p>Name: <%= @decorated_company.display_name %></p>
<p>Email: <%= @decorated_company.protected_email %></p>
<p>Birthday: <%= @decorated_company.formatted_sign_up_at %></p>
Final thoughts
Not only looks better, testing this approach is much simpler.
This does not only applies for Rails apps, this pattern could be used anywhere in Ruby.
Top comments (1)
Nice and clean solution. Awesome!