This concept is probably familiar, if you know some Ruby basics.
The same simple design is applied to views and helpers.
Hanami ships with default helpers, but we can also define custom helper modules.
Views are Ruby objects that are responsible for rendering the associated template. The context for this activity is defined only by the set of methods that a view can respond to.
If a view has a method , we can use it like this: <%= greeting %>
.
This design has a few important advantages:
- Ruby method dispatcher will be fast, as it doesn’t need to do a lookup for many method sources.
# apps/web/views/books/show.rb
module Web::Views::Books
include Web::View
def home_page_link
link_to "Home", "/"
end
end
Our view responds to , because it includes Hanami::Helpers::LinkToHelper
, a module that defines that concrete method.
There are some helpers that have a huge interface. Think of the HTML5 or the helpers, they provide hundreds of methods to map tags or application routes.
Making them available directly in the view context, would be source of confusion, slow method dispatch times and name collisions.
Imagine we have an application with 100 routes. Because Hanami provides both relative and absolute URI facilities, if used directly, it would mean adding 200 methods to all the views. Which is overkill.
For this reason, certain helpers act as a proxy to access these large set of methods.
In this case we have only one method to add to our views, but it opens an infinite number of possibilities without causing performance issues.
We want to avoid complex expressions that will clutter our templates, and make sure that views remain testable.
Here an example of poor and untestable code in a template.
If we want to unit test this logic, we can’t do it directly, unless we render the template and match the output.
For this reason #format_number
, is shipped as a private method, so we are forced to define an explicit method for our interface.
To be used like this:
<%= downloads_count %>
This version is visually simpler and testable.