0

I am using WickedPDF in a Rails 6 project to generate PDFs from HTML, and then combine them with prefilled PDF forms. The WickedPDF generated PDFs are split into two sections, each of which must be combined with a form. The forms must appear at the beginning of their respective sections.

I have attempted to generate two PDFs with WickedPDF and then combine them with the prefilled forms using combine_pdf in the appropriate order.

The render_ar_docs and render_gl_docs both work as expected when I visit their routes individually: they generate and save the expected PDF. However, when I call them sequentially in the print_complete_docs action, the resulting PDFs are a single blank page.

How can I generate multiple PDFs from a single action?

Thank you for your help.

def print_complete_docs
    @policy.fill_and_save_acord28
    @policy.fill_and_save_acord25
    render_ar_docs
    render_gl_docs
    pdf = CombinePDF.new
    pdf << CombinePDF.load("tmp/acord28.pdf")
    pdf << CombinePDF.load("tmp/ar_docs.pdf")
    pdf << CombinePDF.load("tmp/acord25.pdf")
    pdf << CombinePDF.load("tmp/gl_docs.pdf")
    pdf.save "tmp/complete_docs.pdf"
    send_file("#{Rails.root}/tmp/complete_docs.pdf", filename: "tmp/#{@policy.legal_vesting} Complete Docs.pdf", type: 'application/pdf')
  end

  def render_ar_docs
    render pdf: 'ar_docs', 
           layout: 'document',
           save_to_file: Rails.root.join('tmp', "ar_docs.pdf"),
           save_only: true
  end
  
  def render_gl_docs
    render pdf: 'gl_docs', 
           layout: 'document',
           save_to_file: Rails.root.join('tmp', "gl_docs.pdf"),
           save_only: true
  end
Unixmonkey
  • 18,485
  • 7
  • 55
  • 78
  • Are both tempfiles written and openable? Sounds to me like CombinePDF isn't combining, or maybe not properly loading? Does `CombinePDF.load(Rails.root.join('tmp/acord28.pdf').to_s)` make a difference? – Unixmonkey Feb 10 '21 at 18:57
  • CombinePDF seems to be working as expected. If I render only a single pdf, and that template's name matches the print_complete_docs, the pdf generates as expected and CombinePDF concatenates the files as expected. The tempfiles are written, but are single blank pages. If I generate the files individually, and use CombinePDF to concatenate them, I get the expected behavior. – Bobby Meyer Feb 10 '21 at 19:07

1 Answers1

0

My issue seems to be related to trying to render multiple times in a single request, which Rails does not allow. Instead I should have used WickedPDF's pdf_from_string method.

My new (over verbose and un-refactored, but functional) method looks like this:

def print_complete_docs
    @policy.fill_and_save_acord28
    @policy.fill_and_save_acord25
    render_ar_docs
    render_gl_docs
    
    pdf = CombinePDF.new
    pdf << CombinePDF.load("tmp/acord28.pdf")
    pdf << CombinePDF.load("tmp/ar_docs.pdf")
    pdf << CombinePDF.load("tmp/acord25.pdf")
    pdf << CombinePDF.load("tmp/gl_docs.pdf")
    pdf.save "tmp/complete_docs.pdf"
    send_file("#{Rails.root}/tmp/complete_docs.pdf", filename: "tmp/#{@policy.legal_vesting} Complete Docs.pdf", type: 'application/pdf')
  end
  
  def render_ar_docs
    ar_docs = WickedPdf.new.pdf_from_string(
      render_to_string(
        'policies/ar_docs.html.erb',
        layout:'document.html.erb',
        locals: { policy: @policy }
      ),
      layout: 'document.html.erb'
    )
    save_path = Rails.root.join('tmp','ar_docs.pdf')
    File.open(save_path, 'wb') do |file|
      file << ar_docs
    end
  end

  def render_gl_docs
    gl_docs = WickedPdf.new.pdf_from_string(
      render_to_string(
        'policies/gl_docs.html.erb',
        layout:'document.html.erb',
        locals: { policy: @policy }
      ),
      layout: 'document.html.erb'
    )
    save_path = Rails.root.join('tmp','gl_docs.pdf')
    File.open(save_path, 'wb') do |file|
      file << gl_docs
    end
  end
  

PS: Thanks to @Unixmonkey for trying to help, and for his contributions to WickedPDF!

  • Ah, the old DoubleRenderError. Sorry I didn't think of that. I do think that the dependence of specific filenames in `tmp` makes this prone to issues with multiple requests. I would suggest either creating `Tempfile` objects, or using something like `CombinePDF.parse(ar_docs)` to take in the raw string returned from `pdf_from_string` if you can. – Unixmonkey Feb 10 '21 at 22:59
  • Thank you, I am reading up on Tempfile now. – Bobby Meyer Feb 12 '21 at 03:12