Easy PDFs from Rails

Seth Banks at Subimage has made it easy to generate PDFs directly from Rails. Seth uses Prince XML to generate the PDF with some custom Ruby handlers that he wrote. It seems easy, but more importantly, it seems flexible.
I gave it a quick test drive with great results, but I had to make a few modifications that Seth doesn’t make clear. If you want to try it, read his original post, then follow these steps.
- 1. Download Prince XML and unzip it if necessary.
- 2. Open a command-line window, navigate to the Prince XML folder, and type sudo ./install.sh. I installed it in the default location “/usr/local/”.
- 3. Download Seth’s files: prince.rb and pdf_helper.rb
- 4. prince.rb should require no changes, put it in your Rails application’s “lib” folder.
- 5. Consider pdf_helper.rb to be a “usage example”; parts of it are specific to Seth’s setup and will need to be customized for your needs. You can either put the file in your Rails application’s “lib” folder or use the same code directly in your controller. For real world usage, you will probably want to completely rewrite his two examples for your needs but to get up and running quickly simply change a few key parts as detailed in the next step.
- 6. Open up pdf_helper.rb. Where it calls prince.add_style_sheets() change those style sheets to be a list of your stylesheets.
- 7. Also in pdf_helper.rb: Where it calls render_to_string() change the :layout to be your layout name.
- 8. Call the helper in your controller. Here’s an example of how I did it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | class ReportsController < ApplicationController def sales_report # code removed... # the idea is that this action would normally render # a sales report to the browser end # to allow use of the modified version of Seth's helper include PdfHelper def sales_report_pdf # you'll still need to prepare the report sales_report # call a method in Seth's helper # pass it the path to the view template and the PDF name make_and_send_pdf('/reports/sales_report', 'sales_report.pdf') end end |
- 9. Try it! You may need to make CSS changes to get pretty output, but you should get a PDF.
Thanks, Seth!
It would be cool if someone made this into a plug-in and the PdfHelper could be made more universal and called using render_pdf() or render_prince_pdf(). It would be extra-super-cool if it actually extended ActiveRecord’s render method, something like:
1 2 3 | render(:pdf => 'sales_report', :file => 'reports/sales_report', :layout => 'reports') |
Let me know if anyone does!

