Using helpers in a controller: with_helpers

Although there is supposed to be a clear separation between views and controllers, often when it comes to helper functions, there is a small bit of overlap and there are situations where it’d be nice to simply use a few helpers from inside an action.

ActionController::Base.class_eval do
  def with_helpers(&block)
    template = ActionView::Base.new([],{},self)
    template.extend self.class.master_helper_module
    add_variables_to_assigns
    template.assigns = @assigns
    template.send(:assign_variables_from_controller)
    forget_variables_added_to_assigns
    template.instance_eval(&block)
  end
end

Here is what it looks like in a controller. Although this is a non-sensical example, it shows off how you can use a helper (i.e. link_to) in an action. It also shows how the instance variables (i.e. @person) set in the action are available in the with_helpers block… the same way that instance variables are available in views.

class MyController < ApplicationController
  def my_action
    @person = Person.find(params[:id])
    render :text => with_helpers { link_to(@person.full_name, person_path(@person)) }
  end
end

2 Comments

  1. Hey – looks neat.

    I do this to achieve something similar. (think i first came across it here – http://www.johnyerhot.com/2008/01/10/rails-using-helpers-in-you-controller/)

    class Helper
    include Singleton
    include ActionView::Helpers::UrlHelper
    end

    class ApplicationController < ActionController::Base
    def helpers
    Helper.instance
    end
    end

    class MyController < ApplicationController
    def my_action
    @person = Person.find(params[:id])
    render :text => helpers.link_to(@person.full_name, person_path(@person))
    end
    end

  2. Dan Manges says:

    For this particular example, you could use render with :inline.

    render :inline => "<%= link_to(@person.full_name, person_path(@person)) %>"