Rails Presenters

Rails presenters provide a way to separate presentation logic from the core domain model, without polluting your view templates. Let’s talk about the benefits..

Why not in the view template?

Putting logic in view templates is a bad idea because it is difficult to maintain and hard to test.

View templates with embedded business logic are hard to maintain because they are jumbled in with HTML code. They are typically not DRY and logic is not structured in an organised way.

Typically you can only test views templates using some form of integration testing. You can’t test any one part of the template in isolation. You have to simulate a user and start clicking around.

How about moving logic to the controller and model?

Pulling logic out of the view and into the controller is rarely a good idea. However, some pieces of logic can deservedly go in the model. For example, any logic that is not concerned with presentation and belongs in the entity itself.

Otherwise, polluting the model and/or controller is not a good solution. This is really just moving the junk pile from one place to another.

How about view helpers?

This is not a bad solution and some bits of logic should live in view helpers.

View helpers are methods that are included in all view templates. You can split view helpers into separate files but they are all shared globally between all of your view templates.This makes helpers good for utility type methods that are useful across the application (eg: current_user).

The drawback is that the global namespace can quickly become overpopulated. It can also be difficult to know where helper methods are defined.

The solution? Presenters.

Presenters are Ruby classes that are instantiated and used with the view. Presenters are a place to put all of your presentation logic. Here is an example of a simple presenter:

class PrescriptionsPresenter
  attr_accessor :prescription

  def initialize(prescription)
    @prescription = prescription
  end

  def patient(prescription)
    prescription.patient.name
  end
end

To use the presenter, simply initialize it in your controller and make it available to the view template with an instance variable. This allows you to call method on the instance variable, inside your view template.

class PrescriptionsController < ApplicationController
  def index
    @presenter = PrescriptionsPresenter.new(params[:prescription])
  end
end

The advantage of presenters is that they are easy/fast to test and are easier to maintain. They are simple Ruby classes and adhere to the single responsibility rule.

Summing it up

Keep you views simple. Don’t put presentation logic into controllers or models (unless┬áthe logic really should go in the model). Use view helpers sparingly (for global utility methods). Use presenters for everything else.