Managing Complexity with Presenters

Wojciech Wnętrzak edited this page Oct 24, 2013 · 4 revisions

When creating APIs, you should strive to manage complexity by using plain old ruby objects and presenters. RABL is a view and like all views, one of the first principles of web development is to keep complex logic out of views. Keep complex logic in a well-organized object that is well-testable.

Quick Start

From David's excellent post on presenters, we can see how to simplify complex RABL templates. Take this view as an example:

# post_controller.rb
def show
  @post = Post.find(params[:id])
end

# show.rabl
object @post

attributes :title, :body

child :author do |post|
  attribute :name => :author_name unless post.author == current_user
end

node :publication_date do |post|
  if post.status == 'published'
    post.published_date
  end
end

Simply organize the logic needed in the view within a presenter using Draper and/or plain ruby objects:

# post_presenter.rb
class PostPresenter < Draper::Base
  decorates :post
  attr_reader :current_user

  def initialize(post, current_user)
    super(post)
    @current_user = current_user
  end

  def author_name
    author.name unless author == @current_user
  end

  def publication_date
    publication_date if status == 'published'
  end
end

# post_controller.rb
def show
  @post = PostPresenter.new(Post.find(params[:id]), current_user)
end

# show.rabl
object @post

attributes :title, :body, :author_name, :publication_date

Notice that now the logic and complexity is stored in a presenter object and the RABL template is kept clean of complex logic. Keeping complex logic out of views is an important principle in creating maintainable and well-tested applications.

Resources

Great articles to read:

I cover most of the above with Testing in isolation, example in RABL on my blog. After writing that, I recently read Objects on Rails and found that Avdi Grimm covers much of the same but explains it better in book format.