I just finished The Rails View and the best chapter for me was about presenters. I've been working with this for a while and I have to admit I love the approach presented on the view.

All the presenters I've done were instantiated in the controller. In the book they suggest that if the presenter doesn't depend on params or session variables it's the view responsibility to create it. This is extremely flexible specially when we're presenting various objects on the same view. Here's an example to present users in our application, let's use the same presenter for the index and show actions, but let's make it in a really simple way!

The Helper & View

Let's create the helper method first. It's really simple and will take a block that we can use to build a custom markup "on the fly".

# https://gist.github.com/nhocki/2640442

# app/helpers/user_helpers.rb
def basic_information_for(user = @user, options = {})
  presenter = UserBasicPresenter.new(user, self, options)
  if block_given?
    yield(presenter)
  else
    presenter
  end
end

Now, let's take a look at the views. In the show action, we're going to present only one user, and we can easily build the custom view for this. In the index action, we'll present all a "basic info" for the each user. We have that in a partial because this is used for all the collections of users in our application. Here's the view code:

# app/views/show.html.erb
<% basic_information_for do |user|  %>
  <p><%= user.name %></p>
  <p><%= user.status %></p>
  ...
<% end %>

# app/views/index.html
<% @users.each do |user| %>
  <%= basic_information_for(user) %>
<% end %>

The Presenter, A.K.A What's happening here?

What makes this really clean is that we can actually use <%= %> directly on our helper method. This works because we'll define the to_s method in our presenter! In this method we render our partial in the context of the helper, which is amazing. Here's the code for that:

# app/presenters/user_basic_presenter.rb
class UserBasicPresenter
  def initialize(user, template, options = {})
    @user     = user
    @options  = options
    @template = template
  end

  # more methods ...

  def to_s
    @template.render partial: 'user/basic', object: self
  end
end

Is that simple! We have a unique interface (the helper) that will work great in both places! We could obviously make the presenter more complex, otherwise, why use it?

Even though I haven't used this approach a lot, I'm really happy with it. I felt the difference instantly and it made a lot of sense to me. Being able to mix this with a flexible layout is really powerful!

Feedback

I'm also really interested in how people are using presenters. I'd love to gain more feedbacks and points of view about this. Feel free to post a comment (here on in the gist) or ping me on Twitter, @nhocki.