Chapter 11. All About Helpers

 

“Thank you for helping Helpers Helping the Helpless. Your help was very... helpful!”

 
 --Mrs. Duong in the movie The Weekenders

We’ve already covered some of the helper methods provided by Rails to help you assemble the user interface of your web application. This chapter lists and explains all of the helper modules and their methods, followed by instructions on effectively creating your own helpers.

PrototypeHelper and ScriptaculousHelper were demoted out of Rails core and are now packaged as plugins in Rails 2.0. They are used to easily add Ajax functionality to your Rails application and are covered in-depth within Chapter 12, “Ajax on Rails.”

Note

This chapter is essentially reference material. Although every effort has been made to make it readable straight through, you will notice that coverage of ActionView’s helper modules is arranged alphabetically, starting with ActiveRecordHelper and ending with UrlHelper. Within each module’s section, the methods are broken up into logical groups whenever appropriate.

ActiveRecordHelper

The ActiveRecordHelper module contains helper methods for quickly creating forms from ActiveRecord models. The form method is able to create an entire form for all the basic content types of a given record. However, it does not know how to assemble user-interface components for manipulating associations. Most Rails developers assemble their own forms from scratch using methods from FormHelper, instead of using this module.

Reporting Validation Errors

The error_message_on and error_messages_for methods help you to add formatted validation error information to your templates in a consistent fashion.

error_message_on(object, method, prepend_text = "", append_text = "", css_class = "formError")

Returns a DIV tag containing the error message attached to the specified method on the object, if one exists. The contents can be specialized with parameters for pre- and post-text and custom CSS class, as shown in the signature.

Use of this method is common when the user-interface requirements specify individual validation messages per input field of a form, as in the following real-life example:

<div class="form_field">
  <div class="field_label">
    <span class="required">*</span>
    <label>First Name</label>
  </div>
  <div class="textual">
    <%= form.text_field :first_name, :maxlength => 34, :tabindex => 1
%>
    <%= error_message_on :user, :first_name %>
  </div>
</div>

error_messages_for(*params)

Returns a DIV tag containing all of the error messages for all of the objects held in instance variables identified as parameters. This method is used by Rails scaffolding, but rarely in real production applications. The Rails API documentation advises you to use this method’s implementation as inspiration to meet your own requirements:

This is a prepackaged presentation of the errors with embedded strings and a certain HTML structure. If what you need is significantly different from the default presentation, it makes plenty of sense to access the object.errors instance yourself and set it up. View the source of this method to see how easy it is.

In fact, we’ll go ahead and reproduce the source of the method here with the warning that you should not try to use it as inspiration unless you have a good grasp of Ruby! On the other hand, if you have time to study the way that this method is implemented, it will definitely teach you a lot about the way that Rails is implemented, which is its own distinctive flavor of Ruby.

def error_messages_for(*params)
  options = params.last.is_a?(Hash) ? params.pop.symbolize_keys : {}
  objects = params.collect { |object_name|
              instance_variable_get("@#{object_name}")
            }.compact

  count = objects.inject(0) {|sum, object| sum + object.errors.count }
  unless count.zero?
    html = {}
    [:id, :class].each do |key|
      if options.include?(key)
        value = options[key]
        html[key] = value unless value.blank?
      else
        html[key] = 'errorExplanation'
      end
    end

    header_message = "#{pluralize(count, 'error')} prohibited this
    #{(options[:object_name] || params.first).to_s.gsub('_', ' ')}
    from being saved"

    error_messages = objects.map {|object|
      object.errors.full_messages.map {|msg| content_tag(:li, msg)}
    }

    content_tag(:div,
      content_tag(options[:header_tag] || :h2, header_message) <<
      content_tag(:p, 'There were problems with the following fields:') <<
      content_tag(:ul, error_messages), html )
  else
    ''
  end
end

Later on in the chapter we’ll talk extensively about writing your own helper methods.

Automatic Form Creation

The next couple of methods are used for automatic field creation by the scaffolding code. You can try using them too, but I suspect that their usefulness is somewhat limited in real applications.

form(name, options)

Returns an entire form with input tags and everything for a named ActiveRecord model object. Here are the code examples given in the Rails API documentation, using a hypothetical Post object from a bulletin-board application as an example:

> form("post")

=> <form action='/post/create' method='post'>
     <p>
       <label for="post_title">Title</label><br/>
       <input id="post_title" name="post[title]"
              size="30" type="text" value="Hello World" />
     </p>
     <p>
        <label for="post_body">Body</label><br/>
        <textarea cols="40" id="post_body" name="post[body]"
rows="20">
          Back to the hill and over it again!
        </textarea>
     </p>
     <input type='submit' value='Create' />
   </form>

Internally, the method calls record.new_record? to infer whether the action for the form should be create or update. It is possible to explicitly specify the action of the form (and the value of the submit button along with it) by using the :action option.

If you need the form to have its enctype set to multipart, useful for file uploads, set the options[:multipart] to true.

You can also pass in an :input_block option, using Ruby’s Proc.new idiom to create a new anonymous code block. The block you supply will be invoked for each content column of your model, and its return value will be inserted into the form.

> form("entry", :action => "sign",
    :input_block => Proc.new { |record, column|
      "#{column.human_name}: #{input(record, column.name)}<br/>" })

=> <form action='/post/sign' method='post'>
     Message:
     <input id="post_title" name="post[title]" size="30"
            type="text" value="Hello World" /><br />
     <input type='submit' value='Sign' />
   </form>

That example’s builder block, as it is referred to in the Rails API docs, uses the input helper method, which is also part of this module, and is covered in the next section of this chapter.

Finally, it’s also possible to add additional content to the form by giving the call to form a block, as in the following snippet:

form("entry", :action => "sign") do |s|
  s << content_tag("b", "Department")
  s << collection_select("department", "id", @departments, "id",
"name")
end

The block is yielded a string accumulator (named s in the example), to which you append any additional content that you want to appear between the main input fields and the submit tag.

input(name, method, options)

The appropriately named input method takes some identifying information, and automatically generates an HTML input tag based on an attribute of an ActiveRecord model. Going back to the Post example used in the explanation of form, here is the code snippet given in the Rails API docs:

input("post", "title")

=> <input id="post_title" name="post[title]" size="30"
          type="text" value="Hello World" />

To quickly show you the types of input fields generated by this method, I’ll simply reproduce a portion of the code from the ActiveRecordHelper module itself:

def to_tag(options = {})
  case column_type
    when :string
      field_type = @method_name.include?("password") ? "password" :
"text"
      to_input_field_tag(field_type, options)
    when :text
      to_text_area_tag(options)
    when :integer, :float, :decimal
      to_input_field_tag("text", options)
    when :date
      to_date_select_tag(options)
    when :datetime, :timestamp
      to_datetime_select_tag(options)
    when :time
      to_time_select_tag(options)
    when :boolean
      to_boolean_select_tag(options)
  end
end

Customizing the Way Validation Errors Are Highlighted

By default, when Rails marks a field in your form that failed a validation check, it does so by wrapping that field in a DIV element, with the class name fieldWithErrors. This behavior is actually customizable, since it is accomplished via a Proc object stored as a configuration property of the ActionView::Base class:

module ActionView
  class Base
    @@field_error_proc = Proc.new { |html_tag, instance|
      "<div class="fieldWithErrors">#{html_tag}</div>"
    }
    cattr_accessor :field_error_proc
  end

  ...

Armed with this knowledge, changing the validation error behavior is as simple as overriding ActionView’s field_error_proc attribute with your own custom Proc. I would suggest doing so either in config/environment.rb or your ApplicationController class.

In Listing 11.1, I changed the setting so that the input fields with validation errors are prefixed with a red ERR message.

Example 11.1. Custom Validation Error Display

ActionView::Base.field_error_proc =
   Proc.new do |html_tag,instance|
     %(<div style="color:red">ERR</div>) + html_tag
   end

It has been suggested by many people that it would have been a much better default solution to simply add a fieldWithErrors CSS class to the input tag itself, instead of wrapping it with an extra DIV tag. Indeed, that would have made many of our lives easier, since an extra DIV often breaks pixel-perfect layouts. However, since html_tag is already constructed at the time when the field_error_proc is invoked, it is not trivial to modify its contents.

