Decorators
Using Draper
Jason Charnes
@jmcharnes
The Project
ConnectHope Hub
A way to connect people in need with places that can help them.
Let's start with a problem.
= link_to church_path(c) do
.col-sm-4
.well.church-box.text-center
%h5= c.name.split(" ").reject{ |e| e == "Church" }.join(" ")
%p
= c.address_1
%br
= "#{c.city}, #{c.state} #{c.zip}"
%span
Date Joined:
%strong
= c.created_at.strftime("%m/%d/%y")
/churches
index.html.haml
Thought: How can I clean this up?
Procedural Helpers
= link_to church_path(c) do
.col-sm-4
.well.church-box.text-center
%h5= remove_church_from_name(c.name)
%p
= c.address_1
%br
= "#{c.city}, #{c.state} #{c.zip}"
%span
Date Joined:
%strong
= c.created_at.strftime("%m/%d/%y")
module ChurchesHelper
def remove_church_from_name(name)
name.split(" ").reject{ |e| e == "Church" }.join(" ")
end
end
Gross: Where did the OOP go?
Class Methods
= link_to church_path(c) do
.col-sm-4
.well.church-box.text-center
%h5= c.name
%p
= c.address_1
%br
= "#{c.city}, #{c.state} #{c.zip}"
%span
Date Joined:
%strong
= c.created_at.strftime("%m/%d/%y")
class Church < ActiveRecord::Base
def name
self.name.split(" ").reject{ |e| e == "Church" }.join(" ")
end
end
Better... but still feels weird.
The Solution
Decorators
https://github.com/drapergem/draper
Draper
"Draper adds an object-oriented layer of presentation logic to your Rails application."
Install Draper
gem 'draper', '~> 1.3'
bundle install
rails generate resource Church
rails generate controller churches_controller
rails generate decorator Church
or in my case, with an existing controller:
Use Draper
ChurchesController
def index
@churches = Church.approved
end
def index
@churches = Church.approved.decorate
end
= link_to church_path(c) do
.col-sm-4
.well.church-box.text-center
%h5= c.name
%p
= c.address_1
%br
= "#{c.city}, #{c.state} #{c.zip}"
%span
Date Joined:
%strong
= c.created_at.strftime("%m/%d/%y")
app/views/churches/index.html.haml
class ChurchDecorator < Draper::Decorator
def name
model.name.split(" ").reject{ |e| e == "Church" }.join(" ")
end
end
app/decorators/church_decorator.rb
class ChurchDecorator < Draper::Decorator
def name
model.name.split(" ").reject{ |e| e == "Church" }.join(" ")
end
def location
"#{model.city}, #{model.state} #{model.zip}"
end
end
= link_to church_path(c) do
.col-sm-4
.well.church-box.text-center
%h5= c.name
%p
= c.address_1
%br
= c.location
%span
Date Joined:
%strong
= c.created_at.strftime("%m/%d/%y")
class ChurchDecorator < Draper::Decorator
delegate_all
def name
model.name.split(" ").reject{ |e| e == "Church" }.join(" ")
end
def location
"#{model.city}, #{model.state} #{model.zip}"
end
def joined
model.created_at.strftime("%m/%d/%y")
end
end
= link_to church_path(c) do
.col-sm-4
.well.church-box.text-center
%h5= c.name
%p
= c.address_1
%br
= c.location
%span
Date Joined:
%strong
= c.joined
Finishing Draper
-
Decorators can be tested
- RSpec
- MiniTest::Rails
- TestUnit::Rails
-
Decorators can be shared
- ApplicationDecorator
- Access to Rails helpers
- Specific/All methods can be delegated
Decorators
Using Draper
Jason Charnes
@jmcharnes
Decorators in Rails, Using Draper
By Jason Charnes
Decorators in Rails, Using Draper
- 3,447