What is a Helper?
A helper is a piece of code which can be used in several places within your Ruby project, which helps you to keep your code DRY (Don’t Repeat Yourself). By moving code into helpers you can reduce repetition, improve readability and increase stability.
By moving the code into a seperate section, you’re not writing the same function inside each model where it may be required. As long as you have good documentation on what helpers are available and when they would be used, this can save time when developing projects.
By taking code out of the controller, the controller itself becomes smaller and easier to read. Smaller controllers make understanding the structure of your project simpler.
By having only one location for the definition of a helper, we are reducing the number of places where it can break. Without the use of helpers, you’d have functions within controllers which are repeated throughout the system. This would lead to questions such as “Well, ‘PrintTitle’ is broken, but which one?…. there’s 14 of them…”. Yes, a stack trace would identify the culprit, but why go to that level if you don’t have to.
How about an Example
A common function in a controller might be to print a title. A good example of something to move into a helper.
module TitlesHelper def PrintTitle "<h1>This is a title</h1>" end
def PrintSpecialTitle(thespecialtitle) "<h1>" + thespecialtitle + "</h1>" end
def PrintOptionalSpecialTitle(thespecialtitle, printtitle = nil) if (printtitle) "<h1>" + thespecialtitle + "</h1>" else "<p>No title here</p>" end end end
Helpers will return the value of the last line evaluated!
Note that the helper is written in Ruby, so no escaping is required. To use the above functions in a controller, simply call them as Ruby functions, e.g.
<%= PrintTitle %> <%= PrintSpecialTitle "This is a big title" %> <%= PrintOptionalSpecialTitle "This is a big title", true %> <%= PrintOptionalSpecialTitle "This title won't be seen" %>
These would display
<h1>This is a title</h1> <h1>This is a big title</h1> <h1>This is another big title</h1> <p>No title here</p>
Each controller in your project will have its own designated associated helper module.
app controllers application_controller.rb assets_controller.rb helpers application_helper.rb assets_helper.rb
The associated helper for a controller is automatically loaded when the controller is loaded, or on application load if the command
exists in the application_controller.rb file
So, What’s the Problem with Helpers
Well, what is it? Helpers seem simple enough, don’t they?
The problem is, helpers are disassociated from the Ruby on Rails object model. In a real OO system, Helpers would be assigned to a higher level object, and would then cascade down the object model
In the above model, you’d naturally expect that the helper for the AssetsController would be at the same level in the model as the AssetsController, and would be completely separate from the helper in the PeopleController. So you’d create a polymorphic function called ‘PrintTitle’ in both helpers, expecting the object model to determine which version of ‘PrintTitle’ to call depending upon its context.
But no. It doesn’t.
Rails assumes a common workspace for all helpers. If you declare ‘PrintTitle’ in two different helpers, Ruby will pick one. Or both, in any order. The actual action is not defined in the specification (that we can find), but basically; if you have duplicate names in your helper functions, bad things will happen. Randomly.
If you want a helper to be available specifically to only one controller, you have two choices;
1. Don’t use “helper :all” in your application controller, and specifically (or implicitly) load helpers only in the controllers where they are used.
2. Control your helper namespace, so instead of having a general function called ‘PrintTitle’, have ‘AssetsPrintTitle’ and ‘PeoplePrintTitle’. That way you have only one function in each case. We assume in this case that the two PrintTitle functions are in fact different, as otherwise you’re conflicting with the DRY process.
Helpers are helpful. But they can also be unhelpful. Knowledge brings great Power, and with great Power, Responsibility. Make sure you keep your helpers under control!