There are some solutions out there that use regular expressions and modify the html_tag string, for instance this one, found at http://snippets.dzone.com/tag/field_error_proc:

ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
  error_style = "background-color: #ffff80"
  if html_tag =~ /<(input|textarea|select)[^>]+style=/
    style_attribute = html_tag =~ /style=['"]/
    html_tag.insert(style_attribute + 7, "#{error_style}; ")
  elsif html_tag =~ /<(input|textarea|select)/
    first_whitespace = html_tag =~ /s/
    html_tag[first_whitespace] = " style='#{error_style}' "
  end
  html_tag
end

Ugly! This is certainly an area of ActionView that could use improvement.

AssetTagHelper

According to the Rails API docs, this module

Provides methods for linking an HTML page together with other assets such as images, javascripts, stylesheets, and feeds. You can direct Rails to link to assets from a dedicated assets server by setting ActionController::Base.asset_host in your environment.rb. These methods do not verify the assets exist before linking to them.

The AssetTagHelper module includes some methods that you will use on a daily basis during active Rails development, particularly image_tag.

Head Helpers

Most of the helper methods in this module help you add content to the HEAD of your HTML document.

auto_discovery_link_tag(type = :rss, url_options = {}, tag_options = {})

Returns a link tag that browsers and newsreaders can use to autodetect an RSS or ATOM feed. The type can either be :rss (default) or :atom. Control the link options in url_for format using the url_options.

You can modify the LINK tag itself using the tag_options parameter:

  • :relSpecify the relation of this link; defaults to "alternate".

  • :typeOverride MIME type (such as "application/atom+xml") that Rails would otherwise generate automatically for you.

  • :titleSpecify the title of the link; defaults to a capitalized type.

Here are examples of usages of auto_discovery_link_tag as shown in the Rails API docs:

auto_discovery_link_tag # =>
  <link rel="alternate" type="application/rss+xml" title="RSS"
  href="http://www.curenthost.com/controller/action" />

auto_discovery_link_tag(:atom) # =>
  <link rel="alternate" type="application/atom+xml" title="ATOM"
  href="http://www.curenthost.com/controller/action" />

auto_discovery_link_tag(:rss, {:action => "feed"}) # =>
  <link rel="alternate" type="application/rss+xml" title="RSS"
  href="http://www.curenthost.com/controller/feed" />

auto_discovery_link_tag(:rss, {:action => "feed"}, {:title => "My
RSS"}) # =>
  <link rel="alternate" type="application/rss+xml" title="My RSS"
  href="http://www.curenthost.com/controller/feed" />

image_path(source)

Computes the path to an image asset in the public/images directory. Full paths from the document root (beginning with a “/”) will be passed through. This method is used internally by image_tag to build the image path. Passing a filename without an extension, as was practiced in early versions of Rails, is no longer supported.

image_path("edit.png")  # => /images/edit.png
image_path("icons/edit.png")  # => /images/icons/edit.png
image_path("/icons/edit.png")  # => /icons/edit.png

image_tag(source, options = {})

Returns an IMAGE tag for use in a template. The source parameter can be a full path or a file that exists in your public images directory. You can add additional arbitrary attributes to the IMAGE tag using the options parameter.

The following two options are treated specially:

  • :altIf no alternate text is given, the filename part of the source is used, after being capitalized and stripping off the extension.

  • :sizeSupplied as widthxheight so "30x45" becomes the attributes width="30" and height="45". The :size option will fail silently if the value is not in the correct format.

image_tag("icon.png")  # =>
  <img src="/images/icon.png" alt="Icon" />

image_tag("icon.png", :size => "16x10", :alt => "Edit Entry")  # =>
  <img src="/images/icon.png" width="16" height="10" alt="Edit Entry"
/>

image_tag("/photos/dog.jpg", :class => 'icon')  # =>
  <img src="/photos/icon.gif" alt="Dog" class="icon"/>

javascript_include_tag(*sources)

Returns a SCRIPT tag for each of the sources provided. You can pass in the filename (the .js extension is optional) of JavaScript files that exist in your public/javascripts directory for inclusion into the current page, or you can pass their full path, relative to your document root.

To include the Prototype and Scriptaculous JavaScript libraries in your application, pass :defaults as the source. When you’re using :defaults, if an application.js file exists in your public/javascripts directory, it will be included as well. You can modify the attributes of the SCRIPT tag by passing a hash as the last argument.

javascript_include_tag "xmlhr", :defer => 'defer' # =>
  <script type="text/javascript" src="/javascripts/xmlhr.js"
  defer="defer"></script>

javascript_include_tag "common.javascript", "/elsewhere/cools" # =>
  <script type="text/javascript"
src="/javascripts/common.javascript"></script>
  <script type="text/javascript" src="/elsewhere/cools.js"></script>

javascript_include_tag :defaults # =>
  <script type="text/javascript"
src="/javascripts/prototype.js"></script>
  <script type="text/javascript"
src="/javascripts/effects.js"></script>
  ...
  <script type="text/javascript"
src="/javascripts/application.js"></script>

javascript_path(source)

Computes the path to a JavaScript asset in the public/javascripts directory. If the source filename has no extension, .js will be appended. Full paths from the document root will be passed through. Used internally by javascript_include_tag to build the script path.

stylesheet_link_tag(*sources)

Returns a stylesheet LINK tag for the sources specified as arguments. If you don’t specify an extension, .css will be appended automatically. Just like other helper methods that take a variable number of arguments plus options, you can pass a hash of options as the last argument and they will be added as attributes to the tag.

stylesheet_link_tag "style" # =>
  <link href="/stylesheets/style.css" media="screen"
        rel="Stylesheet" type="text/css" />

stylesheet_link_tag "style", :media => "all" # =>
  <link href="/stylesheets/style.css" media="all"
        rel="Stylesheet" type="text/css" />

stylesheet_link_tag "random.styles", "/css/stylish" # =>
  <link href="/stylesheets/random.styles" media="screen"
        rel="Stylesheet" type="text/css" />
  <link href="/css/stylish.css" media="screen"
        rel="Stylesheet" type="text/css" />

stylesheet_path(source)

Computes the path to a stylesheet asset in the public/stylesheets directory. If the source filename has no extension, .css will be appended. Full paths from the document root will be passed through. Used internally by stylesheet_link_tag to build the stylesheet path.

For Plugins Only, Add Default JavaScript Includes

The register_javascript_include_default class method of ActionView::Helpers::AssetTagHelper lets plugin authors register one or more additional JavaScript files to be included when javascript_include_tag :defaults is called. This method is only intended to be called from plugin initialization to register additional .js files that the plugin installed in public/javascripts. You can find more details about this method in Chapter 19, “Extending Rails with Plugins.”

BenchmarkHelper

One of the less frequently mentioned innovations in Rails is the usefulness of its built-in logging facilities. The BenchmarkHelper module adds the ability to time arbitrary bits of template code, and is useful when analyzing an application, looking for performance bottlenecks.

benchmark(message = "Benchmarking", level = :info)

Measures the execution time of a block in a template and reports the result to the log.

<% benchmark "Notes section" do %>
  <%= expensive_notes_operation %>
<% end %>

The preceding example will add something like “Notes section (0.34523)” to the log when the template is executed. It’s possible to give an optional logger level as the second argument (:debug, :info, :warn, :error), but the default is :info.

CacheHelper

This module only contains one method, named cache. It is used to perform fragment caching of blocks within templates, without caching the output of an entire action as a whole. Rails also features page caching using the caches_page method of controllers, where the entire output of an action is stored as a HTML file that the web server can serve without going through the Action Pack.

In contrast, fragment caching is useful when certain elements of an action change frequently or depend on complicated state, while other parts rarely change or can be shared among multiple parties. The boundaries of a fragment to be cached are defined within a view template using the cache helper method. The topic was covered in detail in the caching section of Chapter 2, “Working with Controllers.”

CaptureHelper

One of the great features of Rails views is that you are not limited to rendering a single “flow” of content. Along the way, you can define blocks of template code that should be inserted into other parts of the page during rendering using yield. The technique is accomplished via a pair of methods from the CaptureHelper module.

capture(&block)

The capture method lets you capture part of a template’s output (inside a block) and assign it to an instance variable. The value of that variable can subsequently be used anywhere else on the template.

<% @message_html = capture do %>
<div>This is a message</div>
<% end %>

I don’t think that the capture method is really that useful on its own in a template. It’s a lot more useful when you use it in your own custom helper methods. It gives you the ability to write your own helpers that grab template content wrapped using a block. We cover that technique later on in this chapter in the section “Writing Your Own Helpers.”

content_for(name, &block)

We mentioned the content_for method in Chapter 10 in the section “Yielding Content.” It allows you to designate a part of your template as content for another part of the page. It works similarly to its sister method capture (in fact, it uses capture itself). Instead of returning the contents of the block provided to it, it stores the content to be retrieved using yield elsewhere in the template (or most commonly, in the surrounding layout).

A common example is to insert “sidebar” content into a layout. In the following example, the link will not appear in the “flow” of the view template—it will appear elsewhere in the template, wherever <%= yield :navigation_sidebar %> appears.

<% content_for :navigation_sidebar do %>
  <%= link_to 'Detail Page', item_detail_path(item) %>
<% end %>

DateHelper

The DateHelper module is used primarily to create HTML select tags for different kinds of calendar data. It also features one of the longest-named helper methods, a beast peculiar to Rails, called distance_of_time_in_words_to_now.

The Date and Time Selection Helpers

The following methods help you create form field input tags dealing with date and time data. All of them are prepared for multiparameter assignment to an ActiveRecord object. That’s a fancy way of saying that even though they appear in the HTML form as separate input fields, when they are posted back to the server, it is understood that they refer to a single attribute of the model. That’s some Rails magic for you!

date_select(object_name, method, options = {})

Returns a matched set of three select tags (one each for year, month, and day) preselected for accessing a specified date-based attribute (identified by the method parameter) on an object assigned to the template (identified by the object_name parameter).

It’s possible to tailor the selects through the options hash, which accepts all the keys that each of the individual select builders do (like :use_month_numbers for select_month).

The date_select method also takes :discard_year, :discard_month, and :discard_day options, which drop the corresponding select tag from the set of three. Based on common sense, discarding the month select will also automatically discard the day select. If the day is omitted, but not the month, Rails will assume that the day should be the first of the month.

It’s also possible to explicitly set the order of the tags using the :order option with an array of symbols :year, :month, and :day in the desired order. Symbols may be omitted and the respective select tag is not included.

Passing :disabled => true as part of the options will make elements inaccessible for change (see Listing 11.2).

Example 11.2. Examples of date_select

date_select("post", "written_on")

date_select("post", "written_on", :start_year => 1995,
                                  :use_month_numbers => true,
                                  :discard_day => true,
                                  :include_blank => true)

date_select("post", "written_on", :order => [:day, :month, :year])

date_select("user", "birthday",   :order => [:month, :day])

datetime_select(object_name, method, options = {})

Works exactly like date_select, except for the addition of hour and minute select tags. Seconds may be added with the option :include_seconds. Along with the addition of time information come additional discarding options: :discard_hour, :discard_minute, and :discard_seconds.

time_select(object_name, method, options = {})

Returns a set of select tags (one for hour, minute, and optionally second) preselected for accessing a specified time-based attribute (identified by method) on an object assigned to the template (identified by object_name). You can include the seconds with :include_seconds.

time_select("post", "sunrise")
time_select("post", "start_time", :include_seconds => true)

The Individual Date and Time Select Helpers

Sometimes you need just a particular element of a date or time, and Rails obliges you with a comprehensive set of individual date and time select helpers. In contrast to the date and time helpers that we just looked at, the following helpers are not bound to an instance variable on the page. Instead, they all take a date or time Ruby object as their first parameter. (All of these methods have a set of common options, covered in the following subsection.)

select_date(date = Date.today, options = {})

Returns a set of select tags (one each for year, month, and day) preselected with the date provided (or the current date). It’s possible to explicitly set the order of the tags using the :order option with an array of symbols :year, :month, and :day in the desired order.

select_datetime(datetime = Time.now, options = {})

Returns a set of select tags (one each for year, month, day, hour, and minute) preselected with the datetime. Optionally add a seconds field using the :include_seconds => true option. It’s also possible to explicitly set the order of the tags using the :order option with an array of symbols :year, :month, and :day, :hour, :minute, and :seconds in the desired order. You can also add character values for the :date_separator and :time_separator options to control visual display of the elements (they default to “/” and “:”).

select_day(date, options = {})

Returns a select tag with options for each of the days 1 through 31 with the current day selected. The date can also be substituted for an hour number. Override the field name using the :field_name option. It defaults to day. The date parameter may be substituted by a value from 1 to 31.

select_hour(datetime, options = {})

Returns a select tag with options for each of the hours 0 through 23 with the current hour selected. The datetime parameter can be substituted with an hour number from 0 to 23.

select_minute(datetime, options = {})

Returns a select tag with options for each of the minutes 0 through 59 with the current minute selected. Also can return a select tag with options by minute_step from 0 through 59 with the 00 minute selected. The datetime parameter can be substituted by a seconds value of 0 to 59.

select_month(date, options = {})

Returns a select tag with options for each of the months January through December with the current month selected. By default, the month names are presented as user options in the drop-down selection and the month numbers (1–12) are used as values submitted to the server.

It’s also possible to use month numbers for the presentation instead of names, by setting :use_month_numbers => true. If you happen to want both numbers and names, set the :add_month_numbers => true. If you would prefer to show month names as abbreviations, set the :use_short_month key => true. Finally, if you want to use your own month names, set the value of the :use_month_names key in your options to an array of 12 month names.

# Will use keys like "January", "March"
select_month(Date.today)

# Will use keys like "1", "3"
select_month(Date.today, :use_month_numbers => true)

# Will use keys like "1 - January", "3 - March"
select_month(Date.today, :add_month_numbers => true)

# Will use keys like "Jan", "Mar"
select_month(Date.today, :use_short_month => true)

# Will use keys like "Januar", "Marts"
select_month(Date.today, :use_month_names => %w(Januar Februar
Marts ...))

Override the field name using the :field_name option. It defaults to month.

select_second(datetime, options = {})

Returns a select tag with options for each of the seconds 0 through 59 with the current second selected. The datetime parameter can either be a DateTime object or a second given as a number.

select_time(datetime, options = {})

Returns a set of HTML select tags (one for hour and minute). You can set :add_separator key to format the output.

select_year(date, options = {})

Returns a select tag with options for each of the five years on each side of the current year, which is selected. The five-year radius can be changed using the :start_year and :end_year options. Both ascending and descending year lists are supported by making :start_year less than or greater than :end_year. The date parameter can either be a Date object or a year given as a number.

# ascending year values
select_year(Date.today, :start_year => 1992, :end_year => 2007)

# descending year values
select_year(Date.today, :start_year => 2005, :end_year => 1900)

Common Options for Date Selection Helpers

All of the select-type methods share a number of common options that are as follows:

  • :discard_typeSet to true if you want to discard the type part of the select name. If set to true, the select_month method would use simply date (which can be overwritten using :prefix) instead of date[month].

  • :field_nameAllows you to override the natural name of a select tag (from day, minute, and so on).

  • :include_blankSet to true if it should be possible to set an empty date.

  • :prefixOverwrites the default prefix of date used for the names of the select tags. Specifying birthday would result in a name of birthday[month] instead of date[month] when passed to the select_month method.

  • :use_hiddenSet to true to embed the value of the datetime into the page as an HTML hidden input, instead of a select tag.

distance_in_time Methods with Complex Descriptive Names

Some distance_in_time methods have really long, complex descriptive names that nobody can ever remember without looking them up. Well, at least for the first dozen times or so you might not remember.

I find the following methods to be a perfect example of the Rails way when it comes to API design. Instead of going with a shorter and necessarily more cryptic alternative, the framework author decided to keep the name long and descriptive. It’s one of those cases where a nonprogrammer can look at your code and understand what it’s doing. Well, probably.

I also find these methods remarkable in that they are part of why people sometimes consider Rails part of the Web 2.0 phenomenon. What other web framework would include ways to humanize the display of timestamps?

distance_of_time_in_words(from_time, to_time = 0, include_seconds = false)

Reports the approximate distance in time between two Time or Date objects or integers as seconds. Set the include_seconds parameter to true if you want more detailed approximations when the distance is less than one minute.

Want to know how the times map out to expressions? Here is the implementation, which I think is some pretty cool Ruby code:

def distance_of_time_in_words(from_time, to_time = 0, include_seconds =
false)

  from_time = from_time.to_time if from_time.respond_to?(:to_time)
  to_time = to_time.to_time if to_time.respond_to?(:to_time)

  d_minutes = (((to_time - from_time).abs)/60).round
  d_seconds = ((to_time - from_time).abs).round

  case d_minutes
    when 0..1
      unless include_seconds
        return (d_minutes==0) ? 'less than a minute' : '1 minute'
      end

      case d_seconds
        when 0..4   then 'less than 5 seconds'
        when 5..9   then 'less than 10 seconds'
        when 10..19 then 'less than 20 seconds'
        when 20..39 then 'half a minute'
        when 40..59 then 'less than a minute'
        else             '1 minute'
      end

    when 2..44      then "#{d_minutes} minutes"
    when 45..89     then 'about 1 hour'
    when 90..1439   then "about #{(d_minutes.to_f/60.0).round} hours"
    when 1440..2879      then '1 day'
    when 2880..43199     then "#{(d_minutes / 1440).round} days"
    when 43200..86399    then 'about 1 month'
    when 86400..525599   then "#{(d_minutes / 43200).round} months"
    when 525600..1051199 then 'about 1 year'
    else                      "over #{(d_minutes / 525600).round}
years"
  end
end

The Rails API docs ask you to note that Rails calculates one year as 365.25 days.

distance_of_time_in_words_to_now(from_time, include_seconds = false)

Works exactly like distance_of_times_in_words except that the to_time is hard-coded to the current time. Usually invoked on created_at or updated_at attributes of your model, followed by the string ago in your template, as in the following example:

<strong><%= comment.user.name %></strong><br/>
<small><%= distance_of_time_in_words_to_now review.created_at %>
ago</small>

DebugHelper

The DebugHelper module only contains one method, named debug. Output it in your template, passing it an object that you want dumped to YAML and displayed in the browser inside PRE tags. Useful for debugging during development, but not much else.

FormHelper

The FormHelper module provides a set of methods for working with HTML forms, especially as they relate to ActiveRecord model objects assigned to the template. Its methods correspond to each type of HTML input fields (such as text, password, select, and so on) available. When the form is submitted, the value of the input fields are bundled into the params that is passed to the controller.

There are two types of form helper methods. The types found in this module are meant to work specifically with ActiveRecord model attributes, and the similarly named versions in the FormTagHelper module are not.

Creating Forms for ActiveRecord Models

The core method of this helper is called form_for, and we covered it to some extent in Chapter 4, “REST, Resources, and Rails.” You pass it the name of the model you want to create a form for (or the model instance itself), as its first parameter, followed by URL information for the HTML form’s action attribute. The helper method yields a form object, on which you can invoke input helper methods, omitting their first argument.

Assume we want a form for the user to create a new Person record and additionally assume that @person = Person.new happened in the action of the controller that is rendering this template code:

<% form_for :person, @person, :url => { :action => "create" } do
|form| %>
  <%= form.text_field :first_name %>
  <%= form.text_field :last_name %>
  <%= submit_tag 'Create' %>
<% end %>

This is the equivalent (old-school) version of form_for, which doesn’t use a yielded form object and explicitly names the object being used in the input fields:

<% form_for :person, @person, :url => { :action => "create" } do %>
  <%= text_field :person, :first_name %>
  <%= text_field :person, :last_name %>
  <%= submit_tag 'Create' %>
<% end %>

The first version has less repetition (remember your DRY principle), but don’t forget the more verbose style entirely—it’s necessary in some circumstances.

Variables Are Optional

If you explicitly specify the object name parameter for input fields rather than letting them be supplied by the form, keep in mind that it doesn’t have to match a “live” object instance in scope for the template. Rails won’t complain if the object is not there—it will simply put blank values in the resulting form.

Rails-Generated Form Conventions

The HTML generated by the form_for invocations in the preceding example is characteristic of Rails forms, and follows specific naming conventions:

<form action="/persons/create" method="post">
  <input id="person_first_name" name="person[first_name]" size="30"
type="text" />
  <input id="person_last_name" name="person[last_name]" size="30"
type="text" />
  <input name="commit" type="submit" value="Create" />
</form>

When this form is submitted, the params hash will look like the following example (using the format reflected in your development log for every request):

Parameters: {"commit"=>"Create", "action"=>"create",
"controller"=>"persons",
 "person"=> {"first_name"=>"William", "last_name"=>"Smith"}}

As you can see, the params hash has a nested "person" value, which is accessed using params[:person] in the controller. That’s pretty fundamental Rails knowledge, and I’d be surprised if you didn’t know it already. I promise we won’t rehash much more basic knowledge after the following section.

Displaying Existing Values

If you were editing an existing instance of Person, that object’s attribute values would have been filled into the form, making the resulting HTML look something like this:

<form action="/persons/create" method="post">
  <input id="person_first_name" name="person[first_name]" size="30"
type="text" value="Obie"/>
  <input id="person_last_name" name="person[last_name]" size="30"
type="text" value="Fernandez"/>
  <input name="commit" type="submit" value="Create" />
</form>

Okay, that’s also pretty fundamental Rails knowledge. What about if you want to edit a new model object instance, prepopulated with certain values? Do you have to pass the values as options to the input helper methods? No. Since the form helpers display the values of the model’s attributes, it would simply be a matter of initializing the object with the desired values in the controller, as follows:

def new
  @person = Person.new(:first_name => 'First', :last_name => 'Last')
end

Since you’re only using new, no record is persisted to the database, and your default values magically appear in the input fields.

Updating Multiple Objects at Once

That’s all well and good for editing one object at a time. What if you want to edit multiple records at the same time? When the attribute name passed to form_for or individual input field helper methods contains a set of square brackets, the id for the object will be included in the autogenerated name and id attributes of the input tag.

I find this technique potentially challenging, on a couple of levels. First of all, we usually identify attribute names using symbols, but tacking a pair of square brackets onto a symbol (like :name[]) is invalid. We’re forced to use a string to name the object instead:

<% form_for "person[]" do |form| %>
 <% for @person in @people %>
  <%= form.text_field :name %>
  ...

Secondly, it generates HTML for the input tags looking something like this:

<input type="text" id="person_8_name" name="person[8][name]"
 value="Obie Fernandez"/>

Whoa! The structure of the hash submitted to the controller is significantly different than what we’re used to seeing. That nested params hash will now be three levels deep when it comes to the "person" and to make it more confusing, the ids of the objects are being used as has keys:

Parameters: {"person"=>{"8"=>{"name"=>"Obie Fernandez"},
                        "9"=>{"name"=>"Jodi Showers"}, ...}, ... }

Now the controller code to handle the form needs to change, or you’re likely to see a stack trace like the following one:

NoMethodError (undefined method `8=' for #<User:0x8762174>):
    /vendor/rails/activerecord/lib/active_record/base.rb:2032:in
`method_missing'

The good news is that the way that you handle that nested hash structure in your controller’s update method is probably one of the nicest examples of how Rails is well integrated across its MVC layers:

Person.update(params[:person].keys, params[:person].values)

Beautiful! This is the sort of thing that makes the Rails way so enjoyable.

Square Brackets with New Records?

If you have a way of inserting HTML into your document dynamically, via JavaScript and/or AJAX techniques, you can leverage Rails’ behavior with regard to empty square brackets.

When you’re using the square-brackets naming, Rails will happily generate HTML for new model objects that looks like this:

<input type="text" id="person__name" name="person[][name]"/>

If you were dynamically adding rows of child record entry forms to a parent form, you could replicate that convention easily. Just make sure the names of your input fields have the empty square brackets.

When you submit the form, the Rails request dispatcher will assume that the value of the :person key in the params hash is supposed to be an Array, and that is what you will have to deal with in the controller action as the value of params[:person], an array!

Considering that the create class method of ActiveRecord models takes an array or hashes to do multiple inserts, we have yet another one of those beautiful examples of Rails cross-layer integration:

def add_people
  Person.create(params[:person])
  ...
end

However, there are some drawbacks to this technique, because it only works when all of the input fields in the person namespace have empty square brackets. Stick any other input fields on the same object without the empty square brackets, and the Rails dispatcher will get very, very unhappy about it:

DISPATCHER FAILSAFE RESPONSE (has cgi) Sun Jul 15 14:36:35 -0400 2007
  Status: 500 Internal Server Error
  Conflicting types for parameter containers. Expected an instance of
  Hash but found an instance of Array. This can be caused by colliding
  Array and Hash parameters like qs[]=value&qs[key]=value.

Indexed Input Fields

Okay, moving forward, here is a slightly more verbose and less magical way to define multiple sets of input fields—use the :index option of the input field methods themselves. It lets you explicitly provide an identifier that will be inserted into the field names, and in doing so opens up some interesting possibilities.

First, it lets you replicate the square brackets technique that we just discussed in the preceding section. For example, here’s a set of name fields for a collection of people:

<% for @person in @people %>
<%= text_field :person, :name, :index => @person.id %>
...

The id attribute of the person will be inserted into the parameter hash in the way we’ve already discussed with the square brackets, and we’ll get the same nesting behavior.

Now to make it more interesting, notice that the :index option is not picky about the type of identifier that you supply it, which makes it pretty useful for defining enumerated sets of records! That is exactly what sets it apart from the square-brackets technique, and I’m sure I need to explain it a little more.

Consider the template code in Listing 11.3, part of a basketball tournament application (or in a more generalized guise, any application that stores people in well-defined roles):

Example 11.3. Basketball Team Entry Form

<% form_for :team do |f|%>
  <h2>Team Name</h2>
  Name: <%= f.text_field :name %><br/>
  Coach: <%= f.text_field :coach %>
  <% ["guard_1", "guard_2", "forward_1", "forward_2", "center"].each
{|role| %>
    <h3><%= role.humanize %></h3>
    Name: <%= text_field :players, :name, :index => role %>
  <% } %>
<% end %>

That code produces the following HTML output when you run it:

<form method="post" action="/homepage/team">
  <h2>Team Name</h2>
  Name: <input id="team_name" type="text" size="30"
name="team[name]"/><br/>
  Coach: <input id="team_coach" type="text" size="30"
name="team[coach]"/>
  <h3>Guard 1</h3>
  Name: <input id="players_guard_1_name" type="text" size="30"
  name="players[guard_1][name]"/>
  <h3>Guard 2</h3>
  Name: <input id="players_guard_2_name" type="text" size="30"
  name="players[guard_2][name]"/>
  <h3>Forward 1</h3>
  Name: <input id="players_forward_1_name" type="text" size="30"
  name="players[forward_1][name]"/>
  <h3>Forward 2</h3>
  Name: <input id="players_forward_2_name" type="text" size="30"
  name="players[forward_2][name]"/>
  <h3>Center</h3>
  Name: <input id="players_center_name" type="text" size="30"
  name="players[center][name]"/>
</form>

Now when you submit that form (as I just did, using one of my favorite basketball teams of all time), your controller action would receive the following parameters hash. I took the liberty of formatting the log output nicely, to make sure the structure is clear:

Parameters: {"team"=>{
               "name"=>"Chicago Bulls",
               "coach"=>"Phil Jackson"},
            {"players"=> {
                "forward_1"=>{"name"=>"Scottie Pippen"},
                "forward_2"=>{"name"=>"Horace Grant"},
                "center"=>{"name"=>"Bill Cartwright"},
                "guard_1"=>{"name"=>"Michael Jordan"},
                "guard_2"=>{"name"=>"John Paxson"}}, ... }

I made it a point to give those text field inputs for the player’s names and ages their own :players identifier, rather than linking them to the form’s team object. You don’t even need to worry about initializing an @players variable for the form to work. Form helper methods do not complain if the variable they’re supposed to reflect is nil, provided you identify it using a symbol and not by passing the instance variable directly to the method.

For the sake of completeness, I’ll give you some simplistic controller action code in Listing 11.4 that is capable of handling the form submission.

Example 11.4. Controller Action to Create Team

def create
  @team = Team.create(params[:team])
  params[:players].keys.each do |role|
    @team.add_player(role, Player.new(params[:players][role]))
  end
  ...
end

Taking into account the nested parameters hash, we can take it apart in a loop based on params[:players].keys and do operations per role. Of course, this code assumes that the team has an instance method add_player(role, player), but I think you should get my drift.

Faux Accessors

“Now hold on a second,” you are probably saying to yourself. If our example Team model knew how to handle the setting of a players hash as part of its attributes, the controller code could be dramatically simpler. In fact, we could knock it down to just one line (excluding error checking and redirection):

def create
  @team = Team.create(params[:team])
  ...
end

Impressive, huh? (It is to me!) What we need is to cheat with what Josh Susser calls faux accessors[1]—setters that let you initialize parts of a model that aren’t (database-backed) attributes. Our example Team model would need a players writer method that understood how to add those players to itself. Perhaps it would look like the example in Listing 11.5.

Example 11.5. Adding Writer Methods That Understand Params Hashes

class Team < ActiveRecord::Base
  has_many :positions
  has_many :players, :through => :positions

  def players=(players_hash)
    players_hash.keys.each do |role|
      positions.create(:role => role,
                       :player => Player.new(players_hash[role]))
    end
  end
end

class Position < ActiveRecord::Base
  belongs_to :player
  belongs_to :team
end

class Player < ActiveRecord::Base
  has_many :positions
  has_many :teams, :through => :positions
end

To recap, the players= writer method gets invoked as a result of calling Team.create with the full params hash structure, which includes a nested hash of :players. I must warn you, that your mileage may, as they say, vary with this kind of technique. It’s perfect for the example, with its has_many :through relationship connecting the Team, Position, and Player classes, but it may not be perfect for your domain model. The most important idea is to keep your mind open to the possibility of writing code that is this clean. It’s the Rails way.

I’ve gotten us off on a bit of a tangent—we were talking about form helpers, so let’s cover one more important aspect of them before moving forward.

How Form Helpers Get Their Values

A rather important lesson to learn about Rails form helper methods is that the value they display comes directly from the database prior to “meddling” by the developer. Unless you know what you’re doing, you may get some unexpected results if you try to override the values to be displayed in a form.

Let’s illustrate with a LineItem model, which has a decimal rate attribute (by merits of a rate column in its database table). We’ll override its implicit rate accessor with one of our own:

class LineItem < ActiveRecord::Base
  def rate
    "A RATE"
  end
end

In normal situations, the overridden accessor is hiding access to the real rate attribute, as we can illustrate using the console.

>> li = LineItem.new
=> #<LineItem:0x34b5d18>
>> li.rate
=> "A RATE"

However, suppose you were to compose a form to edit line items using form helpers:

<%- form_for :line_item do |f| -%>
  <%= f.text_field :rate %>
<%- end -%>

You would find that it works normally, as if that overridden rate accessor doesn’t exist. The behavior is intentional, yet confusing enough that it has been reported multiple times as a bug.[2]

The fact is that Rails form helpers use special methods named attribute_before_type_cast (which are covered in Chapter 6, “Working with ActiveRecord”). The preceding example would use the method rate_before_type_cast, and bypass the overriding method we defined.

FormOptionsHelper

The methods in the FormOptionsHelper module are all about helping you to work with HTML select elements, by giving you ways to turn collections of objects into option tags.

Select Helpers

The following methods help you to create select tags based on a pair of object and attribute identifiers.

collection_select(object, attribute, collection, value_method, text_method, options = {}, html_options = {})

Return both select and option tags for the given object and attribute using options_from_collection_for_select (also in this module) to generate the list of option tags from the collection parameter.

country_select(object, attribute, priority_countries = nil, options = {}, html_options = {})

Return select and option tags for the given object and method, using country_options_for_select to generate the list of option tags. Note: The country values inserted by Rails do not include standard 2-character country codes.

The priority_countries argument allows you to specify an array of country names to display at the top of the drop-down selection for the user’s convenience:

<%= form.country_select :billing_country, ["United States"] %>

select(object, attribute, choices, options = {}, html_options = {})

Create a select tag and a series of contained option tags for the provided object_name and attribute. The value of the attribute currently held by the object (if any) will be selected, provided that the object is available (not nil). See options_for_select section for the required format of the choices parameter.

Here’s a small example where the value of @person.person_id is 1:

select("post", "person_id", Person.find(:all).collect {|p|
[ p.name, p.id ] }, { :include_blank => true })

Executing that helper code would generate the following HTML output:

<select name="post[person_id]">
  <option value=""></option>
  <option value="1" selected="selected">David</option>
  <option value="2">Sam</option>
  <option value="3">Tobias</option>
</select>

If necessary, specify :selected => value to explicitly set the selection or :selected => nil to leave all options unselected. The :include_blank => true option inserts a blank option tag at the beginning of the list, so that there is no preselected value.

time_zone_select(object, method, priority_zones = nil, options = {}, html_options = {})

Return select and option tags for the given object and method, using time_zone_options_for_select to generate the list of option tags.

In addition to the :include_blank option documented in the preceding section, this method also supports a :model option, which defaults to TimeZone. This may be used by users to specify a different timezone model object. (See time_zone_options_for_select section for more information.)

Option Helpers

For all of the following methods, only option tags are returned, so you have to invoke them from within a select helper or otherwise wrap them in a select tag.

country_options_for_select(selected = nil, priority_countries = nil)

Returns a string of option tags for pretty much any country in the world. Supply a country name as selected to have it marked as the selected option tag. You can also supply an array of countries as priority_countries, so that they will be listed above the rest of the (long) list.

option_groups_from_collection_for_select(collection, group_method, group_label_method, option_key_method, option_value_method, selected_key = nil)

Returns a string of option tags, like options_from_collection_for_select, but surrounds them with OPTGROUP tags. The collection should return a subarray of items when calling group_method on it. Each group in the collection should return its own name when calling group_label_method. The option_key_method and option_value_method parameters are used to calculate option tag attributes.

It’s probably much easier to show in an example than to explain in words.

>> html_option_groups_from_collection(@continents, "countries",
   "continent_name", "country_id", "country_name",
@selected_country.id)

This example could output the following HTML:

<optgroup label="Africa">
 <select>Egypt</select>
 <select>Rwanda</select>
 ...
</optgroup>
<optgroup label="Asia">
 <select>China</select>
 <select>India</select>
 <select>Japan</select>
 ...
</optgroup>

For the sake of clarity, here are the model classes reflected in the example:

class Continent
  def initialize(p_name, p_countries)
    @continent_name = p_name; @countries = p_countries
  end

  def continent_name
    @continent_name
  end

  def countries
    @countries
  end
end

class Country
  def initialize(id, name)
    @id, @name = id, name
  end

  def country_id
    @id
  end

  def country_name
    @name
  end
end

options_for_select(container, selected = nil)

Accepts a container (hash, array, or anything else enumerable) and returns a string of option tags.

Given a container where the elements respond to first and last (such as a two-element array), the “lasts” serve as option values and the “firsts” as option text. It’s not too hard to put together an expression that constructs a two-element array using the map and collect iterators.

For example, assume you have a collection of businesses to display, and you’re using a select field to allow the user to filter based on the category of the businesses. The category is not a simple string; in this example, it’s a proper model related to the business via a belongs_to association:

class Business < ActiveRecord::Base
  belongs_to :category
end

class Category < ActiveRecord::Base
  has_many :businesses

  def <=>(other)
end

A simplified version of the template code for displaying that collection of businesses might look like this:

<% opts = @businesses.map(&:category).sort.collect {|c| [[c.name],
[c.id]]} %>
<% select_tag(:filter, options_for_select(opts, params[:filter])) %>

The first line puts together the container expected by options_for_select by first aggregating the category attributes of the businesses collection using map and the nifty &:method syntax supported by Rails. The second line generates the select tag using those options (covered later in the chapter). Realistically you want to massage that category list a little more, so that it is ordered correctly and does not contain duplicates:

... @businesses.map(&:category).uniq.sort.collect {...

Particularly with smaller sets of data, it’s perfectly acceptable to do this level of data manipulation in Ruby code. And of course, you probably don’t want to ever shove hundreds or even thousands of rows in a select tag, which means this technique is quite useful. Remember to implement the spaceship method in your model if you need it to be sortable by the sort method.

Also, it’s worthwhile to experiment with eager loading in these cases, so you don’t end up with an individual database query for each of the objects represented in the select tag. In the case of our example, the controller would populate the businesses collection using code like this:

@businesses = Business.find(:conditions => ..., :include => :category)

Hashes are turned into a form acceptable to options_for_select automatically—the keys become “firsts” and values become “lasts.”

If selected parameter is specified (with either a value or array of values for multiple selections), the matching “last” or element will get the selected attribute:

>> options_for_select([["Dollar", "$"], ["Kroner", "DKK"]])
   <option value="$">Dollar</option>
   <option value="DKK">Kroner</option>

>> options_for_select([ "VISA", "MasterCard" ], "MasterCard")
   <option>VISA</option>
   <option selected="selected">MasterCard</option>

>> options_for_select({ "Basic" => "$20", "Plus" => "$40" }, "$40")
   <option value="$20">Basic</option>
   <option value="$40" selected="selected">Plus</option>

>> options_for_select([ "VISA", "MasterCard", "Discover" ],
                      ["VISA", "Discover"])
    <option selected="selected">VISA</option>
    <option>MasterCard</option>
    <option selected="selected">Discover</option>

A lot of people have trouble getting this method to correctly display their selected item—make sure that the value you pass to selected matches the type contained in the object collection of the select; otherwise, it won’t work. In the following example, assuming price is a numeric value, without the to_s, selection would be broken, since the values passed as options are all strings:

>> options_for_select({ "Basic" => "20", "Plus" => "40" }, price.to_s)
   <option value="20">Basic</option>
   <option value="40" selected="selected">Plus</option>

options_from_collection_for_select(collection, value_method, text_method, selected=nil)

Returns a string of option tags that have been compiled by iterating over the collection and assigning the result of a call to the value_method as the option value and the text_method as the option text. If selected is specified, the element returning a match on value_method will get preselected.

time_zone_options_for_select(selected = nil, priority_zones = nil, model = TimeZone)

Returns a string of option tags for pretty much any timezone in the world. Supply a TimeZone name as selected to have it preselected. You can also supply an array of TimeZone objects as priority_zones, so that they will be listed above the rest of the (long) list. TimeZone.us_zones is a convenience method that gives you a list of the U.S. timezones only.

The selected parameter must be either nil, or a string that names a TimeZone (covered in the Appendix A, “ActiveSupport API Reference”).

By default, the model is the TimeZone constant (which can be obtained in ActiveRecord as a value object). The only requirement is that the model parameter be an object that responds to all, returning an array of objects representing timezones.

FormTagHelper

The following helper methods generate HTML form and input tags based on explicit naming and values, contrary to the similar methods present in FormHelper, which require association to an ActiveRecord model instance. All of these helper methods take an options hash, which may contain special options or simply additional attribute values that should be added to the HTML tag being generated.

check_box_tag(name, value = "1", checked = false, options = {})

Creates HTML for a check box input field. Unlike its fancier cousin, check_box in FormHelper, this helper does not give you an extra hidden input field to ensure that a false value is passed even if the check box is unchecked.

>> check_box_tag('remember_me')
=> <input id="remember_me" name="remember_me" type="checkbox"
value="1"/>

>> check_box_tag('remember_me', 1, true)
=> <input checked="checked" id="remember_me" name="remember_me"
   type="checkbox" value="1" />

end_form_tag

Prior to Rails 2.0, the end_form_tag was used to output the HTML string </form> into your template, and was used in conjunction with start_form_tag. Nowadays, we use a block to wrap the content of a form and this method is no longer needed.

file_field_tag(name, options = {})

Creates a file upload field. Remember to set your HTML form to multipart or file uploads will mysteriously not work:

<%= form_tag { :action => "post" }, { :multipart => true } %>
  <label for="file">File to Upload</label>
  <%= file_field_tag :uploaded_data %>
  <%= submit_tag %>
<%= end_form_tag %>

The controller action will receive a File object pointing to the uploaded file as it exists in a tempfile on your system. Processing of an uploaded file is beyond the scope of this book. If you’re smart, you’ll use Rick Olson’s excellent AttachmentFu[3] plugin instead of rolling your own handler code.

form_tag(url_for_options = {}, options = {}, *parameters_for_url, &block)

Starts a FORM tag, with its action attribute set to the URL passed as the url_for_options parameter. It is aliased as start_form_tag.

The :method option defaults to POST. Browsers handle HTTP GET and POST natively; if you specify “put,” “delete,” or any other HTTP verb is used, a hidden input field will be inserted with the name _method and a value corresponding to the method supplied. The Rails request dispatcher understands the _method parameter, which is the basis for the RESTful techniques you learned in Chapter 4.

The :multipart option allows you to specify that you will be including file-upload fields in the form submission and the server should be ready to handle those files accordingly.

>> form_tag('/posts')
=> <form action="/posts" method="post">

>> form_tag('/posts/1', :method => :put)
=> <form action="/posts/1" method="put">

>> form_tag('/upload', :multipart => true)
=> <form action="/upload" method="post" enctype="multipart/form-data">

You might note that all parameters to form_tag are optional. If you leave them off, you’ll get a form that posts back to the URL that it came from—a quick and dirty solution that I use quite often when prototyping or experimenting. To quickly set up a controller action that handles post-backs, just include an if/else condition that checks the request method, something like this:

def add
  if request.post?
    # handle the posted params
    redirect_to :back
  end
end

Notice that if the request is a post, I handle the form params and then redirect back to the original URL (using redirect_to :back). Otherwise, execution simply falls through and would render whatever template is associated with the action.

hidden_field_tag(name, value = nil, options = {})

Creates a hidden field, with parameters similar to text_field_tag.

image_submit_tag(source, options = {})

Displays an image that, when clicked, will submit the form. The interface for this method is the same as its cousin image_tag in the AssetTagHelper module.

Image input tags are popular replacements for standard submit tags, because they make an application look fancier. They are also used to detect the location of the mouse cursor on click—the params hash will include x and y data.

password_field_tag(name = "password", value = nil, options = {})

Creates a password input field. This method is otherwise identical to text_field_tag.

radio_button_tag(name, value, checked = false, options = {})

Creates a radio button input field. Make sure to give all of your radio button options the same name so that the browser will consider them linked.

select_tag(name, option_tags = nil, options = {})

Creates a drop-down selection box, or if the :multiple option is set to true, a multiple-choice selection box. The option_tags parameter is an actual string of option tags to put inside the select tag. You should not have to generate that string explicitly yourself—use the helpers in FormOptions (covered in the previous section of this chapter), which can be used to create common select boxes such as countries, time zones, or associated records.

start_form_tag

Alias for form_tag.

submit_tag(value = "Save changes", options = {})

Creates a submit button with the text value as the caption. The option :disable_with can be used to provide a name for disabled versions of the submit button.

text_area_tag(name, content = nil, options = {})

Creates a multiline text input field (the TEXTAREA tag). The :size option lets you easily specify the dimensions of the text area, instead of having to resort to explicit :rows and :cols options.

>> <%= text_area_tag "body", nil, :size => "25x10" %>
=> <textarea name="body" id="body" cols="25" rows="10"></textarea>

text_field_tag(name, value = nil, options = {})

Creates a standard text input field.

JavaScriptHelper

Provides helper methods to facilitate inclusion of JavaScript code in your templates.

button_to_function(name, function, html_options={}, &block)

Returns a button that will trigger a JavaScript function via the onclick handler. The function argument can be left out, if you provide an update_page block containing RJS-style code. The opts hash takes optional attributes for the button tag.

button_to_function "Greeting", "alert('Hello world!')"

button_to_function "Delete", "if (confirm('Really?')) do_delete()"

button_to_function "Details" do |page|
  page[:details].visual_effect :toggle_slide
end

button_to_function "Details", :class => "details_button" do |page|
  page[:details].visual_effect :toggle_slide
end

define_javascript_functions()

Includes the source code for all of your project’s JavaScript libraries inside a single SCRIPT tag. The function first includes prototype.js and then its core extensions (determined by filenames starting with “prototype”). Afterward, any additional scripts in the public/javascripts will be included in undefined order.

It is much preferable to use the javascript_include_tag helper method of AssetTagHelper to create remote SCRIPT links.

escape_javascript(javascript)

Escapes line breaks, single and double quotes for JavaScript segments.

javascript_tag(content, html_options={})

Outputs a SCRIPT tag with the content inside. The html_options are added as tag attributes.

link_to_function(name, function, html_options={}, &block)

Returns a link that will trigger a JavaScript function using the onclick handler of the link. A return false; statement is added, so that the browser knows to stop processing the link click.

>> link_to_function "Greeting", "alert('Hello world!')"
=> <a onclick="alert('Hello world!'), return false;"
href="#">Greeting</a>

>> link_to_function(image_tag("delete"), "if (confirm('Really?'))
do_delete()")
>> <a onclick="if (confirm('Really?')) do_delete(); return false;"
href="#">
     <img src="/images/delete.png?" alt="Delete"/>
   </a>

Just like button_to_function, you can omit the function parameter and provide JavaScript RJS-style in a code block.

>> link_to_function("Show me more", nil, :id => "more_link") do |page|
     page[:details].visual_effect  :toggle_blind
     page[:more_link].replace_html "Show me less"
   end

>> <a href="#" id="more_link" onclick="try {
        $('details').visualEffect('toggle_blind'),
        $('more_link').update('Show me less'),
      }...

NumberHelper

This module provides assistance in converting numeric data to formatted strings suitable for displaying in your view. Methods are provided for phone numbers, currency, percentage, precision, positional notation, and file size.

human_size(size, precision=1)

Alias for number_to_human_size.

number_to_currency(number, options = {})

Formats a number into a currency string. You can customize the format in the options hash.

  • :precisionSets the level of precision, defaults to 2

  • :unitSets the denomination of the currency, defaults to "$"

  • :separatorSets the separator between the units, defaults to "."

  • :delimiterSets the thousands delimiter, defaults to ","

>> number_to_currency(1234567890.50)
=> $1,234,567,890.50

>> number_to_currency(1234567890.506)
=> $1,234,567,890.51

>> number_to_currency(1234567890.506, :precision => 3)
=> $1,234,567,890.506

>> number_to_currency(1234567890.50, :unit => "&pound;",
=> :separator => ",", :delimiter => ""
=> &pound;1234567890,50

number_to_human_size(size, precision=1)

Formats the bytes in size into a more understandable representation. Useful for reporting file sizes to users. This method returns nil if size cannot be converted into a number. You can change the default precision of 1.

number_to_human_size(123)           => 123 Bytes
number_to_human_size(1234)          => 1.2 KB
number_to_human_size(12345)         => 12.1 KB
number_to_human_size(1234567)       => 1.2 MB
number_to_human_size(1234567890)    => 1.1 GB
number_to_human_size(1234567890123) => 1.1 TB
number_to_human_size(1234567, 2)    => 1.18 MB

This method is also aliased as human_size.

number_to_percentage(number, options = {})

Formats a number as a percentage string. You can customize the format in the options hash.

  • :precisionSets the level of precision, defaults to 3

  • :separatorSets the separator between the units, defaults to "."

number_to_percentage(100)    => 100.000%
number_to_percentage(100, {:precision => 0})   => 100%
number_to_percentage(302.0574, {:precision => 2})   => 302.06%

number_to_phone(number, options = {})

Formats a number as a U.S. phone number. You can customize the format in the options hash.

  • :area_code Adds parentheses around the area code

  • :delimiter Specifies the delimiter to use, defaults to "-"

  • :extension Specifies an extension to add to the end of the generated number

  • :country_code Sets the country code for the phone number

number_to_phone(1235551234)   => 123-555-1234
number_to_phone(1235551234, :area_code => true)   => (123) 555-1234
number_to_phone(1235551234, :delimiter => " ")    => 123 555 1234

number_with_delimiter(number, delimiter=",", separator=".")

Formats a number with grouped thousands using a delimiter. You can customize the format using optional delimiter and separator parameters.

  • delimiterSets the thousands delimiter, defaults to ","

  • separatorSets the separator between the units, defaults to "."

number_with_delimiter(12345678)      => 12,345,678
number_with_delimiter(12345678.05)   => 12,345,678.05
number_with_delimiter(12345678, ".")   => 12.345.678

number_with_precision(number, precision=3)

Formats a number with the specified level of precision. The default level of precision is 3.

number_with_precision(111.2345)    => 111.235
number_with_precision(111.2345, 2) => 111.24

PaginationHelper

The PaginationHelper module was removed from Rails 2. Basically, it sucked and everyone hated it. As long as anyone can remember, the Rails way has been to not use the pagination helper and use something else instead.

Luckily, you don’t have to roll your own pagination because there are a couple of pagination plugins that are worth their weight in gold. We don’t cover them extensively here, but I will at least point you in the right direction.

will_paginate

This plugin,[4] written by the guys behind the popular ERR the blog, is the pagination library of choice for most savvy Rails developers. Install it as a plugin using the following command:

$ script/plugin install svn://errtheblog.com/svn/plugins/will_paginate

In a nutshell, will_paginate works by adding a paginate class method to your ActiveRecord models that takes the place of find. In addition to find’s usual naming conventions, arguments, and options, it takes a :page parameter, for obvious reasons.

A query in the controller might look like this:

@posts = Post.paginate_by_board_id @board.id, :page => params[:page]

View template code is not impacted very much; it just gets fewer records to display. To render the pagination control, you just have to call will_paginate with the collection being rendered:

<%= will_paginate @posts %>

The plugin authors even give you a batch of CSS code so that you can make the pagination control look really pretty, as shown in Figure 11.1.

Pagination control formatted by CSS code

Figure 11.1. Pagination control formatted by CSS code

Users with search-engine optimization (SEO) concerns probably should go with will_paginate because it generates those individually numbered page links. Search robots see them as unique links and will keep clicking through and indexing their content. Conventional SEO wisdom is that search robots click next links only a few times before getting bored and moving on to more interesting sites.

paginator

This project,[5] by notable Rails expert Bruce Williams, is hosted on Rubyforge and might appeal to some because of its simplicity. It’s a Rubygem, not a plugin, so you would type sudo gem install paginator to get your hands on it.

Instead of integrating tightly with ActiveRecord, the way that will_paginate does, the paginator library provides a neat little API to wrap the find invocation in your controller, as follows:

def index
  @pager = ::Paginator.new(Foo.count, PER_PAGE) do |offset, per_page|
    Foo.find(:all, :limit => per_page, :offset => offset)
  end
  @page = @pager.page(params[:page])
  ...
end

The view code, instead of relying on special helper methods, has the @page object at its disposal:

<% @page.items.each do |foo| %>
  <%# Show something for each item %>
<% end %>
<%= @page.number %>
<%= link_to("Prev", foos_url(:page => @page.prev.number)) if @page.prev? %>
<%= link_to("Next", foos_url(:page => @page.next.number)) [email protected]? %>

Paginating Find

If you’re adventurous, check out http://svn.cardboardrocket.com/paginating_find for a simple pagination library that extends ActiveRecord’s find method, instead of trying to replace it. As a project, I think it’s much less mature than will_paginate or paginator, but looks promising.

RecordIdentificationHelper

This module, which wraps the methods of ActionController::RecordIdentifier, encapsulates a number of naming conventions for dealing with records, like ActiveRecords models or ActiveResource models or pretty much any other type of model object that you want to represent in markup code (like HTML) and which has an id attribute. These patterns are then used to try to elevate the view actions to a higher logical level.

For example, assume that you have map.resources :posts defined in your routes file, and code that looks like this in your view:

<% div_for(post) do %>
  <%= post.body %>
<% end %>

The HTML for the DIV element would thus be rendered like this:

<div id="post_45" class="post">
  What a wonderful world!
</div>

Notice the convention reflected in the id attribute. Now, for the controller, which has an AJAX-enabled destroy method. The idea is that it can be called to delete the record and make it disappear from the page without a reload operation:

def destroy
  post = Post.find(params[:id])
  post.destroy

  respond_to do |format|
    format.html { redirect_to :back }
    format.js do
      # Calls: new Effect.fade('post_45'),
      render(:update) { |page| page[post].visual_effect(:fade) }
    end
  end
end

As the preceding example shows, you can stop caring to a large extent what the actual id of the model is (the DIV element holding the model information, that is). You just know that one is being assigned and that the subsequent calls in RJS expect that same naming convention and allow you to write less code if you follow it. You can find more information on this technique in Chapter 12.

dom_class(record_or_class, prefix = nil)

The DOM class convention is to use the singular form of an object or class.

dom_class(post)   # => "post"
dom_class(Person) # => "person"

If you need to address multiple instances of the same class in the same view, you can prefix the dom_class:

dom_class(post, :edit)   # => "edit_post"
dom_class(Person, :edit) # => "edit_person"

dom_id(record, prefix = nil)

The DOM class convention is to use the singular form of an object or class with the id following an underscore. If no id is found, prefix with new_ instead.

dom_class(Post.new(:id => 45)) # => "post_45"
dom_class(Post.new)            # => "new_post"

If you need to address multiple instances of the same class in the same view, you can prefix the dom_id like this: dom_class(Post.new(:id => 45), :edit) results in edit_post_45.

partial_path(record_or_class)

Returns plural/singular for a record or class, which is very useful for automatically rendering partial templates by convention.

partial_path(post)   # => "posts/post"
partial_path(Person) # => "people/person"

RecordTagHelper

This module is closely related to RecordIdentificationHelper in that it assists in creation of HTML markup code that follows good, clean naming conventions.

content_tag_for(tag_name, record, *args, &block)

This helper method creates an HTML element with id and class parameters that relate to the specified ActiveRecord object.

For instance, assuming @person is an instance of a Person class, with an id value of 123 the following template code...

<% content_tag_for(:tr, @person) do %>
  <td><%=h @person.first_name %></td>
  <td><%=h @person.last_name %></td>
<% end %>

will produce the following HTML:

<tr id="person_123" class="person">
  ...
</tr>

If you require the HTML id attribute to have a prefix, you can specify it as a third argument:

>> content_tag_for(:tr, @person, :foo) do ...
=> <tr id="foo_person_123" class="person">...

The content_tag_for helper also accepts a hash of options, which will be converted to additional HTML attributes on the tag. If you specify a :class value, it will be combined with the default class name for your object instead of replacing it (since replacing it would defeat the purpose of the method!).

>> content_tag_for(:tr, @person, :foo, :class => 'highlight') do ...
=> <tr id="foo_person_123" class="person highlight">...

div_for(record, *args, &block)

Produces a wrapper DIV element with id and class parameters that relate to the specified ActiveRecord object. This method is exactly like content_tag_for except that it’s hard-coded to output DIV elements.

TagHelper

This module provides helper methods for generating HTML tags programmatically.

cdata_section(content)

Returns a CDATA section wrapping the given content. CDATA sections are used to escape blocks of text containing characters that would otherwise be recognized as markup. CDATA sections begin with the string <![CDATA[ and end with (and may not contain) the string ]]>.

content_tag(name, content = nil, options = nil, &block)

Returns an HTML block tag of type name surrounding the content. Add HTML attributes by passing an attributes hash as options. Instead of passing the content as an argument, you can also use a block to hold additional markup (and/or additional calls to content_tag) in which case, you pass your options as the second parameter.

Here are some simple examples of using content_tag without a block:

>> content_tag(:p, "Hello world!")
=> <p>Hello world!</p>

>> content_tag(:div, content_tag(:p, "Hello!"), :class => "message")
=> <div class="message"><p>Hello!</p></div>

>> content_tag("select", options, :multiple => true)
=> <select multiple="multiple">...options...</select>

Here it is with content in a block (shown as template code rather than in the console):

<% content_tag :div, :class => "strong" do -%>
  Hello world!
<% end -%>

The preceding code produces the following HTML:

<div class="strong"><p>Hello world!</p></div>

escape_once(html)

Returns an escaped version of HTML without affecting existing escaped entities.

>> escape_once("1 > 2 &amp; 3")
=> "1 &lt; 2 &amp; 3"

>> escape_once("&lt;&lt; Accept & Checkout")
=> "&lt;&lt; Accept &amp; Checkout"

tag(name, options = nil, open = false)

Returns an empty HTML tag of type name, which by default is XHTML compliant. Setting open to true will create an open tag compatible with HTML 4.0 and below. Add HTML attributes by passing an attributes hash to options.

The options hash is used with attributes with no value like (disabled and readonly), which you can give a value of true in the options hash. You can use symbols or strings for the attribute names.

>> tag("br")
=> <br />

>> tag("br", nil, true)
=> <br>

>> tag("input", { :type => 'text', :disabled => true })
=> <input type="text" disabled="disabled" />

>> tag("img", { :src => "open.png" })
=> <img src="open.png" />

TextHelper

The methods in this module provide filtering, formatting, and string transformation capabilities.

auto_link(text, link = :all, href_options = {}, &block)

Turns all URLs and e-mail addresses inside the text string into clickable links. The link parameter is used to optionally limit what should be linked; pass it :email_addresses or :urls. You can add HTML attributes to the generated links using href_options.

If for whatever reason you are unhappy with the way that Rails is turning your e-mail addresses and URLs into links, you can supply a block to this method. Each address found is yielded and the return value of the block is used as the link text.

>> auto_link("Go to http://obiefernandez.com and say hello to
[email protected]")
=> "Go to <a
href="http://www.rubyonrails.org">http://www.rubyonrails.org</a> and
say hello to <a
href="mailto:[email protected]">[email protected]</a>"

>> auto_link("Welcome to my new blog at http://www.myblog.com/.  Please
e-mail me at [email protected].", :all, :target => '_blank') do |text|
    truncate(text, 15)
  end
=> "Welcome to my new blog at <a href="http://www.myblog.com/"
target="_blank">http://www.m...</a>.
        Please e-mail me at <a
href="mailto:[email protected]">[email protected]</a>."

concat(string, binding)

The preferred method of outputting text in your views is to use the <%= expression %> ERB syntax. The regular puts and print methods do not operate as expected in an eRuby code block; that is, if you expected them to output to the browser. If you absolutely must output text within a non-output code block like <% expression %>, you can use the concat method. I’ve found that this method can be especially useful in your own custom helper method implementations.

cycle(first_value, *values)

Creates a Cycle object whose to_s method cycles through elements of the array of values passed to it, every time it is called. This can be used, for example, to alternate classes for table rows.

Here’s an example that alternates CSS classes for even and odd numbers, assuming that the @items variable holds an array with 1 through 4:

<table>
 <% @items.each do |item| %>
   <tr class="<%= cycle("even", "odd") -%>">
    <td>item</td>
   </tr>
 <% end %>
</table>

As you can tell from the example, you don’t have to store the reference to the cycle in a local variable or anything like that; you just call the cycle method repeatedly. That’s convenient, but it means that nested cycles need an identifier. The solution is to pass cycle a :name => cycle_name option as its last parameter. Also, you can manually reset a cycle by calling reset_cycle and passing it the name of the cycle to reset.

For example, here is some data to iterate over:

# Cycle CSS classes for rows, and text colors for values within each
row
@items = [{:first => 'Robert', :middle => 'Daniel', :last => 'James'},
          {:first => 'Emily', :last => 'Hicks'},
          {:first => 'June', :middle => 'Dae', :last => 'Jones'}]

And here is the template code. Since the number of cells rendered varies, we want to make sure to reset the colors cycle before looping:

<% @items.each do |item| %>
<tr class="<%= cycle("even", "odd", :name => "row_class")
  <% item.values.each do |value| %>
    <td style="color:<%= cycle("red", "green", :name => "colors") -%>">
    <%= value %>
    </td>
  <% end %>
  <% reset_cycle("colors") %>
</tr>
<% end %>

excerpt(text, phrase, radius = 100, excerpt_string = "...")

Extracts an excerpt from text that matches the first instance of phrase. The radius expands the excerpt on each side of the first occurrence of phrase by the number of characters defined in radius (which defaults to 100). If the excerpt radius overflows the beginning or end of the text, the excerpt_string will be prepended/appended accordingly. If the phrase isn’t found, nil is returned.

>> excerpt('This is an example', 'an', 5)
=> "...s is an examp..."

>> excerpt('This is an example', 'is', 5)
=> "This is an..."

>> excerpt('This is an example', 'is')
=> "This is an example"

>> excerpt('This next thing is an example', 'ex', 2)
=> "...next t..."

>> excerpt('This is also an example', 'an', 8, '<chop> ')
=> "<chop> is also an example"

highlight(text, phrases, highlighter = '<strong class="highlight">1</strong>')

Highlights one or more phrases everywhere in text by inserting it into a highlighter string. The highlighter can be specialized by passing highlighter as a single-quoted string with 1 where the phrase is to be inserted.

>> highlight('You searched for: rails', 'rails')
=> You searched for: <strong class="highlight">rails</strong>

>> highlight('You searched for: ruby, rails, dhh', 'actionpack')
=> You searched for: ruby, rails, dhh

>> highlight('You searched for: rails', ['for', 'rails'],
'<em>1</em>')
=> You searched <em>for</em>: <em>rails</em>

>> highlight('You searched for: rails', 'rails', "<a
href='search?q=1'>1</a>")
=> You searched for: <a href='search?q=rails>rails</a>

markdown(text)

Returns the text with all the Markdown codes turned into HTML tags. This method is only available if the BlueCloth gem is available.

>> markdown("We are using __Markdown__ now!")
=> "<p>We are using <strong>Markdown</strong> now!</p>"

>> markdown("We like to _write_ `code`, not just _read_ it!")
=> "<p>We like to <em>write</em> <code>code</code>, not just
<em>read</em> it!</p>"

>> markdown("The [Markdown
website](http://daringfireball.net/projects/markdown/) has more
information.")
=> "<p>The <a
href="http://daringfireball.net/projects/markdown/">Markdown
website</a> has more information.</p>"

>> markdown('![The ROR logo](http://rubyonrails.com/images/rails.png
"Ruby on Rails")')
=> '<p><img src="http://rubyonrails.com/images/rails.png" alt="The ROR
logo" title="Ruby on Rails" /></p>'

pluralize(count, singular, plural = nil)

Attempts to pluralize the singular word unless count is 1. If the plural is supplied, it will use that when count is > 1. If the ActiveSupport Inflector is loaded, it will use the Inflector to determine the plural form; otherwise, it will just add an “s” to the singular word.

>> pluralize(1, 'person')
=> "1 person"

>> pluralize(2, 'person')
=> "2 people"

>> pluralize(3, 'person', 'users')
=> "3 users"

>> pluralize(0, 'person')
=> "0 people"

reset_cycle(name = "default")

Resets a cycle (see the cycle method in this module) so that it starts cycling from its first element the next time it is called. Pass in a name to reset a named cycle.

sanitize(html)

Sanitizes the HTML by converting <form> and <script> tags into regular text, and removing all “on*” (e.g., onClick) attributes so that arbitrary JavaScript cannot be executed. It also strips href and src attributes that start with "javascript:". You can modify what gets sanitized by defining VERBOTEN_TAGS and VERBOTEN_ATTRS before this module is loaded.

>> sanitize('<script> do_nasty_stuff() </script>')
=> &lt;script> do_nasty_stuff() &lt;/script>

>> sanitize('<a href="javascript: sucker();">Click here for $100</a>')
=> <a>Click here for $100</a>

>> sanitize('<a href="#" onClick="kill_all_humans();">Click
here!!!</a>')
=> <a href="#">Click here!!!</a>

>> sanitize('<img src="javascript:suckers_run_this();" />')
=> <img />

simple_format(text)

Returns text transformed into HTML using simple formatting rules. Two or more consecutive newlines ( ) are considered to denote a paragraph and thus are wrapped in P tags. One newline ( ) is considered to be a line break and a BR tag is appended. This method does not remove the newlines from the text.

strip_links(text)

Strips all link tags from text leaving just the link text.

>> strip_links('<a href="http://www.rubyonrails.org">Ruby on
Rails</a>')
=> Ruby on Rails

>> strip_links('Please e-mail me at <a
href="mailto:[email protected]">[email protected]</a>.')
=> Please e-mail me at [email protected].

strip_links('Blog: <a href="http://www.myblog.com/" class="nav"
target="_blank">Visit</a>.')
=> Blog: Visit

strip_tags(html)

Strips all HTML tags from the HTML, including comments. This uses the html-scanner tokenizer and so its HTML parsing ability is limited by that of html-scanner.

>> strip_tags("Strip <i>these</i> tags!")
=> Strip these tags!

>> strip_tags("<b>Bold</b> no more!  <a href='more.html'>See more
here</a>...")
=> Bold no more!  See more here...

>> strip_tags("<div id='top-bar'>Welcome to my website!</div>")
=> Welcome to my website!

textilize(text)

This method is only available if the RedCloth gem is available. It returns text with all the Textile codes turned into HTML tags. Learn more about Textile syntax at http://hobix.com/textile/.

>> textilize("*This is Textile!* Rejoice!")
=> "<p><strong>This is Textile!</strong>  Rejoice!</p>"

>> textilize("I _love_ ROR(Ruby on Rails)!")
=> "<p>I <em>love</em> <acronym title="Ruby on
Rails">ROR</acronym>!</p>"

>> textilize("h2. Textile makes markup -easy- simple!")
=> "<h2>Textile makes markup <del>easy</del> simple!</h2>"

>> textilize("Visit Rails website "here":http://www.rubyonrails.org/.)
=> "<p>Visit the Rails website <a
href="http://www.rubyonrails.org/">here</a>.</p>"

textilize_without_paragraph(text)

Returns the text with all the Textile codes turned into HTML tags, but without the bounding <p> tag that RedCloth adds.

truncate(text, length = 30, truncate_string = "...")

If text is longer than length, text will be truncated to the length specified and the last three characters will be replaced with the truncate_string:

>> truncate("Once upon a time in a world far far away", 4)
=> "Once..."

>> truncate("Once upon a time in a world far far away")
=> "Once upon a time in a world f..."

>> truncate("And they found that many people were sleeping better.",
15, "... (continued)")
=> "And they found... (continued)"

word_wrap(text, line_width = 80)

Wraps the text into lines no longer than line_width. This method breaks on the first whitespace character that does not exceed line_width (which is 80 by default).

>> word_wrap('Once upon a time', 4)
=> "Once
upon
a
time"

>> word_wrap('Once upon a time', 8)
=> "Once upon
a time"

>> word_wrap('Once upon a time')
=> "Once upon a time"

>> word_wrap('Once upon a time', 1)
=> "Once
upon
a
time"

UrlHelper

This module provides a set of methods for making links and getting URLs that depend on the routing subsystem, covered extensively in Chapters 3 through 5 of this book.

button_to(name, options = {}, html_options = {})

Generates a form containing a single button that submits to the URL created by the set of options. This is the safest method to ensure that links that cause changes to your data are not triggered by search bots or accelerators. If the HTML button does not work with your layout, you can also consider using the link_to method (also in this module) with the :method modifier.

The options hash accepts the same options as the url_for method (also part of this module).

The generated FORM element has a class name of button-to to allow styling of the form itself and its children. The :method and :confirm options work just like the link_to helper. If no :method modifier is given, it defaults to performing a POST operation. You can also disable the button by passing :disabled => true.

>> button_to "New", :action => "new"
=> "<form method="post" action="/controller/new" class="button-to">
      <div><input value="New" type="submit" /></div>
    </form>"

>> button_to "Delete Image", { :action => "delete", :id => @image.id },
:confirm => "Are you sure?", :method => :delete
=>  "<form method="post" action="/images/delete/1" class="button-to">
       <div>
         <input type="hidden" name="_method" value="delete" />
         <input onclick="return confirm('Are you sure?'),"
value="Delete"
type="submit" />
       </div>
     </form>"

current_page?(options)

Returns true if the current request URI was generated by the given options. For example, let’s assume that we’re currently rendering the /shop/checkout action:

>> current_page?(:action => 'process')
=> false

>>current_page?(:action => 'checkout') # controller is implied
=> true

>> current_page?(:controller => 'shop', :action => 'checkout')
=> true

link_to(name, options = {}, html_options = nil)

One of the fundamental helper methods. Creates a link tag of the given name using a URL created by the set of options. The valid options are covered in the description of this module’s url_for method. It’s also possible to pass a string instead of an options hash to get a link tag that uses the value of the string as the href for the link. If nil is passed as a name, the link itself will become the name.

  • :confirm => 'question?'Adds a JavaScript confirmation prompt with the question specified. If the user accepts, the link is processed normally; otherwise, no action is taken.

  • :popup => trueForces the link to open in a pop-up window. By passing true, a default browser window will be opened with the URL. You can also specify a string of options to be passed to JavaScript’s window.open method.

  • :method => symbolSpecify an alternative HTTP verb for this request (other than GET). This modifier will dynamically create an HTML form and immediately submit the form for processing using the HTTP verb specified (:post, :put, :delete, or other custom string like "HEAD", and so on).

Generally speaking, GET requests should be idempotent, that is, they do not modify the state of any resource on the server, and can be called one or many times without a problem. Requests that modify server-side resources or trigger dangerous actions like deleting a record should not usually be linked to with a normal hyperlink, since search bots and so-called browser accelerators can follow those links while spidering your site, leaving a trail of chaos.

If the user has JavaScript disabled, the request will always fall back to using GET, no matter what :method you have specified. This is accomplished by including a valid href attribute. If you are relying on the POST behavior, your controller code should check for it using the post?, delete?, or put? methods of request.

As usual, the html_options will accept a hash of HTML attributes for the link tag.

>> link_to "Visit Other Site", "http://www.rubyonrails.org/",
:confirm => "Are you sure?"
=> "<a href="http://www.rubyonrails.org/" onclick="return confirm('Are
you sure?'),">Visit Other Site</a>"

>> link_to "Help", { :action => "help" }, :popup => true
=> "<a href="/testing/help/" onclick="window.open(this.href);return
false;">Help</a>"

>> link_to "View Image", { :action => "view" }, :popup =>
['new_window_name', 'height=300,width=600']
=> "<a href="/testing/view/" onclick="window.open(this.href,
'new_window_name','height=300,width=600'),return false;">View
Image</a>"

>> link_to "Delete Image", { :action => "delete", :id => @image.id },
:confirm => "Are you sure?", :method => :delete
=> <a href="/testing/delete/9/" onclick="if (confirm('Are you sure?'))
{
var f = document.createElement('form'),
       f.style.display = 'none'; this.parentNode.appendChild(f);
f.method = 'POST'; f.action = this.href;
       var m = document.createElement('input'), m.setAttribute('type',
'hidden'), m.setAttribute('name', '_method'),
       m.setAttribute('value', 'delete'), f.appendChild(m);f.submit();
};return false;">Delete Image</a>

link_to_if(condition, name, options = {}, html_options = {}, &block)

Creates a link tag using the same options as link_to if the condition is true; otherwise, only the name is output (or block is evaluated for an alternative value, if one is supplied).

link_to_unless(condition, name, options = {}, html_options = {}, &block)

Creates a link tag using the same options as link_to unless the condition is true, in which case only the name is output (or block is evaluated for an alternative value, if one is supplied).

link_to_unless_current(name, options = {}, html_options = {}, &block)

Creates a link tag using the same options as link_to unless the condition is true, in which case only the name is output (or block is evaluated for an alternative value, if one is supplied).

This method is actually pretty useful sometimes. Remember that the block given to link_to_unless_current is evaluated if the current action is the action given. So, if we had a comments page and wanted to render a “Go Back” link instead of a link to the comments page, we could do something like this:

<%= link_to_unless_current("Comment", { :controller => 'comments',
    :action => 'new}) do
      link_to("Go back", { :controller => 'posts', :action => 'index'
})
    end %>

mail_to(email_address, name = nil, html_options = {})

Creates a mailto link tag to the specified email_address, which is also used as the name of the link unless name is specified. Additional HTML attributes for the link can be passed in html_options.

The mail_to helper has several techniques for hindering e-mail harvesters and customizing the e-mail address itself by passing special keys to html_options:

  • :encodeThis key will accept the strings "javascript" or "hex". Passing "javascript" will dynamically create and encode the mailto: link and then eval it into the DOM of the page. This method will not show the link on the page if the user has JavaScript disabled. Passing "hex" will hex-encode the email_address before outputting the mailto: link.

  • :replace_atWhen the link name isn’t provided, the email_address is used for the link label. You can use this option to obfuscate the email_address by substituting the @ sign with the string given as the value.

  • :replace_dotWhen the link name isn’t provided, the email_address is used for the link label. You can use this option to obfuscate the email_address by substituting the “.” in the email with the string given as the value.

  • :subjectThe subject line of the e-mail.

  • :bodyThe body of the e-mail.

  • :ccAdd cc recipients to the e-mail.

  • :bccAdd bcc recipients to the e-mail.

Here are some examples of usages:

>> mail_to "[email protected]"
=> <a href="mailto:[email protected]">[email protected]</a>

>> mail_to "[email protected]", "My email", :encode => "javascript"
=> <script type="text/javascript">eval(unescape('%64%6f%63...%6d%65'))
</script>

>> mail_to "[email protected]", "My email", :encode => "hex"
=> <a href="mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d">My email</a>

>> mail_to "[email protected]", nil, :replace_at => "_at_", :replace_dot =>
"_dot_", :class => "email"
=> <a href="mailto:[email protected]"
class="email">me_at_domain_dot_com</a>

>> mail_to "[email protected]", "My email", :cc => "[email protected]",
:subject => "This is an example email"
=> <a
href="mailto:[email protected][email protected]&subject=This%20i
s%20an%20example%20email">My email</a>

url_for(options = {})

The url_for method returns a URL for the set of options provided and takes the same options as url_for in ActionController (discussed extensively in Chapter 3, “Routing”).

Note that by default, the :only_path option is set to true so that you’ll get the relative /controller/action instead of the fully qualified URL like http://example.com/controller/action.

When called from a view, url_for returns an HTML-escaped URL. If you need an unescaped URL, pass :escape => false in the options.

Here is the complete list of options accepted by url_for:

  • :anchorSpecifies an anchor name (#anchor) be appended to the end of the path.

  • :only_pathSpecifies a relative URL (omitting the protocol, host name, and port).

  • :trailing_slashAdds a trailing slash, as in "/archive/2005/". Note that this is currently not recommended since it breaks caching.

  • :hostOverrides the default (current) host if provided.

  • :protocolOverrides the default (current) protocol if provided.

  • :userInline HTTP authentication (requires :password option).

  • :passwordInline HTTP authentication (requires :user option).

  • :escapeDetermines whether the returned URL will be HTML-escaped or not.

>> url_for(:action => 'index')
=> /blog/

>> url_for(:action => 'find', :controller => 'books')
=> /books/find

>> url_for(:action => 'login', :controller => 'members', :only_path =>
false, :protocol => 'https')
=> https://www.railsapplication.com/members/login/

>> url_for(:action => 'play', :anchor => 'player')
=> /messages/play/#player

>> url_for(:action => 'checkout', :anchor => 'tax&ship')
=> /testing/jump/#tax&amp;ship

>> url_for(:action => 'checkout', :anchor => 'tax&ship', :escape =>
false)
=> /testing/jump/#tax&ship

Relying on Named Routes

If you pass an ActiveRecord or ActiveResource model instance instead of a hash to any method in the UrlModule that takes url_for parameters, you’ll trigger generation of a path for that record’s named route (assuming that one exists). The lookup is based on the name of the class and is smart enough to call new_record? on the passed model to figure out whether to reference a collection or member route.

For example, passing a Timesheet object will attempt to use the timesheet_path route. If that object’s route is nested within another route, you’ll have to use a path helper method explicitly, since Rails won’t be able to figure it out automatically.

>> url_for(Workshop.new)
=> /workshops

>> url_for(@workshop) # existing record
=> /workshops/5

Writing Your Own Helpers

As you develop an application in Rails, you should be on the lookout for opportunities to refactor duplicated view code into your own helper methods. As you think of these helpers, you add them to one of the helper modules defined in the app/helpers folder of your application.

There is an art to effectively writing helper methods, similar in nature to what it takes to write effective APIs. Helper methods are basically a custom, application-level API for your view code. It is difficult to teach API design in a book form. It’s the sort of knowledge that you gain by apprenticing with more experienced programmers and lots of trial and error. Nevertheless, in this section, we’ll review some varied use cases and implementation styles that we hope will inspire you in your own application design.

Small Optimizations: The Title Helper

Here is a simple helper method that has been of use to me on many projects now. It’s called page_title and it combines two simple functions essential to a good HTML document:

  • Setting the title of the page in the document’s head

  • Setting the content of the page’s h1 element

This helper assumes that you want the title and h1 elements of the page to be the same, and has a dependency on your application template. The code for the helper is in Listing 11.6 and would be added to app/helpers/application_helper.rb, since it is applicable to all views.

Example 11.6. The title Helper

def page_title(name)
  @title = name
  content_tag("h1", name)
end

First it sets the value of a variable named @title and then it outputs an h1 element containing the same text. I could have used string interpolation on the second line, such as "<h1>#{name}</h1>", but in my opinion that would be sloppier than using the built-in Rails helper method content_tag.

My application template looks for a @page_title to be available, in which case it will prepend it to the site title, the name of the application:

<html>
  <head>
    <title><%= "#@page_title - " if @page_title %>Site Title</title>

As should be obvious, you call the page_title method in your view template where you want to have an h1 element:

<%= page_title "New User" %>
<%= error_messages_for :user %>
<% form_for(:user, :url => user_path) do |f| %>
  ...

Encapsulating View Logic: The photo_for Helper

Here’s another relatively simple helper. This time, instead of simply outputting data, we are encapsulating some view logic that decides whether to display a user’s profile photo or a placeholder image. It’s logic that you would otherwise have to repeat over and over again throughout your application.

The dependency (or contract) for this particular helper is that the user object being passed in has a profile_photo associated to it, which is an attachment model based on Rick Olson’s excellent attachment_fu Rails plugin.[3] The code in Listing 11.7 should be easy enough to understand without delving into the details of attachment_fu. Since this is a code example, I broke out the logic for setting src into an if/else structure; otherwise, this would be a perfect place to use Ruby’s ternary operator.

Example 11.7. The photo_for Helper, Encapsulating Common View Logic

def photo_for(user, size=:thumb)
  if user.profile_photo
    src = user.profile_photo.public_filename(size)
  else
    src = 'user_placeholder.png'
   end
   link_to(image_tag(src), user_path(user)
end

Smart View: The breadcrumbs Helper

Lots of web applications feature user-interface concepts called breadcrumbs. They are made by creating a list of links, positioned near the top of the page, displaying how far the user has navigated into a hierarchically organized application. I think it makes sense to extract breadcrumb logic into its own helper method instead of leaving it in a layout template.

The trick to our example implementation (shown in Listing 11.8) is to use the presence of instance variables, based on a convention specific to your application, to determine whether or not to add elements to an array of breadcrumb links.

Example 11.8. breadcrumbs Helper Method for a Corporate Directory Application

 1 def breadcrumbs
 2   return if controller.controller_name == 'homepage'

 3   html = [link_to('Home', home_path)]

 4   # first level
 5   html << link_to('Companies', companies_path) if @companies ||
     @company
 6   html << link_to(@company, company_path(@company)) if @company

 7   # second level
 8   html << link_to('Departments', departments_path) if @depts || @dept
 9   html << link_to(@dept, department_path(@dept)) if @dept

10   # third and final level
11   html << link_to('Employees', employees_path) if @employees ||
     @employee
12   html << link_to(@employee.name, employee_path(@employee)) if
     @employee

13   html.join(' &gt; ')
14 end

Here’s the line-by-line explanation of the code, noting where certain application-design assumptions are made:

On line 2, we abort execution if we’re in the context of the application’s homepage controller, since its pages don’t ever need breadcrumbs. A simple return with no value implicitly returns nil, which is fine for our purposes—nothing will be output to the layout template.

On line 3 we are starting to build an array of HTML links, held in the html local variable, which will ultimately hold the contents of our breadcrumb trail. The first link of the breadcrumb trail always points to the home page of the application, which of course will vary, but since it’s always there we use it to initialize the array. In this example, it uses a named route called home_path.

After the html array is initialized, all we have to do is check for the presence of the variables that make up the hierarchy (lines 4 to 12). It is assumed that if a department is being displayed, its parent company will also be in scope. If an employee is being displayed, both its department and company will be in scope as well. This is not just an arbitrary design choice—it is a common pattern in Rails applications that are modeled based on REST principles and using nested resource routes.

Finally, on line 13, the array of HTML links is joined with the > character, to give the entire string the traditional breadcrumb appearance.

Wrapping and Generalizing Partials

I don’t think that partials (by themselves) lead to particularly elegant or concise template code. Whenever there’s a shared partial template that gets used over and over again in my application, I will take the time to wrap it up in a custom helper method that conveys its purpose and formalizes its parameters. If appropriate, I’ll generalize its implementation to make it more of a lightweight, reusable component.

Oh, the heresy! The word component is a dirty word among Rails cognoscenti, and Rails components are so out of favor that I do not cover them in this book and they’ve been removed from Rails 2.0. To be clear, I’m not talking about components in anything other than the sense of an easily reusable piece of user interface.

A tiles Helper

Let’s trace the steps to writing a helper method that wraps what I consider to be a general-purpose partial. Listing 11.9 contains code for a partial for a piece of a user interface that is common to many applications, and generally referred to as a tile. It pairs a small thumbnail photo of something on the left side of the widget, with a linked name and description on the right.

Tiles can also represent other models in your application, such as users and files. As I mentioned, tiles are a very common construct in modern user interfaces and operating systems. So let’s take the cities tiles partial and transform it into something that can be used to display other types of data.

Note

I realize that it’s become passé to use HTML tables and I happen to agree that DIV-based layouts plus CSS are a lot more fun and flexible to work with. However, for the sake of simplicity in this example, and since the UI structure we’re describing is tabular, I’ve decided to structure it using a table.

Example 11.9. A Tiles Partial, Prior to Wrapping and Generalization

 1 <table class="cities tiles">
 2  <% cities.in_groups_of(columns) do |row| -%>
 3   <tr>
 4   <% row.each do |city| -%>
 5    <td id="<%= dom_id(city) %>">
 6     <div class="left">
 7      <%= image_tag city.main_photo.public_filename(:thumb) -%>
 8     </div>
 9     <div class="right">
10       <div class="title"><%= city.name %></div>
11       <div class="description"><%= city.description %></div>
12     </div>
13    </td>
14   <% end # row.each -%>
15   </tr>
16  <% end # in_groups_of -%>
17 </table>

Explanation of the Tiles Partial Code

Since we’re going to transform this city-specific partial into a generalized UI component, I want to make sure that the code we start with makes absolute sense to you first. Before proceeding, I’m going through the implementation line by line and explaining what everything in Listing 11.9 does.

Line 1 opens up the partial with a table element and gives it semantically significant CSS classes so that the table and its contents can be properly styled.

Line 2 leverages a useful Array extension provided by Rails, called in_groups_of. It uses both of our local variables: cities and columns. Both will need to be passed into this partial using the :locals option of the render :partial method. The cities variable will hold the list of cities to be displayed, and columns is an integer number representing how many city tiles each row should contain. A loop iterates over the number of rows that will be displayed in this table.

Line 3 begins a table row using the <tr> element.

Line 4 begins a loop over the tiles for each row to be displayed, yielding a city for each.

Line 5 opens a <td> element and uses the dom_id helper method to autogenerate an identifier for the table cell in the style of city_98, city_99, and so on.

Line 6 opens a <div> element for the left side of the widget, and is demarcated with the appropriate CSS class name needed so that it can be styled properly.

Line 7 calls the image_tag helper to insert a thumbnail photo of the city.

Skipping along, line 10 inserts the content for the title DIV element, in this case, the name and state of the city.

Line 11 directly invokes the description method and finally, the remainder of the lines in the listing simply close out the loops and container elements.

Calling the Tiles Partial Code

In order to use this partial, we have to call render :partial with the two required parameters specified in the :locals hash:

render :partial => "cities/tiles",
       :locals => { :collection => @user.cities, :columns => 3 }

I’m guessing that most experienced Rails developers have written some partial code similar to this and tried to figure out a way to include default values for some of the parameters. In this case, it would be really nice to not have to specify :columns all the time, since in most cases we want there to be three.

The problem is that since the parameters are passed via the :locals hash and become local variables, there isn’t an easy way to insert a default value in the partial itself. If you left off the :columns => n part of your partial call, Rails would bomb with an exception about columns not being a local variable or method. It’s not the same as an instance variable, which defaults to nil and can be used willy-nilly.

Experienced Rubyists probably know that you can use the defined? method to figure out whether a local variable is in scope or not, but the resulting code would be very ugly. The following code might be considered elegant, but it doesn’t work![6]

<% columns = 3 unless defined? columns %>

Instead of teaching you how to jump through annoying Ruby idiom hoops, I’ll show you how to tackle this challenge the Rails way, and that is where we can start discussing the helper wrapping techique.

Write the Helper Method

First, I’ll add a new helper method to the CitiesHelper module of my application, like in Listing 11.10. It’s going to be fairly simple at first. In thinking about the name of the method, it occurs to me that I like the way that tiled(@cities) will read instead of tiles(@cities), so I name it that way.

Example 11.10. The CitiesHelper Tiled Method

module CitiesHelper

  def tiled(cities, columns=3)
    render :partial => "cities/tiles",
           :locals => { :collection => cities, :columns => columns }
  end

end

Right from the start I can take care of that default columns parameter by giving the helper method parameter for columns a default value. That’s just a normal feature of Ruby.

Now instead of specifying the render :partial call in my view template, I can simply write <%= tiled(@cities) %>, which is considerably more elegant and terse. It also serves to decouple the implementation of the tiled city table from the view. If I need to change the way that the tiled table is rendered in the future, I just have to do it in one place: the helper method.

Generalizing Partials

Now that we’ve set the stage, the fun can begin. The first thing we’ll do is to move the helper method to the ApplicationHelper module so that it’s available to all view templates. We’ll also move the partial template file to app/views/shared/_tiled_table.html.erb to denote that it isn’t associated with a particular kind of view, and to more accurately convey its use. As a matter of good code style, I also do a sweep through the implementation and generalize the identifiers appropriately. The reference to cities becomes collection. The block variable item becomes item. Listing 11.11 has the new partial code.

Example 11.11. Tiles Partial Code with Revised Naming

 1 <table class="tiles">
 2  <% collection.in_groups_of(columns) do |row| -%>
 3   <tr>
 4   <% row.each do |item| -%>
 5    <td id="<%= dom_id(item) %>">
 6     <div class="left">
 7      <%= image_tag(item.main_photo.public_filename(:thumb)) %>
 8     </div>
 9     <div class="right">
10       <div class="title"><%= item.name %></div>
11       <div class="description"><%= item.description %></div>
12     </div>
13    </td>
14   <% end # row.each -%>
15   </tr>
16  <% end # in_groups_of -%>
17 </table>

There’s still the matter of a contract between this partial code and the objects that it is rendering. Namely, they must respond to the following messages: main_photo, name, and description. A survey of other models in my application reveals that I need more flexibility. Some things have names, but others have titles. Sometimes I want the description to appear under the name of the object represented, but other times I want to be able to insert additional data about the object plus some links.

Lambda: the Ultimate

Ruby allows you to store references to anonymous methods (also known as procs or lambdas) and call them at will whenever you want.[7] Knowing this capability is there, what becomes possible? For starters, we can use lambdas to pass in blocks of code that will fill in parts of our partial dynamically.

For example, the current code for showing the thumbnail is a big problem. Since the code varies greatly depending on the object being handled, I want to be able to pass in instructions for how to get a thumbnail image without having to resort to big if/else statements or putting view logic in my model classes. Please take a moment to understand the problem I’m describing, and then take a look at how we solve it in Listing 11.12. Hint: The thumbnail, link, title, and description variables hold lambdas!

Example 11.12. Tiles Partial Code Refactored to Use Lambdas

 1     <div class="left">
 2       <%= link_to thumbnail.call(item), link.call(item) %>
 3     </div>
 4     <div class="right">
 5       <div class="title">
 6         <%= link_to title.call(item), link.call(item) %>
 7       </div>
 8       <div class="description"><%= description.call(item) %></div>
 9     </div>

Notice that in Listing 11.12, the contents of the left and right DIVs come from variables containing lambdas. On line 2 we make a call to link_to and both of its arguments are dynamic. A similar construct on line 6 takes care of generating the title link. In both cases, the first lambda should return the output of a call to image_tag and the second should return a URL. In all of these lambda usages, the item currently being rendered is passed to the lambdas as a block variable.

The New Tiled Helper Method

If you now direct your attention to Listing 11.13, you’ll notice that the tiled method is changed considerably. In order to keep my positional argument list down to a manageable size, I’ve switched over to taking a hash of options as the last parameter to the method. This approach is useful and it mimics the way that almost all helper methods take options in Rails.

One of the options, :link, will always be unique to whatever we’re passing in, and cannot simply be guessed, so I make it required by checking for it on line 3. Default values are provided for all optional parameters, and they are all passed along to the partial via the :locals hash given to render :partial.

Example 11.13. The Tiled Collection Helper Method with Lambda Parameters

 1  module ApplicationHelper

 2    def tiled(collection, opts={})
 3      raise 'link option is required' unless opts[:link]

 4      opts[:columns] ||= 3

 5      opts[:thumbnail] ||= lambda do |item|
 6        image_tag(item.photo.public_filename(:thumb))
 7       end

 8      opts[:title] ||= lambda {|item| item.to_s }
 9      opts[:description] ||= lambda {|item| item.description }

10      render :partial => "shared/tiled_table",
11             :locals => { :collection  => collection,
12                          :columns     => opts[:columns] || 3,
13                          :thumbnail   => opts[:thumbnail],
14                          :title       => opts[:title],
15                          :description => opts[:description] }
16    end
17  end

Finally, to wrap up this example, here’s a snippet showing how to invoke our new tiled helper method from a template:

<%= tiled(@cities, :link => lambda {|city| city_path(city)}) %>

The city_path method is available to the lambda block, since it is a closure, meaning that it inherits the execution context in which it is created.

Conclusion

This long chapter served as a thorough reference of helper methods, both those provided by Rails and ideas for ones that you will write yourself. Effective use of helper methods lead to more elegant and maintainable view templates.

Before we fully conclude our coverage of ActionPack, (the name used to refer to ActionController and ActionView together), we’ll jump into the world of Ajax and Javascript. Arguably, one of the main reasons for Rails’s continued popularity is its support for those two crucial technologies of Web 2.0.

References

1.

Josh Susser tells you how to cheat and provide default values to non-column model attributes at http://blog.hasmanythrough.com/2007/1/22/using-faux-accessors-to-initialize-values.

2.

To read up on the “Form field helpers don’t use object accessors saga” check http://dev.rubyonrails.org/ticket/2322.

3.

The Attachment Fu plugin can be found at http://svn.techno-weenie.net/projects/plugins/attachment_fu.

4.

The WillPaginate plugin can be found at http://require.errtheblog.com/plugins/browser/will_paginate, but you knew that already, since all Rails developers subscribe to Err the Blog.

5.

The Paginator project’s homepage is http://paginator.rubyforge.org/.

6.

If you want to know why it doesn’t work, you’ll have to buy the first book in this series: The Ruby Way, Second Edition; ISBN: 0672328844.

7.

If you’re familiar with Ruby already, you might know that Proc.new and its alias proc are also ways to create anonymous blocks of code. I prefer lambda, because of subtle behavior differences. Lambda blocks check the arity of the argument list passed to them when call is invoked, and explicitly calling return in a lambda block works correctly.

 

..................Content has been hidden....................

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