Naming your helper methods in Rails can be very difficult. What do you feel when you see this:
To avoid method name collision, we usually have to append the model name in front. Helper methods are also global, so you can access all kinds of helpers in one go.
For me personally, I want the following when I create a helper method:
- easily know where to put a helper method
- easily know how to name the method
Reinventing the wheel
People thought of ways to organize these helper methods, which are now commonly called presenters, decorators or exhibiters.
Built-in helper methods all reside within view-context objects. So for presenter to work it needs access to the view-context object. However passing it for every helper call can be tedius. I liked how draper and active_decorator grabs that view_context for you, so you won't have to keep passing it to presenter when calling it.
However I see that its effort in decorating the model object can easily leak. For example would you remember to also decorate the association objects?
I wanted something else instead, a presenter object which contains only the helper methods. I add a
presenter() method in the model object to access the presenter object. No decoration and less issues. The
presenter() object also takes care of caching the presenter object, so you only instantiate a presenter per model once.
So I made my changes on top the active_decorator, and called it lulalala_presenter (all the good names are taken already).
First install by putting this in the Gemfile:
Say you want to add a
title() helper method for auction, which takes care of truncation and html cleansing. I simply create a AuctionPresenter class. Remember to subclas it with
And then in the view I call it like this
I think it is good to start with less magic, but allow user to add magic if they want more convenience.
By default you use
h to access all the build-in helper methods, and
model to access the model object. If you are lazy you can choose to add stuff in your presenter so you can type less. For example you can delegate a few model attributes:
You can probably also automatically delegate everything to models using other delegation libraries.
For skipping typing
h, you can mix-in active_decorator's helper module so it will redirect calls to view-context using
At the end I quite like my results. For the top example, now I have
Having to type
.presenter when calling helpers isn't so bad as I first thought. This makes it very obvious that the method belongs to presenter, so you won't ever mix up a helper methods with model methods.
My two goals are also fulfilled. If I need an
og_image_tag helper for my auction, I immediately know I should put it in the
AuctionPresenter, and I can name it without worrying about prefixing model names.