Search code examples
ruby-on-railswkhtmltopdfwicked-pdfrails-activejob

WickedPDF generated with ActiveJob is creating a margin - how to fix?


I want to generate a PDF with ActiveJob, and then save it as an attachment to a record.

When I generate the PDF from a controller action, it looks fine:

enter image description here

When I move it to a background job, it is creating this margin around the pdf.

enter image description here

What is going on, and how can I remove the margin to make the contents cover the entire page?

CODE

Controller method that works as expected:

  def renderCatalogOnServer
      //declaring variables here -- removing to condense question
      respond_to do |format|
      format.html
      format.pdf do
        render pdf: "renderCatalogOnServer",
               layout: "pdf",
               page_size: "Letter",
               margin: { :top => 0, :bottom => 0, :left => 0 , :right => 0}
      end
    end
  end

Active Job method that is adding a margin around each page:

class CreatePdfJob < ApplicationJob
  queue_as :default

  def perform(catalog_id)
    //declaring variables here -- removing to condense question

    generatedPdf  = WickedPdf.new.pdf_from_string(
      ApplicationController.render(
        template: 'catalog/renderCatalogOnServer',
        layout: 'layouts/pdf',
        page_size: "Letter",
        margin: { :top => 0, :bottom => 0, :left => 0 , :right => 0},
        locals: { catalog: @catalog, business_units: @business_units, brands: @brands },
      )
    )

    overlay = Tempfile.new('overlay')
    overlay.binmode
    overlay.write(generatedPdf)
    overlay.close
    pdfPath = overlay.path # to get path

    catalog_record.pdf.attach(io: URI.open(pdfPath), filename: "#{@catalog.name}.pdf")
  end
end

I'm guessing it's in the way I'm having to call ApplicationController.render, or create a tempfile before saving. I'm looking for how to remove the margin from the PDF, but also welcome any feedback on a better way to produce the PDF with ActiveJob and WickedPDF. The way it's working now seems like overkill, but it's the only way I've found that actually generates a PDF (although with incorrect margins).

Thanks!


Solution

  • Right now you are passing the PDF options to ApplicationController#render which is essentially just ignoring them (disposing of them) because that method does not know what those options are intended to do.

    Instead you need to pass the PDF options to WickedPdf#pdf_from_string so that they can control how the PDF itself is generated.

    To do this simply change:

     generatedPdf  = WickedPdf.new.pdf_from_string(
          ApplicationController.render(
            template: 'catalog/renderCatalogOnServer',
            layout: 'layouts/pdf',
            page_size: "Letter",
            margin: { :top => 0, :bottom => 0, :left => 0 , :right => 0},
            locals: { catalog: @catalog, business_units: @business_units, brands: @brands },
          )
        )
    

    To:

     generatedPdf  = WickedPdf.new.pdf_from_string(
          ApplicationController.render(
            template: 'catalog/renderCatalogOnServer',
            layout: 'layouts/pdf',
            locals: { catalog: @catalog, business_units: @business_units, brands: @brands}
          ),  
          page_size: "Letter",
          margin: { :top => 0, :bottom => 0, :left => 0 , :right => 0}
        )