How do you delay a rendering job?
This method works OK, but if I add delayed_job's handle_asychronously, I get can't convert nil into String
:
def onixtwo
s = render_to_string(:template=>"isbns/onix.xml.builder")
send_data(s, :type=>"text/xml",:filename => "onix2.1.xml")
end
handle_asynchronously :onixtwo
So re开发者_开发技巧ndering with delayed job is clearly having a problem with params being passed. I've tried putting this job in a rake task but render_to_string
is a controller action - and I'm using a current_user
variable which needs to be referenced in the controller or view only. So... what's the best way to delay a rendering job?
/////////update////////
Given that I'm currently pair-programming with a toddler, I don't have the free hands to investigate additional class methods as wisely recommended in the comments - so as a quick and dirty I tried this:
def onixtwo
system " s = render_to_string(:template=>'isbns/onix.xml.builder') ; send_data(s, :type=>'text/xml',:filename => 'onix2.1.xml') & "
redirect_to isbns_path, :target => "_blank", :flash => { :success => "ONIX message being generated in the background." }
end
Why doesn't it work? No error message just no file produced - which is the case when I remove system ... &
For what it's worth, this is what I did, bypassing render_to_stream
entirely. This is in /lib or app/classes (adding config.autoload_paths += %W(#{config.root}/classes
into config/application.rb):
#classes/bookreport.rb
# -*- encoding : utf-8 -*-
require 'delayed_job'
require 'delayed/tasks'
class Bookreport
# This method takes args from the book report controller. First it sets the current period. Then it sorts out which report wants calling. Then it sends on the arguments to the correct class.
def initialize(method_name, client, user, books)
current_period = Period.where(["currentperiod = ? and client_id = ?", true, client]).first
get_class = method_name.capitalize.constantize.new
get_class.send(method_name.to_sym, client, user, books.to_a, current_period.enddate)
end
end
#app/classes/onixtwo.rb
require 'builder'
class Onixtwo
def onixtwo(client_id, user_id, books, enddate)
report_name = "#{Client.find_by_id(client_id).client_name}-#{Time.now}-onix-21"
filename = "#{Rails.root}/public/#{report_name}.xml"
current_company = Company.where(:client_id => client_id).first
File.open(filename, "w") do |file|
xml = ::Builder::XmlMarkup.new(:target => file, :indent => 2)
xml.instruct!(:xml, :version => "1.0", :encoding => "utf-8")
xml.declare! :DOCTYPE, :ONIXMessage, :SYSTEM, "http://www.editeur.org/onix/2.1/03/reference/onix-international.dtd"
xml.ONIXMessage do
xml.Header do
#masses of Builder code goes here...
end
end #of file
xmlfile = File.open(filename, "r")
onx = Onixarchive.new(:client_id => client_id, :user_id => user_id)
onx.xml = xmlfile
onx.save!
end #of method
handle_asynchronously :onixtwo
end #of class
Called from the view like this:
= link_to("Export to ONIX 2.1", params.merge({:controller=>"bookreports" , :action=>:new, :method_name => "onixtwo"}))
Via a controller like this:
class Books::BookreportsController < ApplicationController
#uses Ransack for search, hence the @q variable
def new
@q = Book.search(params[:q])
@books = @q.result.order('pub_date DESC')
method_name = params[:method_name]
Bookreport.new(method_name, @client, @user, @books)
redirect_to books_path, :flash => {:success => t("#{method_name.to_sym}").html_safe}
end
end
精彩评论