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!