在Rails3中,我使用WickedPDF gem来渲染我的一个模型的PDF格式.这工作正常:/ invoices / 123返回
HTML,/invoices/123.pdf下载PDF.
在我的发票模型中,我使用state_machine宝石跟踪发票状态.当发票从“未结算”到“已结算”状态时,我想获取发票PDF的副本,并使用CarrierWave将其附加到发票模型.
我有三个部分分开工作:控制器创建一个PDF视图,模型跟踪状态,并在进行正确的转换时触发回调,并且CarrierWave设置正确.但是,我有一个时间让他们一起玩得很好.
如果我只想抓住发票的HTML版本,我可以从模型中调用render_to_string.但是render_to_string似乎在接收PDF二进制文件时窒息.如果我可以得到一个数据流,那么很容易将该数据写入临时文件并将其附加到上传者,但是我不知道如何获取数据流.
有什么想法吗?代码如下:
发票控制器
def show @invoice = @agg_class.find(params[:id]) respond_to do |format| format.pdf do render_pdf end format.html # show.html.erb format.json { render json: @aggregation } end end
…
def render_pdf(options = {}) options[:pdf] = pdf_filename options[:layout] = 'pdf.html' options[:page_size] = 'Letter' options[:wkhtmltopdf] = '/usr/local/bin/wkhtmltopdf' options[:margin] = { :top => '0.5in',:bottom => '1in',:left => '0in',:right => '0in' } options[:footer] = { :html => { :template => 'aggregations/footer.pdf.haml',:layout => false,} } options[:header] = { :html => { :template => 'aggregations/header.pdf.haml',} } render options end
Invoice.rb
def create_pdf_copy # This does not work. pdf_file = ApplicationController.new.render_to_string( :action => 'aggregations/show',:format => :pdf,:locals => { :invoice => self } ) # This part works fine if the above works. unless pdf_file.blank? self.uploads.clear self.uploads.create(:fileinfo => File.new(pdf_file),:job_id => self.job.id) end end
UPDATE找到一个解决方案.
def create_pdf_copy wicked = WickedPdf.new # Make a PDF in memory pdf_file = wicked.pdf_from_string( ActionController::Base.new().render_to_string( :template => 'aggregations/show.pdf.haml',:layout => 'layouts/pdf.html.haml',:locals => { :aggregation => self } ),:pdf => "#{self.type}-#{self}",:layout => 'pdf.html',:page_size => 'Letter',:wkhtmltopdf => '/usr/local/bin/wkhtmltopdf',:margin => { :top => '0.5in',:right => '0in' },:footer => { :content => ActionController::Base.new().render_to_string({ :template => 'aggregations/footer.pdf.haml',:layout => false }) },:header => { :content => ActionController::Base.new().render_to_string({ :template => 'aggregations/header.pdf.haml',:layout => false }) } ) # Write it to tempfile tempfile = Tempfile.new(['invoice','.pdf'],Rails.root.join('tmp')) tempfile.binmode tempfile.write pdf_file tempfile.close # Attach that tempfile to the invoice unless pdf_file.blank? self.uploads.clear self.uploads.create(:fileinfo => File.open(tempfile.path),:job_id => self.job.id) tempfile.unlink end end
解决方法
解:
def create_pdf_copy wicked = WickedPdf.new # Make a PDF in memory pdf_file = wicked.pdf_from_string( ActionController::Base.new().render_to_string( :template => 'aggregations/show.pdf.haml',:job_id => self.job.id) tempfile.unlink end end