DisplayCase Gem Now Available

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:

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#entries association 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_number method to include dashes and have all but the last four digits obscured: ***-**-5678.
  • 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!

5 comments

  1. Is it a true Decorator?  My understanding is that a Decorator augments behavior but preserves the interface.  The objects which interact with a Decorator have no knowledge of the Decorator, and therefore can’t depend on any extensions to the interface.  That is, scoping #entries or formatting #social_security_number would be Decorator-y, but adding new methods would not.

    The original purpose of the Decorator pattern, if I understand it correctly, was to modify the behavior of existing objects at runtime, even in a static language.

    1. In the GoF’s Decorator examples, they describe a TextView class in a GUI framework with decorator subclasses like ScrollDecorator and BorderDecorator.

      “Decorator subclasses are free to add operations for specific functionality. For example, ScrollDecorator’s ScrollTo operation lets other objects scroll the interface if they know there happens to be a ScrollDecorator object in the interface.”

      Most clients of the exhibit—link_to, url_for, etc.—have no knowledge of the decoration, but our view code does, and is free to call methods not in the original interface, like render_yourself.

      Exhibits make it easy to refactor, usually undocumented and untested, procedural Rails helper methods into proper classes. Thanks, Avdi!

Comments are closed.