ruby - Rendering partials / view in a rake task / background job / model in Rails 4 -
i've read lot on rendering rails partials , views in rake tasks / background jobs / models. vast majority of things have found on stackoverflow , web describe approaches working in rails 3, seem outdated , didn't them work (even quite time spent experimenting).
so, how can render partial in background job in rails 4?
here's best approach i've worked out far (demonstrated in console).
c = applicationcontroller.new result = c.render_to_string(partial: 'tweets/tweet', locals: {tweet: tweet.first}) # => # tweet load (0.8ms) select "tweets".* "tweets" order "tweets"."id" asc limit 1 # author load (0.6ms) select "authors".* "authors" "authors"."id" = $1 order "authors"."id" asc limit 1 [["id", 1]] # status load (0.6ms) select "statuses".* "statuses" "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' #<#<class:0x007fb21bf797a0>:0x007fb21cb009e8> # /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'
any ideas? in advance!
update: tweet_path
mentioned above indeed not defined. error resulted linking path = link_to 'tweet', [@project, tweet]
(slim templates) using instance variable present in views inheriting controller, not when rendered outside of context. solved going through appropriate association instead = link_to 'tweet', [tweet.project, tweet]
.
here's compiled lots of sources , works me in rails 4.
with renderer class, should able render rails 4 views , partials in context, background jobs, service objects, models, workers, name it.
# app/services/renderer.rb # render views , partials in rake tasks, # background workers, service objects , more # # use: # # class myservice # def render_stuff # result = renderer.render(partial: 'tweets/tweet', locals: {tweet: tweet.first}) # # or # 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 # helper class 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 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 weird syntax set @ variables in :locals.
update 2:
there's gem called render_anywhere
allows calling "render" anywhere: models, background jobs, rake tasks, etc.
update 3:
in rails 5, renderer has been extracted , can used standalone background jobs , other places:
applicationcontroller.renderer.render( partial: 'messages/message', locals: { message: message } )
for rails <= 4.2, functionality can backported backport_new_renderer gem.
Comments
Post a Comment