#153 PDFs with Prawn (revised)
Nov 03, 2011 | 11 minutes |
Plugins
Prawn is an excellent Ruby library for generating PDF documents. Here you will learn how to add it to a Rails application through a separate PDF renderer class.
- Download:
- source codeProject Files in Zip (87.2 KB)
- mp4Full Size H.264 Video (25.1 MB)
- m4vSmaller H.264 Video (13.1 MB)
- webmFull Size VP8 Video (15.3 MB)
- ogvFull Size Theora Video (30.2 MB)
Hi Ryan,
as always a very useful screencast! But here the hard question:
How do you test things like this?
capybara-prawn?
just joking :)
Ryan's suggested approach makes testing PDFs a breeze.
Create a new unit spec for the OrderPdf class and focus on the #render() method.
As a simple first step, spec that the render() methods returns a string that starts with "%PDF" to make sure it's generating a PDF.
To improve the specs, I'd check the PDF contains the appropriate text.
maybe this : https://github.com/prawnpdf/pdf-inspector
Hi there, I am still rather new to programming. I at around 4:50 where Ryan says something about you can either have the orderpdf class inherit from prawn::document or something about delegating? I know it may be too long to explain here, but does anyone know of a good place to start looking? I don't know even what keyword to search on google about this..
Thank you!
I'm honestly not too familiar with the concept myself. After I watched the video I had the same curiosity. Found this: http://www.simonecarletti.com/blog/2009/12/inside-ruby-on-rails-delegate/
Hope it helps =]
Ryan: great screencast as always, I've been wanting to see an updated version of this one for a while :D
Oh wow, thanks for the find!
In this case, I think Ryan just suggested you would use a
Prawn::Document
object inside yourOrderPdf
class, instead of inheriting from it. So for example, you would change:into:
(or use the
delegate
method mentionned by syath instead of writing your ownrender
method)In general, prefer composition to inheritance is considered good engineering practice because you control more tightly what your class exposes when you "use" an object rather than inheriting from it, so you have less surprises in the future.
For example, if a new version of Prawn renames the
render
function torender_document
, you can just modify your ownrender
method to use the newrender_document
one, instead of having to track every usage ofrender
in your application. Or if you want to scrap Prawn and use another library, you can probably just modify yourOrderPdf
without rewriting a single line outside of it.That's what we mean when we say that composition offer better encapsulation than inheritance.
Enlightening. Thanks for the post!
Thanks for this awesome post.
Any tips on how to test the content of the pdf?
I've actually forked off prawnto and merged all the fragmented branches into a gem. It's working well with Rails 3.1. I hope to continue development, so don't be shy about feature requests or contributions.
You can find it at https://github.com/forrest/prawnto
Great I'll check it out!
Do you know how can I send a pdf generated with prawn as an attachment in an email? Want to send invoices when a customer buys something.
Would really appreciate any help!!!
Hey everyone,
does anyone got :rowspan and/or :colspan working? I've installed the prawn-layout gem and tried this -> (https://github.com/blaxter/prawn-layout/blob/3a80fa65d7c06774c615d6f64b5d24a4a2af784f/examples/table/table_rowspan.rb) example, but nothing happens.
I really want to use prawn, but i really need colspan and rowspan.
Thanks.
The episode video doesn't work (always "Loading...") -- I've also tried to download the mp4 file but get a "404 Not Found"...
I set up template, but it's only on first page, can you help me?
I'm having an issue getting font color to work. I have the code below in my OrderPdf class I recieve no errors but it never changes the color, any ideas?
This functionality was added after the last gem release 0.12.0, if you want to use the latest release you can use the github version by adding the following in your Gemfile:
In ASCII cast there is a '=' missing between self.row_colors AND ["DDDDDD","FFFFFF"]
BTW
Great Cast!!!
Thanks for reporting that! The ASCIIcast has been corrected.
I'm wondering if anyone has ideas on turning a custom page into a pdf. I have a search page. I have a custom action in my controller that looks like this..
When I do this I get a "Completed 406 Not Acceptable". I've also tried to add a link_to to my view, and I get a different issue there. I've laid that out here. http://stackoverflow.com/questions/9381244/rails-3-passing-date-params-to-url Any help appreciated.
Great cast. It's just what I needed.
However, I've had a surprise issue. I followed the video closely. My development environment functioned flawlessly (MacBook Pro, ruby 1.9.2-p290, rails 3.1.3). When loaded into my production server (Intel motherboard, Ubuntu 11.10, ruby 1.9.2-p290, rails 3.1.3) the call to the pdf class from my controller fails with an "uninitialized constant PatientsController::PatientsPdf" It's as though the internal rails "path" fails to find the file in the /app/pdfs directory. I could load the pdf class definition into my controller, but that's going to be a little messy. Any suggestions?
Rookie error!
I discovered the problem.
I had capitalized the first letter of the _pdf.rb files in the app/pdfs directory. Worked OK on the MAC. Completely confused Ubuntu.
Great cast. This was extremely helpful, as always. Thanks for this.
I have still one question, though: Now after I've created my PDF through Prawn, how would I go about caching the PDF? Has anyone any experience with this?
I did this recently. On first create rendered the pdf to webserver's filesystem (/public/generated_docs or similar). In future check for existence of the generated file and render a link to it rather than a link to generate the pdf.
If you don't have too many pdfs then you could pre-render all of them. Depends on your web app if this is suitable or not.
Great cat as always, very helpful!
Does anyone know how to send a pdf generated with prawn as an attachment? I've search for docs on this and can't find any.
typo: *cast
Found a solution to send a prawn generated pdf as an email attachment. Inside your mailer:
def new_subscription(user, invoice)
@invoice = invoice
pdf = SubscriptionPdf.new(@invoice)
attachments["invoice.pdf"] = { :mime_type => 'application/pdf', :content => pdf.render }
mail(:to => user.email, :subject => 'Subscription Receipt', :from => "example@example.com")
end
This is working for me on Rails 3.2
Thanks for this. Just what i was looking for. Works perfectly.
Thanks. Works perfectly for me as well. To who ever uses this method, don't forget to render the pdf as I hadn't first time round and crashed my browser...
I got Prawn working, but I keep getting this message in my terminal:
Anyone else have this issue?
Yes I have the same issue, although everything is working fine and it does not appear to be affecting anything (to my knowledge). Just an annoying message hopefully...
Same issue here. What's more, removing the register statement from
mime_types.rb
may break your app in production.I know it has been several months, but I get the same msg but doesn't seem to hurt anything in production. I'd just like to stop if from annoying me every time I do a rails s or c. Any progress on the issue?
The pdf mime type is added by default in Rails 3.2: http://edgeguides.rubyonrails.org/3_2_release_notes.html
So you no longer need to tell Rails about the PDF MIME type with the following line:
Mime::Type.register "application/pdf", :pdf
Maybe a strange question but, how would I be able to create for example two pdf files of the same show page?
For example, one pdf file would create an overview and one pdf file would go more into detail, is this possible with prawn?
Many thanks!
I generated a new page and will try to use this as solution. ;)
Such a great episode! Thanks!
I'm trying this line
but I get this error "SyntaxError in xxxController#index"
syntax error, unexpected ',', expecting ')'
I get this error when adding the "view_context"
I'm using rails 3.2.5
disposition: "inline" isn't working in Chrome for me. This appears to be somewhat of a known problem with Chrome, something related to Chrome not knowing the file type and deciding not to render it. It works fine in Firefox. Does anybody know a fix?
Update: removing the Mime configuration line seemed to fix this problem. This is using Rails 3.2.1.
What about utf-8? I cannot see Turkish characters in pdf file :/
prawn already support utf-8,just import your font file.
I'm having trouble moving the code that generates the pdf from the controller to a separate ruby file.
I have the following code in the relevant part of my controller:
I created a separate certificate_pdf.rb file in the folder app/pdfs which contains the following code:
However, when I open the generated pdf the document is blank. Any thougths?
Thanks !
The filename is not getting set using your method. Is there a different way to set the filename?
Prawn is working fine in development but in production, my app is not even opening. When I check production logs I get a looping message
Did you ever find an answer?
Does anyone know how to get a background image working when following this methodology? I tried setting it in the controller and in the PDF class where the margins get set. The only thing I can get to work is adding an image the full size of the page, but if I try to repeat that using Prawn's repeat method, the image covers up all the content on the pages. I can't add the image manually one page at a time because the length of the content determines how many pages there are.
Did you ever find an answer?
Great article. I've been using this for a while and due to the number of PDFs that I create would like to create one or more 'partials' or similar to share standard methods (company address, header info etc.). Has anyone been able to do this. There are some queries that allude to this on Stack overflow, bu they are all quite old and don't use the pdfs folder
Prawn had support for 'templates' removed in recent versions. The only solution I know of is to put shared content into helper modules, then mix those modules into each class that you need them in.
I wrote a short example of how to do this here
Just did a little write-up which goes over how to add a repeating footer to your PDFs using Prawn - http://kyleke.es/posts/2013/11/creating-a-repeating-footer-w-prawn/
Does anyone have an example they could post that lists all of the projects, like in index.html.erb, instead of just 1 project (like the tutorial using #show).
Thank You.
Looking for a way to add to my Table a remote image from s3 to my prawn pdf.
I'm using this to insert an S3 image into a table cell:
Then just call
image_cell
in your table data array:[ [ image_cell(url), ... ], [ ... ] ]
.Hi otagi I get this error OpenURI::HTTPError 403 Forbidden
Thank you works!! now
hi folks, I am getting an: "uninitialized constant QuoteController::Prawn" error.
at the following line (with the code in the relevant controller):
anybody have any ideas? It's giving me grief!
This episode has been updated to Rails 5 as a blog post PDFs with Prawn in Rails 5
I want to add before_filter :authenticate_user! but it throws an error.Can you tell you me how i can do this?
Good Post