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:
1 2 3 4 5 |
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:
1 2 3 4 5 |
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:
1 2 3 |
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.