public
Last active

Draft of view+template+helper PDFs with Prawn, including simple spec and manual verification specs triggered by Guard.

  • Download Gist
Gemfile
Ruby
1 2 3 4 5 6 7 8 9
source 'http://rubygems.org'
 
# …
 
gem 'prawn'
 
group :test do
gem 'pdf-inspector', :require => "pdf/inspector"
end
Guardfile
Ruby
1 2 3 4 5 6
# …
 
watch('app/documents/base_document.rb') { |m| "spec/documents" }
watch(%r{app/views/documents/(.+)\.pdf\.rb}) { |m| "spec/documents/#{m[1]}_spec.rb" }
 
# …
app-documents-base_document.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
require "prawn/measurement_extensions"
 
class BaseDocument
 
delegate :render, :render_file,
to: :renderer
 
def initialize(data)
@data = data
end
 
private
 
def renderer
@renderer ||= PrawnTemplateRenderer.new(template, @data, self.class.helper_procs)
end
 
def template
self.class.name.underscore
end
 
# Any time we do "helpers do; stuff; end" in this class or subclasses,
# store that proc to be evaluated in the template context.
 
class_attribute :helper_procs
self.helper_procs ||= []
 
def self.helpers(&block)
self.helper_procs << block
end
 
end
 
 
class BaseDocument::PrawnTemplateRenderer
 
delegate :render, :render_file,
to: :doc
 
module PageSizes
A4 = "A4"
MY_SPECIAL_PAGE_SIZE = [ 123.mm, 456.mm ]
end
 
def initialize(template, data={}, helper_procs=[])
@template = template
@data = data
@helper_procs = helper_procs
 
# Evaluate the template within this instance, i.e. so that
# it calls our `meta` and `content` methods.
instance_eval(read_template, template_path)
end
 
def meta
extend PageSizes
@prawn_document_options = yield
end
 
def content(&block)
# Define any helpers on the Prawn document by evaluating them
# in its instance.
@helper_procs.each do |proc|
doc.instance_eval(&proc)
end
 
# Evaluate the contents of the data block in the Prawn document
# instance, yielding the data hash to that block.
doc.instance_exec(data_object, &block)
end
 
private
 
def doc
@doc ||= Prawn::Document.new(@prawn_document_options || {})
end
 
def data_object
OpenStruct.new(@data)
end
 
def read_template
File.read(File.join(app_root, template_path))
end
 
def template_path
"app/views/documents/#{@template}.pdf.rb"
end
 
def app_root
Rails.root
end
 
end
app-documents-my_document.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
class MyDocument < BaseDocument
 
def initialize(user)
super(
name: user.name,
copies: 1
)
end
 
helpers do
 
def copies(count)
count.times do |i|
yield
start_new_page unless i == count-1
end
end
 
end
 
end
app-views-documents-my_document.pdf.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14
meta do
{
page_size: MY_SPECIAL_PAGE_SIZE,
margin: 12.mm
}
end
 
content do |data|
 
copies(data.copies) do
text "Hello #{data.name}!"
end
 
end
spec-documents-my_document_spec.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
# encoding: utf-8
require "spec_helper"
 
describe MyDocument do
let(:document) { MyDocument.new(user) }
let(:pdf) { document.render }
let(:text) { PDF::Inspector::Text.analyze(pdf).strings.join(" ") }
 
context "with name" do
let(:user) { User.new(name: "Svelle") }
 
it "generates" do
text.should include("Hello Svelle!")
end
 
# To trigger these during dev:
# VIEW_PDF=true guard
it "previews", :manual_verification do
preview :name
end
end
 
context "with long name" do
let(:user) { User.new(name: "Svelle Forever") }
 
it "previews", :manual_verification do
preview :long_name
end
end
 
def preview(name)
file_name = "/tmp/my_document_#{name}.pdf"
document.render_file(file_name)
system("open", file_name) # OS X
end
end
spec-spec_helper.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12
RSpec.configure do |config|
config.treat_symbols_as_metadata_keys_with_true_values = true
 
# These are only for manual verification in dev and should never trigger from CI, specjour, rake spec etc.
# Do: VIEW_PDF=true guard
if ENV['VIEW_PDF']
puts "PDFs may open at any time!!1"
else
config.filter_run_excluding :manual_verification
end
 
end

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.