Generating PDFs With Rails

Following this tutorial, I was able to generate PDF’s on development mode. My issue is on Heroku as I’ve tried uploading the repo and but can’t get the PDF generation working.

Is this because Heroku doesn’t allow serving of PDF files, just like images when using Paperclip? BTW, I didn’t upload the exact repo of the tutorial, I just wrote mine from scratch and followed along. Did I perhaps missed some gems?

It’s working locally but the PDF generation on Heroku does not.

@christoomey, I worked on this tutorial and pushed a repo to Heroku. Only the PDF generation part fails but in development mode locally it was fine at all.

Does this mean that Heroku can’t serve the PDF generated files just like other static assets?

Hey @panoysia, Heroku will happily serve the PDF, although you have to make sure you have the needed wkhtmltopdf binary available. There is a section in the video that covers PDF generation on Heroku which should have everything you need. Are you still having issues after following those notes?

The PDF generation in Heroku is working fine now @christoomey, and the issue was that the <%= Rails.application.assets.find_asset(‘invoice_pdf’).to_s %> heroku line of code in the invoice_pdf.html.erb layout file was causing the error.

I think this is because when assets are precompiled, Rails adds a hash to the invoice_pdf.html.erb file which in turn makes the call to** <%= Rails.application.assets.find_asset('invoice_pdf').to_s %> invalid.

Sorry to bring up an old topic, but I thought it would be worth adding this can now be done in Rails 5 without the render_anywhere gem: you can use ApplicationController.renderer (method signature is identical). Just keep in mind that you need to set your asset host correctly in all envs so Rails picks ups on things (I think Suspenders does this out of the box, which is probably why @christoomey did not run into it during this vid). Hope this is useful to somebody!

3 Likes

Error in the docs I think. Step describing ‘inlining’ css with a Rails.application.assets call has the filename as invoice.pdf whereas it should be invoice_pdf since the full filename is invoice_pdf.scss

@pedrosmmoreira How did you get this working without render_anywhere gem? Can you show me a sample, I am using rails 5.1.0 (beta). Reducing a dependency if it’s not needed would be great for me. Thanks.

Hi, let me create a sample repo and I’ll get back to you

I’ve been trying to get this to work by following the tutorial and having to make some modifications that suit my situation which involves 2 tables. I keep getting this error:

 NoMethodError (undefined method `view_paths=' for # 
<ActionView::LookupContext:0x00007f900bcaa2b8>
Did you mean?  view_paths):

My DownloadsController:

class DownloadsController < ApplicationController
 
  
  def show
    respond_to do |format|
      format.pdf { send_audit_pdf }
    end
  end

  private

  def audit
    audit = {
    :record_incoming => params[:record_incoming],
    :record_sent => params[:record_sent]
    }
  end

  def download
    Download.new(audit)
  end

  def send_audit_pdf
    byebug 
    send_file download.to_pdf, download_attributes
  end

  def download_attributes
    {
      filename: download.filename,
      type: "application/pdf",
      disposition: "inline"
    }
  end


end

and my Download model:

require "render_anywhere"

class Download 
  include RenderAnywhere

  
  
  def initialize(audit) 
    @audit = audit
  end
 
  def to_pdf 
    kit = PDFKit.new(as_html, page_size: 'A4')
    kit.to_file("#{Rails.root}/public/audit.pdf")
  end
 
  def filename
    "audit #{audit.id}.pdf"
  end
 
  private
 
    attr_reader :audit
 
    def as_html
      render template: "audits/pdf", layout: "audit_pdf", locals: { audit: audit }
    end
end

So the 2 tables are incoming and sent. The audit object I’m trying to make a pdf from draws from both. So here’s the pdf.html.erb:

<h1>Request</h1>

<div class="flex-grid">
    <div class="items-col">

        <h3>State</h3>
        <h3>Time Modified</h3>
        <h3>License</h3>
        <h3>Account</h3>
        <h3>DPPA Reason</h3>

    </div>

    <div class="items-col">

        <h3><%= @record_incoming[:request_state] %></h3>
        <h3><%= @record_sent[:time_modified] %></h3>
        <h3><%= @record_incoming[:request_license] %></h3>
        <h3><%= @record_incoming[:account] %></h3>
        <h3><%= @record_incoming[:customers_reason] %></h3>

    </div>

</div>