RailsConf 2012: Presenters and Decorators

Mike Moore /@blowmage 

Rails is a diverse community, there are lots of approaches
There are flaws in this, as in any singular approach
 
Presenters should ease pain
You shouldn’t start with these, but implement them when you feel pain
 
Components (bad smell)
New developer wants to go change the dashboard and this is all he finds:
 
<%= render_component(@component) %>
 
Okay, let’s let’s look for this method. 
This method renders a partial.
 
The partial has:
 
<%= render_component(component) %>
 
It’s actually in component_helper.rb
 
Keep drilling down, find something in a builder in lib/dashboard_component_builder.rb
CallsPostItemComponentBuilder, which inherits form ComponentBuilder
 
There is still no build list (which is what we’ve been looking for)
Maybe it’s in the ComponentBuilder class. 
This lives in app/components/component_builder.rb (why?)
So _this_ builds the list! Yay!
 
post_item_component.rb defines off Partial Component and references another partial of posts/post_item
PartialComponent… do we have a render call? 
 
“This is MetaProgramming, and it’s incredibly difficult to understand”
They dynamically create a new class, etc etc. 
 
[Continues to drill down the insanity]
 
Totally not a productive flow
 
“Wont’ someone please think of the new developers?!”
Not newbies, but people not familiar with the app
There is no excuse for the component example. That’s awful code. 
 
You should only use presenters when the pain that the presenters solve is exponentially more than the pain they create.
You want more benefit than  cost.
 
View is a total bike shed
A bike shed is when you have a lot of people arguing about the cosmetic detail of how something is going on but it doesn’t really matter
 
[Typical presenter example]
Local assigns, lots of conditional content
 
A lot of things get stuffed in the model
Does your domain really need these? 
This is not domain logic. it’s front end presentation logic
The model is not the location for this. 
 
Alternatively, we could create something in /lib
We have something that we can test without confusing the rest of User.rb
Typically, a presenter is something that knows about your models for view logic.
 
Extract those local assigns OUT of your view
 
We have some libraries that do this for us:
Draper
ActiveDecorator github.com/amatsuda/active_decorator
 
Decorators move things into the app/decorators directory
It helps. 
 
Typical Serialization Example
Post controller post#show
JSON delivery with RABL file
 
“I look at this and say ‘how am I going to test this?'”
The only way is an integration test, and it’s a lot of work to set that up
 
ActiveModel::Serializer looks for the rendering of JSON and intercepts it. 
 
This is where most people stop with presenters.
But is that all?  
 
Let’s take a look at some design patterns.
 
Decorator Design Pattern
Attach additional responsibilities to an object dynamiclaly Decorators provide a flexible alternaitve to subclassing for extending functionality. 
 
Mediator design pattern
Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly and letsvyou vary their interaction
Not every presenter is a mediator, and vice versa
 
We have a presenter spectrum between views and models. Presenters go anywhere between. Decorators are more model side of the spectrum
Presenters is more on the view side (at least 5 years ago that’s what it was called)
 
Where did it come from?
http://blog.jayfields/com/2007/03/rails-presenter-pattern.html
 
Calls out Martin Fowler’s work
http://martinfowler.com/eaaDev/PresentationModel.html
Enterprise Application Architecture book
 
Presentation Model
[definition from MF’s site]
 
Presentation is a “representation of the state of the view”
A true presenter is a Presentation Model, or as close as we can get in the Rails community.
 
[A slightly better example]
complex conditionals are dangerous to expose. How do we move them?
How do we get there?
 
[A better example]
How, When, What of the display for categories
Creating different presenters  for public, private, etc
Controller has logic to determine which presenter is used
Makes it testable.
 
WARNING:
Do not start with presenters. 
ONLY use this when you feel pain, e.g. can’t verify flows, etc. 
There is overhead. Should not be the same as components if we do it right.
But there is overhead when dealing with presenters.
JEG, II quote on how bad presenter code can be
 
[Thanks for pimping the book, Mike!]