Creating Helper Methods

So far, this chapter has shown you how to use a number of the helper methods that come with Rails. You can also create your own helper methods. There are lots of good reasons to do so:

Less repetition

You can come closer to Rails’ DRY (Don’t Repeat Yourself) ideal if you can combine multiple pieces into a single invocation.

More readable code

You can see more obviously which pieces of your code are actually doing the same work when they call the same method, instead of perpetually reinventing the wheel.

More consistency

The same code used in multiple places will rarely stay identical.

Sharing across views

Multiple views within an application can reference the same helper methods.

Creating helper methods might not be your very first priority in creating an application, but once you have a basic idea of what you want to create in your views, it’s a good idea to start assembling common tasks into helper methods.

Within the application directory structure, helper methods go into the app/helpers directory. At this point, the guestbook application will have two files there: application_helper.rb and people_helper.rb. Helper methods that are defined in application_helper.rb are available to views throughout the entire Rails application, whereas methods defined in people_helper.rb are only available to views that pertain to operations on the person model. For now, the helper methods built in this section can go in people_helper.rb and graduate to application_helper.rb if you think they’re worth sharing across the application.

Note

If you have helper methods with the same names in people_helper.rb and in application_helper.rb, the method in people_helper.rb will take precedence.

The first helper method will take the Example 6-4 code for generating radio buttons from a hash. Example 6-6 shows what’s left when this is reduced to a call to the buttons helper method.

Example 6-6. Creating a sorted set of linked radio buttons from a hash

<% nations = { 'United States of America' => 'USA', 'Canada' => 'Canada', 'Mexico'
=> 'Mexico', 'United Kingdom' => 'UK' }%>

  <p>
    <b>Country</b><br />
    <%= buttons(:person, nations) %>
  </p>

The buttons method is in the people_helper.rb file, the contents of which are shown in Example 6-7.

Example 6-7. Creating a sorted set of linked radio buttons from a hash

1   module PeopleHelper
2
3   def buttons(model_name, target_property, button_source)
4       html=''
5       list = button_source.sort
6       list.each do|x|
7         html << radio_button(model_name, target_property, x[1])
8         html << h(x[0])
9         html << '<br />'
10     end
11     return html
12  end
13
14  end

There’s a lot going on in the buttons method. It’s contained by the PeopleHelper module, which was originally empty in the version created by the scaffolding. Lines 2 through 13 are all new additions. This version of buttons, defined starting on line 3, looks more like the older version of the helper functions, taking a model name as its first argument, then the targeted property, and then the source from which the radio buttons will be created.

Because the helper function isn’t in the view, there isn’t any ERb markup here. Instead, the helper function builds a string, starting in line 4. Often, the first declaration of the string includes the first tag, but as the radio buttons don’t have a containing element, this starts with the empty string. Lines 5 and 6 are the same logic for sorting the hash as was used in the original code from Example 6-3, but the contents of the loop, in lines 7 to 9, are very different.

Lines 7 through 9 all append something to the html variable, using the << operator. Line 7 appends radio button markup created through Rails’ radio_button helper. Line 8 appends the text the user will see, and line 9 appends a <br /> tag, putting a line break between the buttons. Rails developers often avoid mixing explicit markup with code, preferring to use content_tag or other helper methods—but you can use markup here if you think it’s appropriate.

Line 10 just closes the loop over the hash, but line 11 is a bit unusual. Explicit return statements aren’t necessary in Ruby methods unless you’re returning multiple results or want to break at an unexpected time. Ruby will assume that the last variable you touched is the return value. However, using return is a good way to avoid surprises, and if you feel like writing briefer code, you can leave off return and just write html there.

If you leave off line 11 completely, however, you’ll have an unpleasant surprise, shown in Figure 6-6. It looks like html was the last variable touched in line 9, but the each loop block, which closes in line 10, is actually considered the last thing touched. The value of the block is the underlying array, which gets mashed together to yield this unfortunate result.

Instead of radio buttons, an unpleasant squashed list

Figure 6-6. Instead of radio buttons, an unpleasant squashed list

Letting Helper Methods Make Choices

A more sophisticated helper method, shown in Example 6-8, could check the list of items to select from, and decide whether to represent it as a radio buttons or a list, depending on length. It adds an extra if statement, highlighted in the code. This may or may not be a level of smarts you want to build into your helper methods, but it certainly demonstrates how custom helper methods can assemble just a little more logic for your views.

Example 6-8. A helper method that chooses between radio buttons and selection lists

def button_select(model_name, target_property, button_source)
    html=''
    list = button_source.sort 
    if list.length <4
      list.each {|x|
       html << radio_button(model_name, target_property, x[1])
       html << h(x[0])
       html << '<br />'
      }
    else
       html << select(model_name, target_property, list)
    end

    return html
    end
end

There are a lot more things you could do in a helper method, from adding labels to your form components (addressing a complaint from the previous section) to handling calculations.

A More Elegant Helper Method

While the helper method in Example 6-8 works, its foundation is a loop that builds a long string of HTML, using the << operator to concatenate additional content. Example 6-9 is a slightly more idiomatic Ruby version, skipping the creation of an explicit html variable and letting Ruby’s default handling of return values handle what gets sent back to the page.

Example 6-9. A more elegant version of the helper method

def button_select(model_name, target_property, button_source)
     list = button_source.sort
     if list.length < 4
       list.collect do |item|
          radio_button(model_name, target_property, item[1]) +  
h(item[0])
       end.join('<br />')
     else
       select(model_name, target_property, list)
     end
end
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset