237

While I realize you are supposed to use a helper inside a view, I need a helper in my controller as I'm building a JSON object to return.

It goes a little like this:

def xxxxx

   @comments = Array.new

   @c_comments.each do |comment|
   @comments << {
     :id => comment.id,
     :content => html_format(comment.content)
   }
   end

   render :json => @comments
end

How can I access my html_format helper?

Aaron Brager
  • 65,323
  • 19
  • 161
  • 287
AnApprentice
  • 108,152
  • 195
  • 629
  • 1,012

10 Answers10

352

You can use

  • helpers.<helper> in Rails 5+ (or ActionController::Base.helpers.<helper>)
  • view_context.<helper> (Rails 4 & 3) (WARNING: this instantiates a new view instance per call)
  • @template.<helper> (Rails 2)
  • include helper in a singleton class and then singleton.helper
  • include the helper in the controller (WARNING: will make all helper methods into controller actions)
Paweł Gościcki
  • 9,066
  • 5
  • 70
  • 81
grosser
  • 14,707
  • 7
  • 57
  • 61
  • 59
    This answer is even better! In rails 3, simply calling `view_context.helper_function` is simple and works great. `ActionController::Base.helpers.helper_function` is equally good. – trisweb Oct 19 '12 at 20:51
  • 4
    Thank you for introducing me to view_context! Just what's needed here, shame yours isn't the accepted answer! – mistertim May 27 '13 at 11:02
  • 1
    I like the accepted answer, if the module is limited to items that are needed in that controller. Functions being included in the controller are not a problem as long as your routes are not set up to match everything, ie, no catch all routes. view_context adds more typing, if you need it a lot. Depends on the situation. – DGM Aug 27 '13 at 20:25
  • Just to add to everyone else's pleasure - `view_context` :+1: – Alex Villa May 15 '15 at 16:25
  • 7
    WARNING: Don't use `view_context`. It'll instantiate a new view instance per call... – fny Jun 28 '15 at 13:16
  • 7
    `ActionController::Base.helpers.helper_function` doesn't seem to work. I get `NoMethodError - undefined method spell_date_and_time' for #:` when trying to call `ActionController::Base.helpers.spell_date_and_time()` in a controller method. calling `view_context.spell_date_and_time()` does work however. – Catfish Jan 16 '16 at 17:01
  • 44
    rails 5: simply use `helpers.helper_function` in your controller (https://github.com/rails/rails/pull/24866) – Markus Jun 27 '16 at 13:55
  • 1
    The comment about using `helpers.helper_function` is the only one that worked for me (Rails 5). – rgin Jan 09 '18 at 11:31
  • @fny Can you please elaborate. Creating a new view instance per call, does that mean our view layer is computed twice? – Qasim Apr 18 '23 at 10:26
225

Note: This was written and accepted back in the Rails 2 days; nowadays grosser's answer is the way to go.

Option 1: Probably the simplest way is to include your helper module in your controller:

class MyController < ApplicationController
  include MyHelper
    
  def xxxx
    @comments = []
    Comment.find_each do |comment|
      @comments << {:id => comment.id, :html => html_format(comment.content)}
    end
  end
end

Option 2: Or you can declare the helper method as a class function, and use it like so:

MyHelper.html_format(comment.content)

If you want to be able to use it as both an instance function and a class function, you can declare both versions in your helper:

module MyHelper
  def self.html_format(str)
    process(str)
  end
    
  def html_format(str)
    MyHelper.html_format(str)
  end
end
starball
  • 20,030
  • 7
  • 43
  • 238
Xavier Holt
  • 14,471
  • 4
  • 43
  • 56
  • Thanks but I'm a little confused. Right now my helper is in /app/helpers/application_helper.rb ... ANd you're suggesting I should move the helper to ApplicationController? – AnApprentice Feb 26 '11 at 23:17
  • I added 'include ApplicationHelper' to my application_controller but that errors with 'NoMethodError (undefined method `html_format' for ApplicationHelper:Module):' – AnApprentice Feb 26 '11 at 23:19
  • 1
    @AnApprentice Looks like you've figured it out, but I tweaked my answer a little, hopefully making things clearer. In the first version, you can just use `html_format` - you only need `MyHelper.html_format` in the second. – Xavier Holt Feb 26 '11 at 23:28
  • 4
    This does not work when the helper method you want to use make use of view methods such as `link_to`. Controllers don't have access to these methods and most of my helpers use these methods. Also, including the helper into the controller exposes all the helper's methods as publicly accessible actions which is not good. `view_context` is the way to go in Rails 3. – GregT Sep 12 '13 at 03:48
  • @GregT - Hadn't seen grosser's answer before, as it came in a bit after the fact, but I like it better too. He just got my upvote. – Xavier Holt Sep 12 '13 at 09:28
  • @GregT Thanks for your comment. I had similar issues and view_context is just the magic I needed! – anbiniyar Feb 19 '14 at 06:03
  • Good stuff. Though in Ruby, you don't need to use the `return` keyword, since the last line is the returned value. – Unixmonkey Feb 10 '15 at 03:25
84

In Rails 5 use the helpers.helper_function in your controller.

Example:

def update
  # ...
  redirect_to root_url, notice: "Updated #{helpers.pluralize(count, 'record')}"
end

Source: From a comment by @Markus on a different answer. I felt his answer deserved it's own answer since it's the cleanest and easier solution.

Reference: https://github.com/rails/rails/pull/24866

Fellow Stranger
  • 32,129
  • 35
  • 168
  • 232
Gerry Shaw
  • 9,178
  • 5
  • 41
  • 45
10

My problem resolved with Option 1. Probably the simplest way is to include your helper module in your controller:

class ApplicationController < ActionController::Base
  include ApplicationHelper

...
miguelbgouveia
  • 2,963
  • 6
  • 29
  • 48
  • 1
    Only downside that it adds controller actions with the name of the helper functions. But tbh, I do that, too :) – Felix Apr 18 '19 at 14:23
9

In general, if the helper is to be used in (just) controllers, I prefer to declare it as an instance method of class ApplicationController.

Franco
  • 669
  • 2
  • 8
  • 23
8

Before Rails 5, you have to include the helper module.

In newer versions, you can use helpers in your controller with the helpers (plural) object.

  class UsersController
    def index
      helpers.my_helper_method_name(even_pass_arg_here)
    end
  end

https://www.rubyguides.com/2020/01/rails-helpers/

aldrien.h
  • 3,437
  • 2
  • 30
  • 52
4

In Rails 5+ you can simply use the function as demonstrated below with simple example:

module ApplicationHelper
  # format datetime in the format #2018-12-01 12:12 PM
  def datetime_format(datetime = nil)
    if datetime
      datetime.strftime('%Y-%m-%d %H:%M %p')
    else
      'NA'
    end
  end
end

class ExamplesController < ApplicationController
  def index
    current_datetime = helpers.datetime_format DateTime.now
    raise current_datetime.inspect
  end
end

OUTPUT

"2018-12-10 01:01 AM"
Ravistm
  • 2,163
  • 25
  • 25
3

In rails 6, simply add this to your controller:

class UsersController < ApplicationController
  include UsersHelper
  
  # Your actions

end

Now the user_helpers.rb will be available in the controller.

stevec
  • 41,291
  • 27
  • 223
  • 311
  • 1
    This works in mailers too, unlike calling via `helpers` (see https://stackoverflow.com/questions/4937208/access-helpers-from-mailer). – Andrew Smith Jan 22 '22 at 10:14
2

One alternative missing from other answers is that you can go the other way around: define your method in your Controller, and then use helper_method to make it also available on views as, you know, a helper method.

For instance:


class ApplicationController < ActionController::Base

private

  def something_count
    # All other controllers that inherit from ApplicationController will be able to call `something_count`
  end
  # All views will be able to call `something_count` as well
  helper_method :something_count 

end
sandre89
  • 5,218
  • 2
  • 43
  • 64
0
class MyController < ApplicationController
    # include your helper
    include MyHelper
    # or Rails helper
    include ActionView::Helpers::NumberHelper

    def my_action
      price = number_to_currency(10000)
    end
end

In Rails 5+ simply use helpers (helpers.number_to_currency(10000))

albertm
  • 61
  • 3