Monday, September 3, 2007

Helpers

Using helpers inside controllers in Ruby on Rails

Rails provides some nice helper functions (numbers, dates, etc.) that are available to views, but they’re not automatically available to controllers. I found a number of ways to accomplish this on the web, but I wasn’t satisfied with any of them.

The motivation for me to do this was to use the number_to_currency() helper function in a controller, so I’ll use that for the example. This helper is in the ActionView::Helpers::NumberHelper module, which on my Ubuntu 7.04 system is located here:

/usr/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/
action_view/helpers/number_helper.rb

It may be located elsewhere on your system. If you’re running *nix (or OSX), then typing the following command should locate it:

locate number_helper.rb

If you edit number_helper.rb, you’ll notice that NumberHelper is a module and number_to_currency() is an instance method, so we’ll need an instance that has included NumberHelper to be able to call the number_to_currency() method.

One way to do this would be to create a new class that includes the module, and then create an instance of that class:

class MyNumberHelper
include ActionView::Helpers::NumberHelper
end
my_helper = MyNumberHelper.new
formatted_str = my_helper.number_to_currency(n)

If we had an existing object, called obj, another way to accomplish this would be via:

obj.extend(ActionView::Helpers::NumberHelper)

Since I didn’t have an appropriate object to extend the NumberHelper module, I simply created a new one:

Object.new.extend(ActionView::Helpers::NumberHelper)

If I only need to call the helper once, I could accomplish that via:

Object.new.extend(
ActionView::Helpers::NumberHelper).number_to_currency(n)

However, I preferred to create a Proc object and store it for future use:

format_currency = lambda { |n|
Object.new.extend(
ActionView::Helpers::NumberHelper).number_to_currency(n) }

format_currency.call(n)

I deliberately wanted to avoid simply including ActionView::Helpers::NumberHelper in the controller to avoid polluting the namespace and possibly expose additional public methods in the controller.

No comments:

analytics