Showcase

A simple (< 100 lines of code) but powerful exhibit/presenter implementation. It's framework agnostic: works with Rails, Padrino or simply Sinatra.
Properties of the Exhibit pattern
Citing Avdi's introductory post:
- 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:***-**-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.
Installation
Add this line to your application's Gemfile:
gem 'showcase'
And then execute:
$ bundle
Or install it yourself as:
$ gem install showcase
Usage
With Rails, include Showcase::Helpers into your controller and/or views:
# config/initializers/showcase.rb
ActionController::Base.send :include, Showcase::Helpers
ActionView::Base.send :include, Showcase::Helpers
With Padrino, include Showcase::Helpers in your app helpers block.
helpers do
include Showcase::Helpers
end
You can now instantiate new presenters in your controller/views using the included helpers:
# this is the object that needs to be presented
person = Person.new
# automatically infers presenter class to use based on person's class name
present(person) # => returns a PersonPresenter instance
# you can also explicitly tell what presenter to use
present(person, AdminPresenter) # => returns an AdminPresenter instance
# explicit presenter and context
present(person, PersonPresenter, context)
# maps each person in the collection with a presenter
present_collection([person]) # => returns an array of PersonPresenters
Define your presenters i.e. in a app/presenters folder:
class ProjectPresenter < Showcase::Presenter
# automatically wraps the attribute into a PersonPresenter
presents :person
# automatically wraps the attribute into an AdminPresenter
presents :person, with: AdminPresenter
# expects project.task to return an enumerable. automatically wraps each task in a TaskPresenter presenter
presents_collection :tasks
# you can use `view_context`, or the shortcut `h`, to access the context.
# `object` refers to the object being presented
def title
h.link_to object.title, object
end
end
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create new Pull Request