Alpha Hydrae

Coding on the edge of the web...

Rails 3: Rendering Views Outside a Controller

I discovered recently that Rails 3’s action views really don’t like it when you try to render them outside a controller. This was a problem, as I wanted to render a view in a Resque background task for caching.

You have to jump through a few hoops to make it work. The trick is to create a subclass of ActionView::Base and mix in a few things it’s missing:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
module Renderer

  # Renders a view.
  def self.render options = {}

    # Pass a hash of local variables as :assigns.
    assigns = options.delete(:assigns) || {}

    # Create a view.
    view = view_class.new ActionController::Base.view_paths, assigns

    # Mix in other helpers you need.
    view.extend ApplicationHelper
    view.extend CustomHelper

    # Render.
    view.render options
  end

  # Creates a subclass of ActionView::Base with route helpers mixed in.
  def self.view_class
    @view_class ||= Class.new ActionView::Base do
      include Rails.application.routes.url_helpers
    end
  end
end

You can then use it from wherever:

1
Renderer.render template: 'users/show', assigns: { user: @logged_user }

That’s it. Not quite clean but at least it’s short.

Meta

Comments