I\'ve read a lot on rendering Rails partials and views in rake tasks / background jobs / models. The vast majority of things I have found on Stackoverflow and the web describe
Make sure you're loading the rails environment in the job. If that is already done you can try something like:
include Rails.application.routes.url_helpers
Here's what I compiled from lots of sources and what works for me in Rails 4.
With this Renderer class, you should be able to render Rails 4 views and partials in any context, like background jobs, service objects, models, workers, you name it.
# app/services/renderer.rb
# Render views and partials in rake tasks,
# background workers, service objects and more
#
# Use:
#
# class MyService
# def render_stuff
# result = renderer.render(partial: 'tweets/tweet', locals: {tweet: Tweet.first})
# # or even
# result = renderer.render(Tweet.first)
# end
#
# private
#
# def renderer
# @renderer ||= Renderer.new.renderer
# end
# end
#
class Renderer
def renderer
controller = ApplicationController.new
controller.request = ActionDispatch::TestRequest.new
ViewRenderer.new(Rails.root.join('app', 'views'), {}, controller)
end
end
# app/services/view_renderer.rb
# A helper class for Renderer
class ViewRenderer < ActionView::Base
include Rails.application.routes.url_helpers
include ApplicationHelper
def default_url_options
{host: Rails.application.routes.default_url_options[:host]}
end
end
Update:
There seems to be an easier solution: http://makandracards.com/makandra/17751-render-a-view-from-a-model-in-rails
ApplicationController.new.render_to_string(
:template => 'users/index',
:locals => { :@users => @users }
)
# Mind the weird syntax to set @ variables in :locals.
Update 2:
There's a gem called render_anywhere that allows for calling "render" from anywhere: models, background jobs, rake tasks, etc.
Update 3:
In Rails 5, the renderer has been extracted and can be used standalone from background jobs and other places:
ApplicationController.renderer.render(
partial: 'messages/message',
locals: { message: message }
)
For Rails <= 4.2, this functionality can be backported with the backport_new_renderer gem.