Helpers are methods that are widely available throughout your application. They are primarily used within templates but are also available within controllers, given the tight coupling of controllers and views in Merb.
The use of helpers greatly simplifies the most common tasks application developers face. Consequently, their structure exhibits some of the best refactoring that web application developers typically run into. That said, we’re going through the helper source extensively, so that you will be comfortable with the methods you use all the time but also with designing your own.
Before continuing, it is worthwhile to mention that most active helpers exist in the module Merb::GlobalHelpers
, which is included at boot within all controllers. You can add your own helper methods to this module within the file app/helpers/global_helpers.rb
. Alternatively, particular controllers may have their own helpers. These should be placed in the file app/helpers/#controller_name_helpers.rb
. The rest of this chapter goes through the helpers found within the module merb-helpers
.
One of the most commonly used helpers included in the Merb helpers is truncate
. It truncates a string at a point and then appends a suffix, making it perfect for the display of preview allotments of text on views:
The default suffix is '...'
, but by passing in a second parameter we can override this. Here’s the source to the method. Note that this helper is essentially a core class extension, which very rarely happens within helpers.
The numeric helpers have been included with the Merb helpers to add in some of the most common conversions applications make between numbers and strings. All of these helpers exist as utility methods of the module Numeric::Transformer
and are made accessible through same-name instance methods in the Numeric
class itself. Keep this in mind as we display the source to each of them.
The two_digits
helper does exactly what it says it does: adds a single leading zero to numbers under 10. This can be useful for displaying dates and is used in other helpers for just that:
8.two_digits # => "08"
The source behind two_digits
is divided into two methods, one API private and the other public:
The helper minutes_to_hours
builds on the two_digits
helper, allowing us to conveniently convert minutes to hours:
345.minutes_to_hours # => "05:55"
Here’s the utility method where everything interesting happens:
The helper method to_currency
converts a numeric into a standard currency string like "$1.99"
. We accomplish this with the following:
1.99.to_currency # => "$1.99"
We can also use other currencies by specifying a locale. This automatically modifies the unit, format, precision, delimiter, and separator:
20.to_currency(:uk) # => "£20.00"
The predefined formats are US, UK, AU, FR, and RU. However, you can easily add more formats using the method add_format
:
Note that in the last two lines we also changed the default currency.
There are also two methods used by to_currency
that are available to the application developer. Let’s take a look at their source, once again noting that a public instance method in Numeric
makes them accessible:
From this we can easily determine how to pass in options for delimiter, separator, and precision that override the defaults. Though the methods above are pretty standard fare for Rubyists writing helpers, you may be interested in studying them if you haven’t done extensive string formatting before.
The module DateAndTimeFormatting
mixes a number of helper methods into the DateTime
, Date
, and Time
classes. It also stores a number of predefined formats and gives you the opportunity to add your own.
Let’s first take a look at the list of provided formats. These can be accessed as a hash by invoking the class method formats
on any of the data and time classes.
• db
—formats a time as databases typically store it
• time
—outputs just the time in 24-hour format
• date
—outputs just the date as year, month, and day
• short
—displays only the day, month (abbreviated), and time
• long
—displays the full date, written out
• rfc822
—formats the time to match RFC 822
We can use these directly by passing one in as the parameter of the method formatted
on an instance of any date or time class:
Time.now.formatted(:date) # => "2009-02-14"
Adding new formats for your application to use is simply a matter of using the add_format
method on any date or time class:
Note that when you add a format, it is added not only to the class on which you used add_format
but to all date and time classes. Let’s peek at the source for this method to understand how this is done:
The formats are all stored within a module called DateAndTimeFormatting
. This module is included within both Date
and Time
, and whenever either is used to add a format, it affects the module itself. It is noteworthy that this helper is consequently not thread-safe. This is because when you add a format in one thread it does not affect the other. To overcome this, we recommend that you put a mutex around any dynamically created formats, or simply define new formats in a boot loader before the application loads.
The module Ordinalize
is used extensively by the date and time helpers and therefore is included there. Nonetheless, it is essentially an extension of the Integer
class. You can use it directly on any integer by calling the method ordinalize
:
The method for ordinalize
is expectedly simple, using only modular arithmetic and one if statement to create the result:
The Merb helpers also include a Time DSL similar to the one found with Rails. This allows us to go from numeric to number of seconds using methods that mimic natural language. For example:
There are also a couple of DSL methods that generate time objects:
Rather then present a comprehensive list of the methods, we present the extremely simple source code to these methods, including their aliasing:
To make the output of dates more relevant to the moment, relative time can be used. For example, instead of giving yesterday’s day, we simply say “yesterday.” There are Merb helpers that can help translate date and time objects to relative time strings. These utility methods are relative_date
, relative_date_span
, relative_time_span
, time_lost_in_words
, and prettier_time
. Here we use them within a view:
As you may have guessed, these methods are included within the module Merb::GlobalHelpers
and are available within views. This also makes them a great template for structuring your own reusable global helpers. Here we present the source to the prettier_time
method but demonstrate the organization of the helpers:
The cycle helper may at first seem to be a peculiarity among helpers, but it can be put to extensive use. Inside the module Merb::helpers::Text
, it is, like the relative time helpers, included within the GlobalHelpers
and thus available to all views. It can be used to continuously step through a list of values, outputting them as necessary. Here we put this to use to alternate the class names on rows of a table:
Cycles can also be reset, so if we had one table followed by another, we might reset the cycle before outputting the second table:
Alternatively, in order to make the positions of cycles independent from one another, we can name each of the cycles we use by passing in a hash as the final parameter. This could be important among cycles that reset within cycles.
Here’s the source behind the cycle
method:
Note that the default cycle name is :default
and that it is extracted from the values using the method extract_options_from_args!
, which is an extension the Merb core makes to Kernel
:
The tag helpers, of which there are only four, are fundamental to the creation of HTML and XML entities. Let’s go through the code that pulls these together:
We find that the tag helpers, like other helpers, are contained within a module and then included within the module Merb::GlobalHelpers
. Remember that this module is included within the Merb::Controller
, and consequently these methods are available to all controllers and all views. The first method, tag
, can take three arguments: name
, contents
, and attrs
. Thus we can create HTML entities as follows:
tag("div","Hello There", :class => "message")
It also takes an optional block that we can use to place in nested entities:
Most of the hard work is done through the other helper methods and to_html_attributes
. Chances are you will not use these helpers within templates themselves, because their real target is within other helpers, allowing for the construction of HTML entities in an abstract, template-agnostic way. In the next section, we’ll see just that.
The design of the form helpers is more complex than that of any of the other helpers described in this chapter. With that in mind, we will not cover the API of helpers entirely in this section and aim only to fundamentally understand the design of helpers by picking apart its quintessential parts. Let’s start off with the underlying builder class upon which the actual helpers rely.
The Form::Builder
module holds
Note the class Base
. It has access to the tag helpers previously described, so we can expect them to be littered throughout the rest of the code. It’s also the class that will be used under the hood by the form helpers themselves. As such, it must maintain three instance variables, two of which may simply end up being nil. The first of these, obj
, is meant as a reference to the model object with which the form may be associated and may be nil. The second, name
, holds the name of the form context, which again is related to the model object and most of the time derived from it. This parameter can also be nil without causing issues. Finally, the parameter origin
links us back to the actual form helper making use of the base. This parameter is strictly necessary.
The two methods form
and fieldset
are used indirectly in the production of form and fieldset elements. We have grouped them together for you because they both make use of blocks passed to them. It’s worthwhile to point out that the capture
method is employed in handling these blocks, which ultimately means that they will be handled by the template engine. You may also have spotted the use of process_form_attrs
:
The processing of form attributes does three things. First, it checks to see if we’ve set the form to use the GET method. If so, it leaves it alone. Otherwise it will use POST. In general, all forms should use POST, unless the form is meant simply as an interface to some complex set of data. The best example of this would be a search form leading to a filtered index. Second, irrespective of the actual method used on the form, the method figures out what the best REST verb is. This later comes into play as a hidden form element that, as we saw very early on while studying the Merb fundamentals, overrides the actual request method used from the perspective of the router. This again is meant to compensate for the lack of availability of all HTTP methods among browsers. Third, the method allows us to use :multipart => true
as shorthand for specifying that the form should accept uploads.
Note that the methods for several fields are dynamically generated. This is because there is inherently nothing special about them. The biggest difference between bound and unbound variants is that the bound variants automatically set a name and value based upon the object of the form context before invoking the unbound method. Below we see the private methods used to generate the name and value attributes.
You may also wonder what the method update_*_controls
is for, but before we get to that let’s analyze at least one of the more complicated form element fields:
The checkbox control is more complicated than those we have seen before, or at least the unbound variant is. Notice how the method bound_check_box
doesn’t set a field value. Where is this work being done?
Inside the cascaded call to update_bound_check_box
we find that the checked attribute is set to true or false based upon either the matching of the control value with the on
value or otherwise when some value generically considered true has been used. Ignoring the specifics for a moment, the method update_bound_check_box
exemplifies the extension of form field behavior. This technique is used not only with many of the bound controls but also with many of the unbound ones.
Remembering how the bound checkbox eventually defers to the behavior of the unbound checkbox, we see that the code above is used by both methods. The argument errors are ways of making sure developers don’t misuse the helper, while the final line shows us that despite whatever value it may have had in the past, the checked attribute simplifies to the HTML oddity of either being present and equal to "checked"
or not there at all. We’ve left out the numerous other methods used behind the scenes by form fields, but we recommend the pure API for help with the specifics of these helpers. If, however, you do run into a bug, you’ll know right where to track it down.
The Base
class for form builders can be extended. For instance, the following subclass of Base
adds labels to forms and is used by the Merb form helpers by default:
The method label
is used to build a label element, but we don’t typically call this method ourselves:
Instead, the methods for individual form elements have been extended to include labels automatically. The code above displays only some of these extended methods. However, all of them make use of the method unbound_label
to determine what to name and caption the label:
Altogether, the application developer should be aware that form helper methods that have not been handed a value for the :label
key within the attributes parameter are not preceded by a label.
Two other extensions of the form builder come as modules. Take your time understanding both, as they probably serve as the best structure for extending the form helpers for your own applications.
This module defines a method error_messages_for
, which can be used to output validation errors related to form objects. Many of the lines are there to handle the various ways ORMs store this error within the properties of an invalidated object.
The private method update_bound_controls
does something sweet with ease: It adds a CSS error class on all specifically invalidated element fields. By now, update_bound_controls
should no longer seem pointless but instead quite useful to developers needing to extend the base form builder.
Above we see the inclusion of the module within a subclass of the Form
builder class. Note, however, that Merb does not use the FormWithErrors
builder by default, but it does use the module above through the builder we’re about to see.
The extension of the method process_form_attrs
allows us to automatically set the action of a form when it is bound to a resource object. In practice this means a form bound to a RESTfully controlled model.
Ending our discussion of form builders, we arrive at the form builder used by default with Merb, ResourcefulFormWithErrors
. Having gone through the greater part of the source for the Merb form builder, you should be aware of how form elements are handled under the hood. However, we did skip the specifics for a number of elements, so you may need to consult the Merb documentation at times, or otherwise adventurously dive into the source code, which by now should cause you no fear.
The Helpers::Form
module holds the actual methods that application developers use with regard to forms. With that in mind, though we will be going through the raw source for them, it’s worth taking the time to let these methods sink in for later use.
The concept of form context is critical to the form helper methods. This is because forms can associate with model objects, and the context of those objects affects how particular form elements should semantically be created. The two methods form_contexts
and current_form_context
serve as a foundation for determining the current context:
The application developer should pay particular attention to the method form
. It is used for forms without any model object context. As a consequence, we see it pull up what is internally called the singleton form context. This context initiates a new form builder or retrieves the last one built. The form
method then delegates the handling of its parameter block to the same-named builder method as in the last section. This, however, is not the only way to construct a form.
In contrast with the method above, form_for
takes a name in addition to its attributes. This name is used to form a specific form context. Note that this name can be either a string/symbol or a variable. This means that :user
and @user
are equivalent. We recommend that you stay away from using strings or symbols because they apply only to instance variables and consequently are not applicable to the local variables of partials. Another takeaway message from the code above is that the form block is handled through a yield
statement that is surrounded by the push and later pop of the form context array. As a web application developer, you may be wondering, Why all the complexity? After all, forms cannot be embedded within one another. Our helpers, however, allow for something a bit different:
The three helpers fields_for
, fieldset
, and fieldset_for
offer us a way of changing the form context from within another form. This versatility means that we can easily produce the appropriate form elements for multiple objects within one form. The distinction between fields_for
and the other two is that fields_for
does not create a fieldset HTML entity. Of course, of interest to us now is the helper method for the particular form elements:
You may find it odd that none of the methods above has any body. The reason for this is to make them available even before they are dynamically generated below.
The templated method above holds the actual code for each of these methods. If it’s your first time, note the explicit use of _ _FILE_ _
and _ _LINE_ _
with a class_eval
. These are there so that exception output actually directs us to the relevant file and line. Inside the method template itself, it delegates to either the bound or the unbound builder methods. The way of determining which is simple:
We realize that the only thing that matters is whether the helper method’s first argument is a symbol or not. This is because the methods above accept a hash of arguments, but a symbol can be added before this hash, effectively indicating that it should be bound within the current form context. The symbol given, therefore, should be that of a model accessor. As we previously saw, this is used to dynamically generate the name attribute on the element. If the form element we need should not be bound, however, then we can explicitly give it its name by setting the value of :name
within the attributes hash.
The label
, button
, and submit
helper methods of course do not need to be bound, so they have been handled separately.
The method error_messages_for
can simplify the output of model object validation errors. Note that we can pass in alternatives to its defaults, which is certainly useful if we need to deviate from standard text.
Finally, the delete_button
method creates a delete form consisting of only a hidden element and a delete button. This helper needs either a specific object to delete or a URL pointing to the path requesting its deletion. The reason for this is simply to avoid misuse of GET requests to alter persisted states on the server.
In this chapter, we explored in depth the code build helpers. That said, both application developers and framework enthusiasts should be able to take away direct insight into how to extend the controllers and views of Merb applications with just about any kind of helper method. We also saw, principally through the form helpers, how a model object can more easily be used within views, tucking away applicable logic almost exclusively into helper code.
3.137.164.69