Representación parcial / vista en una tarea de rake / trabajo de fondo / modelo en Rails 4

He leído mucho sobre la representación de parciales y vistas de Rails en tareas de rake / trabajos / modelos de fondo. La gran mayoría de las cosas que he encontrado en Stackoverflow y en la web describen los enfoques que funcionan en Rails 3, pero parecen estar desactualizados y no los puse a trabajar (incluso con bastante tiempo de experimentación).

Entonces, ¿cómo puedo hacer un trabajo parcial en segundo plano en Rails 4?

Aquí está el mejor enfoque que he trabajado hasta ahora (demostrado en la consola).

c = ApplicationController.new result = c.render_to_string(partial: 'tweets/tweet', locals: {tweet: Tweet.first}) # => # Tweet Load (0.8ms) SELECT "tweets".* FROM "tweets" ORDER BY "tweets"."id" ASC LIMIT 1 # Author Load (0.6ms) SELECT "authors".* FROM "authors" WHERE "authors"."id" = $1 ORDER BY "authors"."id" ASC LIMIT 1 [["id", 1]] # Status Load (0.6ms) SELECT "statuses".* FROM "statuses" WHERE "statuses"."twitter_id" = 367523226848866304 LIMIT 1 # Rendered tweets/_tweet_body.html.slim (17.5ms) # Rendered tweets/_resolved_tweet.html.slim (23.7ms) # Rendered tweets/_tweet.html.slim (28.1ms) # ActionView::Template::Error: undefined method `tweet_path' for #<#:0x007fb21cb009e8> # from /Users/thomasklemm/.rbenv/versions/2.0.0-p195/lib/ruby/gems/2.0.0/gems/actionpack-4.0.0/lib/action_dispatch/routing/polymorphic_routes.rb:129:in `polymorphic_url' 

¿Algunas ideas? ¡Gracias por adelantado!

Actualización : el tweet_path mencionado anteriormente no está definido. Este error se debió a la vinculación a una ruta = link_to 'Tweet', [@project, tweet] (plantillas delgadas) usando una variable de instancia que estaría presente en las vistas que heredan de un controlador determinado, pero no cuando se representan fuera de este contexto. Resolví esto pasando por la asociación apropiada en su lugar = link_to 'Tweet', [tweet.project, tweet] .

Esto es lo que he recostackdo de muchas fonts y lo que me funciona en Rails 4.

Con esta clase de Renderizador, debería poder representar vistas y parciales de Rails 4 en cualquier contexto, como trabajos en segundo plano, objetos de servicio, modelos, trabajadores, lo que sea.

 # 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 

Actualización :

Parece que hay una solución más fácil: 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. 

Actualización 2 :

Hay una gem llamada render_anywhere que permite llamar "render" desde cualquier lugar: modelos, trabajos en segundo plano, tareas de rake, etc.

Actualización 3 :

En Rails 5 , el renderizador se ha extraído y se puede utilizar de forma independiente a partir de trabajos en segundo plano y otros lugares:

 ApplicationController.renderer.render( partial: 'messages/message', locals: { message: message } ) 

Para Rails <= 4.2, esta funcionalidad se puede realizar con la gema backport_new_renderer .

Asegúrese de que está cargando el entorno de Rails en el trabajo. Si eso ya está hecho, puedes probar algo como:

 include Rails.application.routes.url_helpers