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)
UPDATE: it’s not necessary to use the lambda (as cool as they
are), simply storing the result of
Object.new.extend(ActionView::Helpers::NumberHelper) is
sufficient. For example:
x = Object.new.extend(ActionView::Helpers::NumberHelper)
x.number_to_currency(7.4)
# results in "$7.40"
END UPDATE
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.