August 5th, 2007 at 7:16 am
I keep getting this error:
——————
You have a nil object when you didn’t expect it.
The error occurred while evaluating nil.chomp
——————
I’m on winxp btw.
Any ideas on what the problem could be?
August 5th, 2007 at 9:15 am
It’s difficult to say because I didn’t write Prince or the Prince helper.
But here’s my advice: Check your customizations and make sure you are generating the report (and are getting some data) before outputing the PDF. If that doesn’t work, search inside pdf_helper.rb and prince.rb for ‘chomp’. That may give you a clue as to what variable is nil when it shouldn’t be.
August 6th, 2007 at 4:03 pm
Thanks Kevin.
I got it to work…finally.
I edited the prince.rb file as follows:
- @exe_path = “C:\\Program Files\\Prince\\Engine\\bin\\prince” .chomp
- uncommented the logger method because it gave me errors. (had this same error on osx as well)
- plus I added the following line in the pdf_from_string method; pdf.binmode
so now it’s:
pdf = IO.popen(path, “w+”)
pdf.binmode
…etc…
August 10th, 2007 at 5:19 pm
THANK YOU!
August 11th, 2007 at 11:05 pm
am getting garbled text when using utf8
am working on ubuntu 7.04
is that related to prince.rb , specifically line 66 when passing the html string: pdf.puts(string)
??
also i found out that it adds ’script/../config/../public’ to each image src attribute…. and so it misses the paths of all images. what to do?
August 12th, 2007 at 9:49 am
ok i think i could manage the image src issue , he handles that in pdf_helper.rb line 27
so once omitting or commenting it things goes on.
still the issue of utf8, any solution?
August 12th, 2007 at 10:40 am
@ khelll
Have you tried the Princexml forum?
http://www.princexml.com/bb/viewtopic.php?t=227&highlight=utf
August 13th, 2007 at 5:25 am
ok after the test, i turned out that prince is considering it the input string as latin1 or ISO_8859-1, so my question is : is there an option to tell prince abt the encoding.
i need to let prince consider the received code as UTF-8….
thanks for help
August 29th, 2007 at 7:16 am
thanks for your clear advices…
I am trying to get it running into my project now..
you wrote.. in the sales_report action
this action would normally render
# a sales report to the browser
do I need to render it in the action ? into a views/reports/sales_report.rhtml … with a layout/reports.rhtml layout ?
how should I handle the views with a layout ? is that correct ?
that’s what the following lines seems to indicate , no need for template extension /reports/sales_report.rhtml
make_and_send_pdf(’/reports/sales_report’, ’sales_report.pdf’)
when doing that .. I get an error
Missing template …./config/../app/views/documents/sales_report_pdf.rhtml
thanks again for your advices
December 6th, 2007 at 10:09 am
Khelll => in , in <meta http-equiv… “charset=UTF-8″ instead of “charset=iso-8859-1″ in your document layout.
I’ve got probs with gsub(src) too.
If i comment the line, got nil exception
If i transform the pattern with /src=”\//, nil exception too.
I really don’t understand, especially for the first case, if someone has an idea.
thanks
May 6th, 2008 at 8:58 am
hi there,
how can i pass ‘/reports/sales_report?id=12345′ instead of /reports/sales_report? i wanted to display some dynamic contents in pdf. thanks!
August 28th, 2008 at 7:44 am
I cant get the images displayed into my application. I have also removed the line pdf_helper.rb line 27
. but still not getting the images displayed…
November 27th, 2008 at 11:25 am
2 Robert write before sales_report params[:id] = 12345 and then make_and_send_pdf(’/reports/sales_report’, “123.pdf”)
December 17th, 2008 at 7:10 am
I used pricely pluging. Prince is installed in /usr/local/lib but still i am getting this error
sh: Usage:: command not found
prince: warning: failed to load external entity “[OPTIONS]”
prince: [OPTIONS]: error: could not load input file
prince: warning: failed to load external entity “file.xml”
prince: file.xml: error: could not load input file
prince: warning: failed to load external entity “Convert”
prince: Convert: error: could not load input file
prince: warning: failed to load external entity “file.xml”
prince: file.xml: error: could not load input file
prince: warning: failed to load external entity “to”
prince: to: error: could not load input file
prince: error: no input documents to process
prince: warning: failed to load external entity “[OPTIONS]”
prince: [OPTIONS]: error: could not load input file
prince: warning: failed to load external entity “doc.html”
prince: doc.html: error: could not load input file
prince: warning: failed to load external entity “Convert”
prince: Convert: error: could not load input file
prince: warning: failed to load external entity “doc.html”
prince: doc.html: error: could not load input file
prince: warning: failed to load external entity “to”
prince: to: error: could not load input file
prince: warning: failed to load external entity “out.pdf”
prince: out.pdf: error: could not load input file
prince: error: no input documents to process
prince: warning: failed to load external entity “[OPTIONS]”
prince: [OPTIONS]: error: could not load input file
prince: warning: failed to load external entity “FILES…”
prince: FILES…: error: could not load input file
prince: warning: failed to load external entity “Combine”
prince: Combine: error: could not load input file
prince: warning: failed to load external entity “multiple”
prince: multiple: error: could not load input file
prince: warning: failed to load external entity “files”
prince: files: error: could not load input file
prince: warning: failed to load external entity “to”
prince: to: error: could not load input file
prince: warning: failed to load external entity “out.pdf”
prince: out.pdf: error: could not load input file
prince: error: no input documents to process
sh: line 5: Try: command not found
sh: line 6: –input=html: command not found
Can you tell me how to solve this?
September 1st, 2009 at 7:09 pm
Can’t make it work..
Im using it within a show method like this
_______________________________________
include PdfHelper
def show
@user = User.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @user }
make_and_send_pdf(’/users/show’,'leo.pdf’)
end
end
_______________________________________
And I’ve got te following error
ArgumentError in UsersController#show
wrong number of arguments (2 for 1)
_______________________________________
Any ideas?
December 20th, 2009 at 9:35 am
hm, also having problem with utf-8 processing..
i have in layout of pdf prince ..
December 20th, 2009 at 9:58 am
ok, sorry
my mistake
:layout => “prince_pdf” instead of “prince-pdf”
^_^