One of the core tenets of Ruby on Rails is Don’t Repeat Yourself (frequently abbreviated as DRY). Eliminating repetition is often done through refactoring. Which can be done anywhere your project has repeating or similar stretches of code.
Refactoring views takes a little more effort. Because rails offers helpers and partials as two destinations for code refactored from views. However there are no stone-set rules dictating which should be used where.
Generally partials are better suited for refactoring sections that are more HTML/ERB/HAML than ruby. Helpers on the other hand are used for chunks of ruby code with minimal HTML or generating simple HTML from parameters.
The way helpers are processed hinder their use for producing large amounts of HTML. Which is why helpers produce minimal amounts of HTML. If you look at the source of the helpers that ship with rails you will notice that most of them generate html. The few that don’t, are mainly used to generate parameters and evaluate common conditions.
For example, any of the form helpers or link_to variants fit the first form of helpers. While things like url_for and logged_in? (as supplied by various authentication plugins) are of the second kind.
How to decide whether to extract common/similar view code into partials or helpers?
Every one is going to have their own answer to that question. Here’s the decision chain I use to choose whether to refactor to a partial or helper.
If the answer to any of these questions about the code to be refactored is yes, then it belongs in a helper.
- Repeating [nearly] identical statements producing a single shallow html tag?
- Common expression used as an argument or condition?
- Long expression (more than 3 terms) used as an argument for another helper?
- 4 or more lines of ruby (that is not evaluated into HTML)?
If the answer to all of these questions is no, then it might belong in a partial. I prefer to keep my partials completely independent units. Such that every HTML tag opened in that block is closed in that block and vice versa. While it’s not a necessity it does help to cut down on errors. This is forced when working with HAML, assuming there are no raw HTML closing tags (if there are raw HTML closing tags in your HAML documents, you’re doing it wrong.)
If the answer to any of the following questions about code that could be refactored is yes, then I would extract it into a partial.
- Part of an iterative loop (for, each, etc)?
- Section that could be returned as part of an AJAX call?
- Common code occurring in multiple views?
Answering no to all of the above questions means the there will be trouble refactoring the code cleanly.