Lojic Technologies

Using helpers inside controllers in Ruby on Rails

with 5 comments

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.

Written by Brian Adkins

July 27, 2007 at 7:20 pm

Posted in programming

Tagged with , ,

5 Responses

Subscribe to comments with RSS.

  1. Thanks, helped me out. First time I heard of lambda, too. Yes, i am that much of a rookie in ruby world. πŸ™‚

    Attila

    April 21, 2008 at 6:47 am

  2. Thanks for this. I am using it with my app. However, I can’t help but feel this is some how the wrong way to things. There has to be a reason why helpers are not accessible in controllers right???

    vinhboy

    January 7, 2009 at 2:13 am

  3. @vinhboy why would you want an arbitrary function available to a view but not a controller ?

    Brian Adkins

    January 19, 2009 at 10:33 pm

  4. The simple method in your last update solved my problem. Thank you. -Chris

    Chris Cera

    May 27, 2009 at 10:32 am

  5. include the helper module in application controller

    e.g.
    class ApplicationController < ActionController::Base
    protect_from_forgery
    include SessionsHelper
    end

    kumar deepak

    September 30, 2010 at 10:05 am


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: