When I set out to write Objects on Rails, I knew I wanted to cover the Presenter pattern. Or at least, what I thought of as the Presenter pattern. So I set out to read up on the history of Presenters in the context of Ruby on Rails applications.
The more I read, the more I realized that what I and possibly others had been calling “Presenter” was really something a bit different from the idea that Jay Fields first introduced under that name in 2006, and subsequently expanded on. Originally, Presenter was fundamentally an aggregation pattern. The canonical example is a report: you have a view in which data from numerous models is brought together into a single summary view. Rather than have a controller instantiate and/or query numerous models, you group them all into a Presenter object which represents that logical “screen” as a single aggregate object.
I won't bore you with the details of my research. If you're curious, here's my Presenter reading list from OoR:
- Model View Controller + Presenter? – the post that first introduced the Presenter concept.
- Another Presenter Example
- Presenters – An Additional layer example.
- Presenter Pattern – a formalization of the pattern.
- Rise, Fall, and Potential Rebirth of the Presenter Pattern. A retrospective look at the experiences Jay and others had applying Presenters to various projects.
- Courtenay Gasking: Simple Presenters.
- Zach Dennis: The Exceptional Presenter.
- Dmytro Shteflyuk: Simplifying your Ruby on Rails code: Presenter pattern, cells plugin.
- Steve Klabnick: Better Ruby Presenters. A follow-up to The Secret to Rails OO Design, referenced earlier.
- Jeff Casimir: Blow Up Your Views. Jeff encoded the concepts introduced in this presentation in his Draper gem.
- Martin Fowler summarizes GUI patterns. Note: this article is more concerned with rich client-side GUI patterns than web GUIs.
By contrast, what I had been using on several projects, and was eager to show people in the book, was more of a presentational decorator. Now I had a quandary: I had already drafted a whole section on them, but now I wasn't sure what to call them. “Decorator” was too generic for the very specific kind of decorator I was describing. “Presentational decorator” didn't exactly roll off the tongue.
The presentational pattern I came to describe as an “exhibit” in OoR has the following trademarks:
- It wraps a single model instance. Not an assortment of objects.
- It is a true Decorator. All unrecognized messages are passed through to the underlying object. This facilitates a gradual migration to the use of Exhibits to encapsulate presentation knowledge, since they can be layered onto models without any change to the existing views. It also enables multiple Exhibits to be layered onto an object, each handling different aspects of presentation.
- It brings together a model and a context. Exhibits need a reference to a “context” object—either a controller or a view context—in order to be able to render templates as well as construct URLs for the object or related resources.
- It encapsulates decisions about how to render an object. The tell-tale of an Exhibit is telling an object “render yourself”, rather than explicitly rendering a template and passing the object in as an argument.
- It may modify the behavior of an object. For instance, an Exhibit might impose a scope on a
Blog#entriesassociation which only returns entries that are visible to the current user (as determined from the Exhibit's controller context). Or it might reformat the return value of a
#social_security_numbermethod to include dashes and have all but the last four digits obscured:
- There is a many-to-many relationship between model classes and exhibit classes. One generic exhibit class may apply to several different types of model. Other exhibits may be specific, not just to a model, but to a model in a particular state, or within a particular viewing context.
The more I thought about it, the clearer it seemed that while this idea wasn't new–a number of people were already using similar constructs–it had sufficient unique traits to perhaps warrant a name of its own. And I was convinced that continuing to call it a “presenter” would just make things needlessly confusing. Hence, the term “exhibit” was born.
Since I released the book, the Exhibit idea seems to have struck a chord. I get a lot of feedback from people who say they are happily using it in their own projects. In fact, I get more positive feedback about Exhibits than about anything else in the book.
While anyone can roll their own Exhibits–that's the point of a pattern, after all–I fully intended to release the basic Exhibit framework demonstrated in the OoR source code as open-source code. Today, thanks once again to the diligent curation of Sammy Larbi, I'm happy to announce that this code is available as the display_case gem. Of course, it's also available on GitHub as well.
Why call it “display_case” instead of “exhibit”? Simply because it's a pet peeve of mine to name libraries after patterns. It makes discussing them confusing–are we talking about the general pattern, or a specific library?
This post has been long enough, so I won't go into usage here. You can read all about how to use the gem on the homepage. And if you have any questions or suggestions, please do join the Objects on Rails public discussion list!