Decorators, Presenters, Delegators and Rails
Here is a quite nice and simple way of using Ruby’s SimpleDelegtor class as a Presenter in Ruby on Rails that I have been using recently to encapsulate some view related code from various separate places.
Model != View
Ideally you should decouple your Rails models from any kind of code that deals with presenting and displaying it’s attributes; the model should not be interested in representing anything for the view and one way of doing this code is using a - lets call it a Presenter but it’s just a class that represents display logic for a model.
We’re not talking about moving away from Model View Controller, just separating and encapsulating code that will be used in views into one specific class rather than bolting it onto ActiveRecord models or adding to the generic dumping ground that the Rails helpers (
app/helpers/*_helper.rb) can become.
I think the Rails helper classes should generally be used for utility methods, not for specific use cases such as formatting model attributes for any kind of presentation logic. Keep them light and breezy.
Stuff like this in a view is a smell; too much in the wrong place; get it out of there.
Yay! We can encapsulate these bits of logic and test them to death! We can fire all the test cases you can think of through them (yes, if you use helpers you can test them too but see above) and because we can unit test a Presenter its fast! We can continue to run these tests again and again, each time you run your unit test suite and catch bugs before any high level functional or acceptance tests.
Decorators and Presenters
A nice and simple way of creating a Presenter is to use Ruby’s SimpleDelegtor class to implement the decorator pattern. The SimpleDelegator takes another object in it’s constructor and will add functionality; thus decorating, whilst delegating all other method calls to this object. So based on this, we don’t need to deal with all attributes, we can encapsulate methods intended for use by the view in this new class and keep the the model separate but still access properties.
Strictly speaking Decorators and Presenters are subtlety different and often open to interpretation but here we are using the decorator pattern to create a presenter; we are decorating an object for a specific purpose, that being used in the view.
An example model
Unit tests # not an exhaustive set or sensibly implemented
Back to Rails
So, if you hadn’t guessed already then you can use the Presenter as follows;
So, I think using the decorator pattern is a really neat and simple way of implementing Presenters for Rails models;
- It separates presentation code from the core data model code.
- You don’t need to implement all methods for the model, you can delegate to the model if you wish.
- You can unit test the Presenters.
- You can share common methods between presenters too. (hmmm… reminds me of helpers. :o )
Thanks to someone called goldeneye for the [image].