Presenters were a hot topic in the rails community last year. A lot of prominent bloggers wrote about using them, and the implementations they had come up with. Oddly, though, when I needed one a couple of weeks ago, I was unable to find a suitable implementation. Lots of articles — no code.
Let's answer the question on everybody's mind before we move on. Feel free to skip ahead if you already know the answer.
WTF is a presenter?!
In its simplest form, a presenter is an object that wraps up several other objects to display, and manipulate them on the front end. For example, if you have a form that needs to manipulate several models, you'd probably want to wrap them in a presenter.
Indeed, attribute_fu solves this problem for some cases. However, when you're dealing with unrelated models, or, really, any situation other than a parent saving its children, you're probably better off using a presenter.
Presenters take the multi model saving code out of your controller, and put it in to a nice object. Because presenter logic is encapsulated, it's reusable, and easy to test.
Want one?
ActivePresenter
Daniel and I wrote most of this on the train ride over to RubyFringe. It is an ultra-simple presenter base class that is designed to wrap ActiveRecord models (and, potentially, others that act like them).
ActivePresenter works just like an ActiveRecord model, except that it works with multiple models at the same time. Let me show you.
Imagine we've got a signup form that needs to create a new User, and a new Account. We'd create a presenter that looks like this.
class SignupPresenter < ActivePresenter::Base
presents :user, :account
end
Then, we'd write a new action like this one:
def new
@signup_presenter = SignupPresenter.new
end
And a form:
<%= error_messages_for :signup_presenter %>
<%- form_for @signup_presenter, :url => signup_url do |f| -%>
<%= f.label :account_subdomain, "Subdomain" %>
<%= f.text_field :account_subdomain %>
<%= f.label :user_login, "Login" %>
<%= f.text_field :user_login %>
<%- end -%>
A create action:
def create
@signup_presenter = SignupPresenter.new(params[:signup_presenter])
if @signup_presenter.save
redirect_to dashboard_url
else
render :action => "new"
end
end
Lastly, an update action:
def update
@signup_presenter = SignupPresenter.new(:user => current_user, :account => current_account)
if @signup_presenter.update_attributes(params[:signup_presenter])
redirect_to dashboard_url
else
render :action => "edit"
end
end
Seem familiar?
If you're using r_c, most of this comes for free with:
class SignupsController < ResourceController::Base
model_name :signup_presenter
end
For more on complex forms in rails, and the presenter pattern, see my upcoming PeepCode screencast!
Organization
I have been sticking my presenters in app/presenters. If you want to do the same, you'll need to add a line like this to your environment.rb:
config.load_paths += %W( #{RAILS_ROOT}/app/presenters )
Get It!
As a gem:
$ sudo gem install active_presenter
As a rails gem dependency:
config.gem 'active_presenter'Or get the source from github:
$ git clone git://github.com/giraffesoft/active_presenter.git
(or fork it at http://github.com/giraffesoft/active_presenter)
Also, check out the RDoc.



Wow! Very nice. Congratulations once more!
This is simply brilliant!
The API looks good and I am sure the implementation is nice but I'm not sure I sold on the concept of a presenter. Seems like you are for the most part the developer is just implementing their controller in another object and then including a reference to the object in the controller. Almost like a mixin for controllers only.
There might be a few cases where you would need the same forms in multiple controllers (i.e. the abstraction and reuse you provide with a presenter) but it seems that that would be a rare case. Is it worth the mental overhead of having this "presenter" concept for those few rare cases? My preference would be to just reuse the mixin concept people are already familiar with (i.e. implement the various REST actions on a module then mixin to multiple controllers). This would seem to give you the same reuse the presenter provides without the additional mental overhead of an entirely new concept.
Just my two cents
awesome work James & Daniel!
@Eric, this is an implementation of the Presenter design pattern: http://blog.jayfields.com/2007/03/rails-presenter-pattern.html
hey James, great work!
I led a BOF session at Railsconf 2008 on this topic, and there's definitely a big interest and need for this gem. In fact I registered "active_presenter" on RubyForge, but never got around to doing anything with it, so if you want to publish this gem there, I'd be glad to transfer the project to you. Just hit me up with an email at mike /-at-/ subelsky.com.
-Mike
@Eric Anderson: If you can avoid multi-object creation, then more power to you. This is indeed only for rare cases - although I think you confuse things by calling it a mixin. Check out the link macournoyer to get a better sense of what this encapsulates.
Will this gem also handle cases where I want to create/edit a single model with some 'child' models?
So one project with (to leave javascript out of the equation) 10 tasks in a single form for creating and updating the tasks? What about deleting them?
@Mathijs: It doesn't yet, but we're hoping to have that functionality going soon.
Hi James,
Nice article.
We met in Berlin last year. I need to send you an email. Can you email me to the address included in this form?
Thanks.
Hiya, I can't seem to grab this gem. I'm getting not found errors when I run the gem install command. Thoughts?
@John - No idea. I can run it ok. You're trying to download it from rubyforge?
This looks much nicer than the presenter plugin I slapped together, thanks.
Thanks! It looks good. But what if there are equal attribute names? Like User.name and Account.name. What form will be in this case?
This looks great for multiple unrelated models or two models with a belongsto relationship, but doesn't handle hasmany scenarios, correct?
<rant> Why are multi-model forms so fraking hard (no standard solution, gotta write extra code, little documentation on the solutions that exists) in Rails when WebObjects was doing this 10 years ago with keypaths? </rant>
Awesome stuff. I do have a question though. After installing the plugin and then trying to run rake routes I get an error: uninitialized constant ActivePresenter.
I installed from Github as a plugin. Also, when using the presenter to create a user and an account I'm getting some weird posting issues.
so my AccountSignupPresenter presents :account, :user
then on my form I have this: formfor @accountsignuppresenter, :url => accountspath
for some reason everything looks great and works, but the form is posting to the accounts index action. It obviously should post to the accounts create action.
Any help would be appreciated. Thanks again for the great work!
@Nate, have you tried something like this:
:url => { :controller => 'accounts', :action => :create }
I haven't tried active_presenter yet, but it does seem intriguing.
Hi, I've been using it and works really nice. Any plans to include a before_validation callback?
@Max - Sure. If there's a need for one, I can definitely add it. Could you not put that validation in one of the models, though?
ActivePresenter seems to be doing two things: handling presentation logic for one or more models, and also handling save/update logic for more than one model. It's meddling in two distinct and completely separate responsibilities. This seems to encourages bad practice when it comes to dealing with either presentation logic and/or multiple model forms. Presenters should only be handling presentation logic. The save/update logic should be done in the model, or if it can't be done there in a domain Service/Manager object.
CachingPresenter is a strict presentation-logic presenter. It does cool stuff with caching/memoization. Should it provide useful to James or anyone else seeing this post please check it out:
Github - http://github.com/zdennis/caching_presenter/
Docs - http://github.com/zdennis/caching_presenter/wikis/home