Skip to content

Instantly share code, notes, and snippets.

@calebhaye
Created October 24, 2012 17:23
Show Gist options
  • Select an option

  • Save calebhaye/3947475 to your computer and use it in GitHub Desktop.

Select an option

Save calebhaye/3947475 to your computer and use it in GitHub Desktop.
Generating PDFs with wicked_pdf
module PdfHelper
require 'wicked_pdf'
def self.included(base)
base.class_eval do
alias_method_chain :render, :wicked_pdf
end
end
def render_with_wicked_pdf(options = nil, *args, &block)
if options.is_a?(Hash) && options.has_key?(:pdf)
logger.info '*'*15 + 'WICKED' + '*'*15
make_and_send_pdf(options.delete(:pdf), (WICKED_PDF.blank? ? {} : WICKED_PDF).merge(options))
else
render_without_wicked_pdf(options, *args, &block)
end
end
def parse_options opts
"#{parse_header_footer(:header => opts.delete(:header), :footer => opts.delete(:footer), :layout => opts[:layout])} " + \
"#{parse_toc(opts.delete(:toc))} #{parse_outline(opts.delete(:outline))} #{parse_margins(opts.delete(:margin))} #{parse_others(opts)} "
end
private
def make_pdf(options = {})
html_string = render_to_string(:template => options[:template], :layout => options[:layout])
w = WickedPdf.new(options[:wkhtmltopdf])
w.pdf_from_string(html_string, parse_options(options))
end
def make_and_send_pdf(pdf_name, options = {})
options[:wkhtmltopdf] ||= nil
options[:layout] ||= false
options[:template] ||= File.join(controller_path, action_name)
if options[:show_as_html]
render :text => render_to_string(:template => options[:template], :layout => options[:layout])
else
send_data(make_pdf(options), :filename => pdf_name + '.pdf', :type => 'application/pdf')
end
end
def make_option name, value, type=:string
"--#{name.gsub('_', '-')} " + case type
when :boolean: ""
when :numeric: value.to_s
else "'#{value}'"
end + " "
end
def make_options opts, names, prefix="", type=:string
names.collect {|o| make_option("#{prefix.blank? ? "" : prefix + "-"}#{o.to_s}", opts[o], type) unless opts[o].blank?}.join
end
def parse_header_footer opts
r=""
[:header, :footer].collect do |hf|
unless opts[hf].blank?
opt_hf = opts[hf]
r += make_options(opt_hf, [:center, :font_name, :left, :right], "#{hf.to_s}")
r += make_options(opt_hf, [:font_size, :spacing], "#{hf.to_s}", :numeric)
r += make_options(opt_hf, [:line], "#{hf.to_s}", :boolean)
unless opt_hf[:html].blank?
r += make_option("#{hf.to_s}-html", opt_hf[:html][:url]) unless opt_hf[:html][:url].blank?
WickedPdfTempfile.open("wicked_pdf.html") do |f|
f << render_to_string(:template => opt_hf[:html][:template], :layout => opts[:layout])
r += make_option("#{hf.to_s}-html", "file://#{f.path}")
end unless opt_hf[:html][:template].blank?
end
end
end unless opts.blank?
r
end
def parse_toc opts
unless opts.blank?
r = make_options(opts, [:font_name, :header_text], "toc")
r += make_options(opts, [:depth, :header_fs, :l1_font_size, :l2_font_size, :l3_font_size, :l4_font_size, :l5_font_size, :l6_font_size, :l7_font_size, :l1_indentation, :l2_indentation, :l3_indentation, :l4_indentation, :l5_indentation, :l6_indentation, :l7_indentation], "toc", :numeric)
r + make_options(opts, [:no_dots, :disable_links, :disable_back_links], "toc", :boolean)
end
end
def parse_outline opts
unless opts.blank?
r = make_options(opts, [:outline], "", :boolean)
r + make_options(opts, [:outline_depth], "", :numeric)
end
end
def parse_margins opts
make_options(opts, [:top, :bottom, :left, :right], "margin", :numeric) unless opts.blank?
end
def parse_others opts
unless opts.blank?
r = make_options(opts, [:orientation, :page_size, :proxy, :username, :password, :cover, :dpi, :encoding, :user_style_sheet])
r += make_options(opts, [:redirect_delay, :zoom, :page_offset], "", :numeric)
r + make_options(opts, [:book, :default_header, :disable_javascript, :greyscale, :lowquality, :enable_plugins, :disable_internal_links, :disable_external_links, :print_media_type, :disable_smart_shrinking, :use_xserver, :no_background], "", :boolean)
end
end
end
<h3>Samples</h3>
<ul>
<li>
hello world (<%= link_to 'html', samples_path('hello_world') %> |
<%= link_to 'pdf', samples_path('hello_world', 'pdf') %>)
</li>
<li>
breakfast (<%= link_to 'html', samples_path('breakfast') %> |
<%= link_to 'pdf', samples_path('breakfast', 'pdf') %>)
</li>
</ul>
require 'test_helper'
WICKED_PDF = { :exe_path => '/usr/local/bin/wkhtmltopdf' }
HTML_DOCUMENT = "<html><body>Hello World</body></html>"
class WickedPdfTest < ActiveSupport::TestCase
test "should generate PDF from html document" do
wp = WickedPdf.new
pdf = wp.pdf_from_string HTML_DOCUMENT
assert pdf.start_with?("%PDF-1.4")
assert pdf.rstrip.end_with?("%%EOF")
assert pdf.length > 100
end
test "should raise exception when no path to wkhtmltopdf" do
assert_raise RuntimeError do
WickedPdf.new " "
end
end
test "should raise exception when wkhtmltopdf path is wrong" do
assert_raise RuntimeError do
WickedPdf.new "/i/do/not/exist/notwkhtmltopdf"
end
end
test "should raise exception when wkhtmltopdf is not executable" do
fp = File.expand_path(File.dirname(__FILE__)) + '/wkhtmltopdf'
File.chmod 0000, fp
assert_raise RuntimeError do
WickedPdf.new fp
end
File.chmod 0755, fp
end
test "should raise exception when pdf generation fails" do
fp = File.expand_path(File.dirname(__FILE__)) + '/wkhtmltopdf'
File.chmod 0777, fp
wp = WickedPdf.new fp
assert_raise RuntimeError do
wp.pdf_from_string HTML_DOCUMENT
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment