More on the Presenter Pattern
June 27, 2014
Here I describe a nice adjustment to the Presenter Pattern as I explained it in a recent post. This update makes the views even more readable.
The problem with my previous implementation of the Presenter is that it leads to the view template using two instance variables that are really representing the same thing–
@presenter are both presenting information about a book record from the database. Yes, one is handling more complicated data than the other, but I wouldn’t blame someone for assuming at first glance that the two instance variables
@presenter are representing totally unique objects. It’d be much clearer if there was one object to use throughout the view.
We know we need a BookPresenter class to hide things like formatting logic, so we’ll keep that, but we’ll refer to that object as
@book in the view and not pass the actual book object:
class BookController < ApplicationController
book = Book.find(params[:id])
@book = BookPresenter.new(book)
The question is how to handle any fields that we originally were calling directly on the instance of Book (in other words, methods that don’t need formatting logic, like
page_count). We could define those methods on the BookPresenter and in those method definitions just call the field on the book object we passed in upon initialization:
@book = book
This will give us our desired functionality, but it will clutter up the BookPresenter class with methods that are barely doing anything. Fortunately, Ruby’s “Forwardable” module provides a way to cleanly and concisely effect this behavior.
def_delegators :@book, :title, :page_count
@book = book
@book.publication_date.strftime("%B %d, %Y")
With Forwardable and
def_delegators, we are essentially saying “if
page_count is called on an instance of BookPresenter, call that method on
@book instead of the instance of this class.” Lovely! We can now pass just one variable,
@book, to the show view template. This one object is solely responsible for all the presentational logic regarding the data about that book.