-
Notifications
You must be signed in to change notification settings - Fork 640
/
pdf_helper.rb
128 lines (112 loc) · 4.45 KB
/
pdf_helper.rb
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
class WickedPdf
module PdfHelper
def self.prepended(base)
# Protect from trying to augment modules that appear
# as the result of adding other gems.
return if base != ActionController::Base
base.class_eval do
after_action :clean_temp_files
end
end
def render(*args)
options = args.first
if options.is_a?(Hash) && options.key?(:pdf)
render_with_wicked_pdf(options)
else
super
end
end
def render_to_string(*args)
options = args.first
if options.is_a?(Hash) && options.key?(:pdf)
render_to_string_with_wicked_pdf(options)
else
super
end
end
def render_with_wicked_pdf(options)
raise ArgumentError, 'missing keyword: pdf' unless options.is_a?(Hash) && options.key?(:pdf)
options[:basic_auth] = set_basic_auth(options)
make_and_send_pdf(options.delete(:pdf), (WickedPdf.config || {}).merge(options))
end
def render_to_string_with_wicked_pdf(options)
raise ArgumentError, 'missing keyword: pdf' unless options.is_a?(Hash) && options.key?(:pdf)
options[:basic_auth] = set_basic_auth(options)
options.delete :pdf
make_pdf((WickedPdf.config || {}).merge(options))
end
private
def set_basic_auth(options = {})
options[:basic_auth] ||= WickedPdf.config.fetch(:basic_auth) { false }
return unless options[:basic_auth] && request.env['HTTP_AUTHORIZATION']
request.env['HTTP_AUTHORIZATION'].split(' ').last
end
def clean_temp_files
return unless defined?(@hf_tempfiles)
@hf_tempfiles.each(&:close)
end
def make_pdf(options = {})
render_opts = {
:template => options[:template],
:layout => options[:layout],
:formats => options[:formats],
:handlers => options[:handlers],
:assigns => options[:assigns]
}
render_opts[:inline] = options[:inline] if options[:inline]
render_opts[:locals] = options[:locals] if options[:locals]
render_opts[:file] = options[:file] if options[:file]
html_string = render_to_string(render_opts)
options = prerender_header_and_footer(options)
w = WickedPdf.new(options[:wkhtmltopdf])
w.pdf_from_string(html_string, options)
end
def make_and_send_pdf(pdf_name, options = {})
options[:wkhtmltopdf] ||= nil
options[:layout] ||= false
options[:template] ||= File.join(controller_path, action_name)
options[:disposition] ||= 'inline'
if options[:show_as_html]
render_opts = {
:template => options[:template],
:layout => options[:layout],
:formats => options[:formats],
:handlers => options[:handlers],
:assigns => options[:assigns],
:content_type => 'text/html'
}
render_opts[:inline] = options[:inline] if options[:inline]
render_opts[:locals] = options[:locals] if options[:locals]
render_opts[:file] = options[:file] if options[:file]
render(render_opts)
else
pdf_content = make_pdf(options)
File.open(options[:save_to_file], 'wb') { |file| file << pdf_content } if options[:save_to_file]
send_data(pdf_content, :filename => pdf_name + '.pdf', :type => 'application/pdf', :disposition => options[:disposition]) unless options[:save_only]
end
end
# Given an options hash, prerenders content for the header and footer sections
# to temp files and return a new options hash including the URLs to these files.
def prerender_header_and_footer(options)
%i[header footer].each do |hf|
next unless options[hf] && options[hf][:html] && options[hf][:html][:template]
@hf_tempfiles = [] unless defined?(@hf_tempfiles)
@hf_tempfiles.push(tf = WickedPdf::Tempfile.new("wicked_#{hf}_pdf.html"))
options[hf][:html][:layout] ||= options[:layout]
render_opts = {
:template => options[hf][:html][:template],
:layout => options[hf][:html][:layout],
:formats => options[hf][:html][:formats],
:handlers => options[hf][:html][:handlers],
:assigns => options[hf][:html][:assigns]
}
render_opts[:locals] = options[hf][:html][:locals] if options[hf][:html][:locals]
render_opts[:file] = options[hf][:html][:file] if options[:file]
tf.write render_to_string(render_opts)
tf.flush
options[hf][:html][:url] = "file:///#{tf.path}"
end
options
end
end
end