Prawnto
=======
a rails plugin providing templating abilities
for generating pdf files leveraging the new kick-ass prawn library
full documentation/demos at: http://cracklabs.com/prawnto
Copyright (c) 2008 cracklabs.com, released under the MIT license
Forked prawnto
==============
Ever wanted to use layouts for PDF's ? Here it is!
Note that it is targeted to Rails 2.3.x, a Rails 3.x branch may be created in the future.
The first change was to remove prawn_xxx template handler, it contained too much specific magic.
If you had some template for it, read on and convert your templates.
Usage
=====
Without layout
--------------
Your templates are either .prawn or .prawn_dsl at the moment, and you don't have to change anything to make them
work with this new plugin. This is because you are not using layouts.
With layout
-----------
Simply define a layout in views/layouts with some code and at least one yield statement:
# invoices.pdf.prawn_dsl
header_height = 2.5.cm
footer_height = 1.cm
repeat :all do
mask :fill_color, :line_width, :stroke_color do
fill_color "000000"
stroke_color '000000'
line_width(1)
# header
bounding_box [bounds.left, bounds.top], :width => bounds.width, :height => header_height-3.mm-5.mm do
image "#{Rails.root}/public/images/logo.jpg", :fit => [5.cm, 1.6.cm], :at => [bounds.left,bounds.top]
text @title.to_s, :align => :center, :size => 20 if @title
# action template may put some additional header stuff
yield :header
stroke_horizontal_line bounds.left,bounds.right, :at => bounds.bottom - 3.mm
end
# footer
stroke_horizontal_line bounds.left,bounds.right, :at => bounds.bottom + footer_height - 5.mm
end
end
bounding_box [bounds.left, bounds.top - header_height], :width => bounds.width, :height => bounds.height-(header_height+footer_height) do
# action rendering comes here!
yield
end
# put page numbers now that all pages are generated
page_count.times do |i|
go_to_page(i+1)
mask :fill_color, :line_width, :stroke_color do
fill_color "000000"
stroke_color '000000'
line_width(1)
caption = "#{i+1} / #{page_count}"
draw_text caption, :size => 12, :at => [bounds.left + (bounds.width - width_of(caption)) / 2, bounds.bottom]
end
end
Then in an action template
# show.prawn.dsl
# This code is run before the layout so you may setup some variables that will be used in the layout
@title = "Invoice of #{@invoice.date}"
# This is required to postpone the action "rendering" within the layout
content_for do |pdf|
# put some text
pdf.text @invoice.title
# do like .prawn_dsl
view = self
pdf.instance_eval do
# you can call direct pdf methods here
text "Waoow"
# access view instance variable like this (which comes from the controller @invoice)
text view[:invoice].customer.name
# render a partial (ask the view to do it)
view.render :partial => 'link', :object => 'A link'
end
# render a partial
render :partial => 'link', :collection => @links
end
For the sake of completeness, here is the partial
# _links.pdf.prawn_dsl
text link
You may use #content_for and corresponding yield anywhere you want. It follows the same behaviour
than in ERB like templates.
Internals
=========
The way layout works in Rails is targeted for text template generation. With prawn we use code template
generation, I mean each layout doesn't produce any output (like in ERB) it is simply run at a specific
time with a specific object (pdf). The output is generated by calling pdf.render just before sending it
as the request response (not on your template, backed in the plugin).
So, the action template is run FIRST, then the layout template. This is exactly the opposite way for
code template as the layout should run first (setup page, put some header or footer, etc...).
This is the reason for this call to content_for in the action template when using a layout (see doc above).
This is also the reason for the patch to #content_for and Template class.
Copyright (c) 2011 Pascal Hurni, released under the MIT license