renorb-pdf_filler 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.rdoc +117 -0
- data/Rakefile +4 -0
- data/init.rb +1 -0
- data/lib/iText-2.1.7.jar +0 -0
- data/lib/pdf_filler.rb +50 -0
- data/lib/pdf_filler/book.rb +94 -0
- data/lib/pdf_filler/page.rb +246 -0
- data/lib/pdf_filler/pdf_db_mapper.rb +74 -0
- data/lib/pdf_filler/util_methods.rb +50 -0
- data/spec/lib/pdf_book_spec.rb +74 -0
- data/spec/lib/pdf_db_mapper_spec.rb +51 -0
- data/spec/lib/pdf_page_spec.rb +89 -0
- data/spec/spec_helper.rb +111 -0
- data/spec/templates/certificate_template.pdf +0 -0
- data/tasks/build_gem.rake +60 -0
- data/tasks/documentation.rake +32 -0
- metadata +86 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Great Basin Solutions, LLC dba Great Basin Development
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
= pdf_filler
|
2
|
+
|
3
|
+
The <b>pdf_filler</b> Rails plugin makes it easy to update existing PDFs that have form fields defined.
|
4
|
+
Rather then building PDFs in Ruby using something like PDF-Writer, it is much easier to create a PDF in Acrobat,
|
5
|
+
define fields, and update those fields using pdf_filler. An example would be a First/Last name field on a PDF that is possible to update.
|
6
|
+
|
7
|
+
|
8
|
+
== Requirements
|
9
|
+
|
10
|
+
This plugin requires RJB (Ruby Java Bridge), so you will need to set your JAVA_HOME environment variable to point your installation of Java.
|
11
|
+
|
12
|
+
If your JAVA_HOME environment variable is not setup correctly you will get something like:
|
13
|
+
|
14
|
+
|
15
|
+
Building native extensions. This could take a while...
|
16
|
+
ERROR: Error installing pdf_filler-0.1.0.gem:
|
17
|
+
ERROR: Failed to build gem native extension.
|
18
|
+
|
19
|
+
/opt/local/bin/ruby extconf.rb
|
20
|
+
*** extconf.rb failed ***
|
21
|
+
Could not create Makefile due to some reason, probably lack of
|
22
|
+
necessary libraries and/or headers. Check the mkmf.log file for more
|
23
|
+
details. You may need configuration options.
|
24
|
+
|
25
|
+
Provided configuration options:
|
26
|
+
--with-opt-dir
|
27
|
+
--without-opt-dir
|
28
|
+
--with-opt-include
|
29
|
+
--without-opt-include=${opt-dir}/include
|
30
|
+
--with-opt-lib
|
31
|
+
--without-opt-lib=${opt-dir}/lib
|
32
|
+
--with-make-prog
|
33
|
+
--without-make-prog
|
34
|
+
--srcdir=.
|
35
|
+
--curdir
|
36
|
+
--ruby=/opt/local/bin/ruby
|
37
|
+
extconf.rb:45: JAVA_HOME is not set. (RuntimeError)
|
38
|
+
|
39
|
+
Gem files will remain installed in /opt/local/lib/ruby/gems/1.8/gems/rjb-1.1.7 for inspection.
|
40
|
+
Results logged to /opt/local/lib/ruby/gems/1.8/gems/rjb-1.1.7/ext/gem_make.out
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
<b>On my Mac I set JAVA_HOME to be "/System/Library/Frameworks/JavaVM.framework/Versions/1.5/Home".</b>
|
45
|
+
|
46
|
+
|
47
|
+
== Installing
|
48
|
+
|
49
|
+
The recommended method to enable pdf_filler in your project is adding the pdf_filler gem to your environment. Add the following code to your Rails configuration in <tt>config/environment.rb</tt>:
|
50
|
+
|
51
|
+
Rails::Initializer.run do |config|
|
52
|
+
...
|
53
|
+
config.gem 'gbdev-pdf_filler', :lib => 'pdf_filler', source => 'http://gems.github.com/'
|
54
|
+
end
|
55
|
+
|
56
|
+
Run <tt>sudo rake gems:install</tt> to install the gem.
|
57
|
+
|
58
|
+
Another alternative is to install pdf_filler as a Rails plugin:
|
59
|
+
|
60
|
+
script/plugin install git://github.com/gbdev/pdf_filler.git
|
61
|
+
|
62
|
+
|
63
|
+
== Usage
|
64
|
+
|
65
|
+
1. You will need a PDF that has form fields to fill.
|
66
|
+
|
67
|
+
2. A writable directory to store the generated PDFs.
|
68
|
+
|
69
|
+
3. For a single page use the Page object?
|
70
|
+
|
71
|
+
// ** Single page **
|
72
|
+
page = GBDev::PDF::Page.new('/path/to/template.pdf')
|
73
|
+
page.set_text(:full_name, 'Wes Hays')
|
74
|
+
page.save_to('/path/to/save.pdf')
|
75
|
+
|
76
|
+
4. For a collection of pages to be added to a single PDF use a Book object.
|
77
|
+
|
78
|
+
book = GBDev::PDF::Book.new
|
79
|
+
|
80
|
+
page1 = GBDev::PDF::Page.new('/path/to/template1.pdf')
|
81
|
+
page1.set_text(:full_name, 'Wes Hays')
|
82
|
+
|
83
|
+
page2 = GBDev::PDF::Page.new('/path/to/template2.pdf')
|
84
|
+
page2.set_text(:full_name, 'Darren Johnson')
|
85
|
+
|
86
|
+
book.add_page(page1)
|
87
|
+
book.add_page(page2)
|
88
|
+
|
89
|
+
book.save_to('/page/to/book.pdf')
|
90
|
+
|
91
|
+
5. Rather then setting all the fields manually a PDF can be mapped to an ActiveRecord model.
|
92
|
+
The model must use the acts_as_pdf_db_mapper module. (<b><i>See rdocs on acts_as_pdf_db_mapper for more options</i></b>)
|
93
|
+
|
94
|
+
class User < ActiveRecord::Base
|
95
|
+
...
|
96
|
+
acts_as_pdf_db_mapper
|
97
|
+
...
|
98
|
+
end
|
99
|
+
|
100
|
+
user = User.first
|
101
|
+
page = GBDev::PDF::Page.new('/path/to/template1.pdf')
|
102
|
+
page.map_to_object(user)
|
103
|
+
page.save_to('/path/to/save.pdf)
|
104
|
+
|
105
|
+
|
106
|
+
Note: You can use the shorter kernel methods PDFPage instead of GBDev::PDF::Page.new. The same goes for PDFBook instead of GBDev::PDF::Book.new.
|
107
|
+
|
108
|
+
Example:
|
109
|
+
|
110
|
+
page = PDFPage('/path/to/template.pdf')
|
111
|
+
book = PDFBook()
|
112
|
+
|
113
|
+
|
114
|
+
== License
|
115
|
+
|
116
|
+
This plugin is released under the MIT license. Please contact weshays (http://github.com/weshays)
|
117
|
+
or djohnson (http://github.com/djohnson) for any questions.
|
data/Rakefile
ADDED
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'pdf_filler'
|
data/lib/iText-2.1.7.jar
ADDED
Binary file
|
data/lib/pdf_filler.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'rjb'
|
3
|
+
|
4
|
+
load_path = File.expand_path(File.dirname(__FILE__) + '/iText-2.1.7.jar')
|
5
|
+
options = ['-Djava.awt.headless=true']
|
6
|
+
Rjb::load load_path, options
|
7
|
+
|
8
|
+
FileOutputStream = Rjb::import('java.io.FileOutputStream')
|
9
|
+
ByteArrayOutputStream = Rjb::import('java.io.ByteArrayOutputStream')
|
10
|
+
ByteArrayInputStream = Rjb::import('java.io.ByteArrayInputStream')
|
11
|
+
PdfWriter = Rjb::import('com.lowagie.text.pdf.PdfWriter')
|
12
|
+
PdfReader = Rjb::import('com.lowagie.text.pdf.PdfReader')
|
13
|
+
PdfCopy = Rjb::import('com.lowagie.text.pdf.PdfCopy')
|
14
|
+
PdfImportedPage = Rjb::import('com.lowagie.text.pdf.PdfImportedPage')
|
15
|
+
Document = Rjb::import('com.lowagie.text.Document')
|
16
|
+
Paragraph = Rjb::import('com.lowagie.text.Paragraph')
|
17
|
+
AcroFields = Rjb::import('com.lowagie.text.pdf.AcroFields')
|
18
|
+
PdfStamper = Rjb::import('com.lowagie.text.pdf.PdfStamper')
|
19
|
+
HashMap = Rjb::import('java.util.HashMap')
|
20
|
+
Iterator = Rjb::import('java.util.Iterator')
|
21
|
+
|
22
|
+
require 'pdf_filler/util_methods'
|
23
|
+
require 'pdf_filler/page'
|
24
|
+
require 'pdf_filler/book'
|
25
|
+
require 'pdf_filler/pdf_db_mapper'
|
26
|
+
|
27
|
+
|
28
|
+
module Kernel
|
29
|
+
|
30
|
+
# A shortcut kernel method for creating a new PDF Page without having to specify the full path to the page.
|
31
|
+
# Therefore,
|
32
|
+
# * PDFPage(template)
|
33
|
+
# and
|
34
|
+
# * RenoRB::PDF::Page.new(template)
|
35
|
+
# are the same thing.
|
36
|
+
def PDFPage(template)
|
37
|
+
RenoRB::PDF::Page.new(template)
|
38
|
+
end
|
39
|
+
|
40
|
+
# A shortcut kernel method for creating a new PDF Book without having to specify the full path to the book.
|
41
|
+
# Therefore,
|
42
|
+
# * PDFBook()
|
43
|
+
# and
|
44
|
+
# * RenoRB::PDF::Book.new
|
45
|
+
# are the same thing.
|
46
|
+
def PDFBook()
|
47
|
+
RenoRB::PDF::Book.new
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module RenoRB
|
2
|
+
|
3
|
+
module PDF
|
4
|
+
|
5
|
+
# A book that represents collection of PDF page.
|
6
|
+
class Book
|
7
|
+
|
8
|
+
def initialize()
|
9
|
+
@pages = []
|
10
|
+
end
|
11
|
+
|
12
|
+
# Add a page to the book
|
13
|
+
#
|
14
|
+
# * new_page - The page object of type RenoRB::PDF::Page
|
15
|
+
def add_page(new_page)
|
16
|
+
@pages << new_page
|
17
|
+
end
|
18
|
+
|
19
|
+
# Renders the PDF Book and saves it to the specified file.
|
20
|
+
#
|
21
|
+
# * filename - A path to the file to be created.
|
22
|
+
def save_to(filename)
|
23
|
+
dir = File.dirname(filename)
|
24
|
+
temp_dir = [dir, "collection_temp_#{build_random_string}"].join('/')
|
25
|
+
Dir.mkdir(temp_dir)
|
26
|
+
@pages.each_with_index do |page, indx|
|
27
|
+
page.save_to([temp_dir, "#{indx}_#{build_random_file_name}"].join('/'))
|
28
|
+
end
|
29
|
+
temp_files = Dir[[temp_dir,'*'].join('/')].sort
|
30
|
+
|
31
|
+
document = Document.new
|
32
|
+
copier = PdfCopy.new(document, FileOutputStream.new(filename))
|
33
|
+
|
34
|
+
document.open
|
35
|
+
temp_files.each do |read_target|
|
36
|
+
reader = PdfReader.new(read_target)
|
37
|
+
n_pages = reader.getNumberOfPages
|
38
|
+
n_pages.times do |i|
|
39
|
+
copier.addPage( copier.getImportedPage(reader, i+1)) if copier
|
40
|
+
end
|
41
|
+
end
|
42
|
+
document.close
|
43
|
+
|
44
|
+
FileUtils.rm_rf(temp_dir, {:secure => true})
|
45
|
+
end
|
46
|
+
|
47
|
+
# Renders the template with the given data and returns that buffer.
|
48
|
+
def to_buffer
|
49
|
+
dir = defined?(RAILS_ROOT) ? [RAILS_ROOT, 'tmp'].join('/') : File.expand_path(File.dirname(__FILE__) + '/../../spec/output')
|
50
|
+
temp_dir = [dir, "collection_temp_#{build_random_string}"].join('/')
|
51
|
+
Dir.mkdir(temp_dir)
|
52
|
+
@pages.each_with_index do |page, indx|
|
53
|
+
page.save_to([temp_dir, "#{indx}_#{build_random_file_name}"].join('/'))
|
54
|
+
end
|
55
|
+
temp_files = Dir[[temp_dir,'*'].join('/')].sort
|
56
|
+
|
57
|
+
document = Document.new
|
58
|
+
baos = ByteArrayOutputStream.new
|
59
|
+
copier = PdfCopy.new(document, baos)
|
60
|
+
|
61
|
+
document.open
|
62
|
+
|
63
|
+
# This did not work but try working on it again later.
|
64
|
+
# @pages.each do |page|
|
65
|
+
# bais = ByteArrayInputStream.new_with_sig(page.to_buffer)
|
66
|
+
# reader = PdfReader.new(bais)
|
67
|
+
# reader = page.get_pdf_reader
|
68
|
+
# n_pages = reader.getNumberOfPages
|
69
|
+
# n_pages.times do |i|
|
70
|
+
# copier.addPage( copier.getImportedPage(reader, i+1)) if copier
|
71
|
+
# end
|
72
|
+
# end
|
73
|
+
|
74
|
+
temp_files.each do |read_target|
|
75
|
+
reader = PdfReader.new(read_target)
|
76
|
+
n_pages = reader.getNumberOfPages
|
77
|
+
n_pages.times do |i|
|
78
|
+
copier.addPage( copier.getImportedPage(reader, i+1)) if copier
|
79
|
+
end
|
80
|
+
end
|
81
|
+
document.close
|
82
|
+
|
83
|
+
#FileUtils.rm_rf(temp_dir, {:secure => true})
|
84
|
+
|
85
|
+
return baos.toByteArray()
|
86
|
+
end
|
87
|
+
|
88
|
+
include RenoRB::Utils::PrivateMethods
|
89
|
+
|
90
|
+
end # End Filler
|
91
|
+
|
92
|
+
end # End PDF
|
93
|
+
|
94
|
+
end # End RenoRB
|
@@ -0,0 +1,246 @@
|
|
1
|
+
module RenoRB
|
2
|
+
|
3
|
+
module PDF
|
4
|
+
|
5
|
+
# A page that represents a PDF page.
|
6
|
+
class Page
|
7
|
+
|
8
|
+
CHECK_BOX = 'Check Box'
|
9
|
+
COMBO_BOX = 'Combo Box'
|
10
|
+
LIST = 'List'
|
11
|
+
PUSH_BUTTON = 'Push Button'
|
12
|
+
RADIO_BUTTON = 'Radio Button'
|
13
|
+
SIGNATURE = 'Signature'
|
14
|
+
TEXT_FIELD = 'Text Field'
|
15
|
+
NONE = 'None'
|
16
|
+
UNKNOWN = '?'
|
17
|
+
|
18
|
+
# String template : A path to the template file
|
19
|
+
def initialize(template)
|
20
|
+
@template = template
|
21
|
+
|
22
|
+
@pdf_fields = {}
|
23
|
+
|
24
|
+
@check_boxes = {}
|
25
|
+
@images = {}
|
26
|
+
@radio_buttons = {}
|
27
|
+
@signature_fields = {}
|
28
|
+
@text_fields = {}
|
29
|
+
|
30
|
+
@pdf_reader = nil
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns a hash where the keys are the field names in the template PDF and the values are the field types.
|
34
|
+
def get_pdf_fields
|
35
|
+
return @pdf_fields unless @pdf_fields.empty?
|
36
|
+
|
37
|
+
reader = PdfReader.new(@template)
|
38
|
+
form = reader.getAcroFields()
|
39
|
+
fields = form.getFields()
|
40
|
+
i = fields.keySet().iterator()
|
41
|
+
|
42
|
+
while(i.hasNext())
|
43
|
+
key = i.next()
|
44
|
+
|
45
|
+
case(form.getFieldType(key))
|
46
|
+
when AcroFields.FIELD_TYPE_CHECKBOX
|
47
|
+
@pdf_fields[key.to_string().to_sym] = RenoRB::PDF::Page::CHECK_BOX
|
48
|
+
when AcroFields.FIELD_TYPE_COMBO
|
49
|
+
@pdf_fields[key.to_string().to_sym] = RenoRB::PDF::Page::COMBO_BOX
|
50
|
+
when AcroFields.FIELD_TYPE_LIST
|
51
|
+
@pdf_fields[key.to_string().to_sym] = RenoRB::PDF::Page::LIST
|
52
|
+
when AcroFields.FIELD_TYPE_NONE
|
53
|
+
@pdf_fields[key.to_string().to_sym] = RenoRB::PDF::Page::NONE
|
54
|
+
when AcroFields.FIELD_TYPE_PUSHBUTTON
|
55
|
+
@pdf_fields[key.to_string().to_sym] = RenoRB::PDF::Page::PUSH_BUTTON
|
56
|
+
when AcroFields.FIELD_TYPE_RADIOBUTTON
|
57
|
+
@pdf_fields[key.to_string().to_sym] = RenoRB::PDF::Page::RADIO_BUTTON
|
58
|
+
when AcroFields.FIELD_TYPE_SIGNATURE
|
59
|
+
@pdf_fields[key.to_string().to_sym] = RenoRB::PDF::Page::SIGNATURE
|
60
|
+
when AcroFields.FIELD_TYPE_TEXT
|
61
|
+
@pdf_fields[key.to_string().to_sym] = RenoRB::PDF::Page::TEXT_FIELD
|
62
|
+
else
|
63
|
+
@pdf_fields[key.to_string().to_sym] = RenoRB::PDF::Page::UNKNOWN
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
return @pdf_fields
|
68
|
+
end
|
69
|
+
|
70
|
+
# Returns an array of field states. For example if the field type is a list an array
|
71
|
+
# with all possible choices in the list will be returned.
|
72
|
+
#
|
73
|
+
# * field_name - The field name to get all the possible states for.
|
74
|
+
def get_field_states(field_name)
|
75
|
+
reader = PdfReader.new(@template)
|
76
|
+
form = reader.getAcroFields()
|
77
|
+
form.getAppearanceStates(field_name.to_s);
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
# Sets a know checkbox in the PDF template.
|
82
|
+
#
|
83
|
+
# * key - A known checkbox in the PDF.
|
84
|
+
# * value - The checkbox to update.
|
85
|
+
def set_checkbox(key, value)
|
86
|
+
@check_boxes[key] = value
|
87
|
+
end
|
88
|
+
|
89
|
+
# Alias for the set_checkbox method
|
90
|
+
alias :checkbox :set_checkbox
|
91
|
+
|
92
|
+
# NOT WORING YET
|
93
|
+
# Sets a known image area in the PDF template.
|
94
|
+
#
|
95
|
+
# * key - A known image in the PDF.
|
96
|
+
# * value - The image to apply to the know image area.
|
97
|
+
def set_image(key, value)
|
98
|
+
raise 'Image not working yet'
|
99
|
+
@images[key] = value
|
100
|
+
end
|
101
|
+
|
102
|
+
# Alias for the set_image method
|
103
|
+
alias :image :set_image
|
104
|
+
|
105
|
+
|
106
|
+
# Sets a known radio button in the PDF template.
|
107
|
+
#
|
108
|
+
# * key - A known radio button group in the PDF.
|
109
|
+
# * value - The radio button group to update.
|
110
|
+
def set_radio_button(key, value)
|
111
|
+
@radio_buttons[key] = value
|
112
|
+
end
|
113
|
+
|
114
|
+
# Alias for the set_checkbox method
|
115
|
+
alias :radio_button :set_radio_button
|
116
|
+
|
117
|
+
|
118
|
+
# NOT WORKING YET
|
119
|
+
# Sets a known signature field in the PDF template.
|
120
|
+
#
|
121
|
+
# * key - A known signature field in the PDF.
|
122
|
+
# * value - The value to apply to the know field.
|
123
|
+
def set_signature_field(key, value)
|
124
|
+
raise 'Signature field not working yet'
|
125
|
+
@signature_fields[key] = value
|
126
|
+
end
|
127
|
+
|
128
|
+
# Alias for set_signature_field method
|
129
|
+
alias :signature_field :set_signature_field
|
130
|
+
|
131
|
+
|
132
|
+
# Sets a known text field in the PDF template.
|
133
|
+
#
|
134
|
+
# * key - A known text field in the PDF.
|
135
|
+
# * value - The value to apply to the know field.
|
136
|
+
def set_text_field(key, value)
|
137
|
+
@text_fields[key] = value
|
138
|
+
end
|
139
|
+
|
140
|
+
# Alias for set_text method
|
141
|
+
alias :text_field :set_text_field
|
142
|
+
|
143
|
+
# Maps PDF fields to an ActiveRecord object. The ActiveRecord object must use the
|
144
|
+
# acts_as_pdf_db_mapper module.
|
145
|
+
#
|
146
|
+
# * object - An ActiveRecord object that uses the acts_as_pdf_db_mapper module.
|
147
|
+
def map_to_object(object)
|
148
|
+
if object.methods.include?('mapped_fields')
|
149
|
+
fields = self.get_pdf_fields
|
150
|
+
object.mapped_fields.each do |mapped_field|
|
151
|
+
|
152
|
+
if mapped_field.class.to_s == 'Hash'
|
153
|
+
key_value_pair = mapped_field.first.to_a.flatten
|
154
|
+
key = key_value_pair[0]
|
155
|
+
value = key_value_pair[1]
|
156
|
+
else
|
157
|
+
key = mapped_field
|
158
|
+
value = mapped_field
|
159
|
+
end
|
160
|
+
|
161
|
+
case(fields[key])
|
162
|
+
when RenoRB::PDF::Page::CHECK_BOX
|
163
|
+
self.set_checkbox(key, object.send(value))
|
164
|
+
when RenoRB::PDF::Page::COMBO_BOX
|
165
|
+
#self.set_combobox(key, object.send(value))
|
166
|
+
when RenoRB::PDF::Page::LIST
|
167
|
+
#self.set_list(key, object.send(value))
|
168
|
+
when RenoRB::PDF::Page::NONE
|
169
|
+
#self.set_none(key, object.send(value))
|
170
|
+
when RenoRB::PDF::Page::PUSH_BUTTON
|
171
|
+
#self.set_push_button(key, object.send(value))
|
172
|
+
when RenoRB::PDF::Page::RADIO_BUTTON
|
173
|
+
self.set_radio_button(key, object.send(value))
|
174
|
+
when RenoRB::PDF::Page::SIGNATURE
|
175
|
+
self.set_signature_field(key, object.send(value))
|
176
|
+
when RenoRB::PDF::Page::TEXT_FIELD
|
177
|
+
self.set_text_field(key, object.send(value))
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
|
185
|
+
# Renders the template with the given data and saves to the given filename path.
|
186
|
+
#
|
187
|
+
# * filename - A path to the file to be created.
|
188
|
+
def save_to(filename)
|
189
|
+
field_cache = HashMap.new
|
190
|
+
reader = PdfReader.new(@template)
|
191
|
+
stamper = PdfStamper.new( reader, FileOutputStream.new(filename) )
|
192
|
+
form = stamper.getAcroFields()
|
193
|
+
form.setFieldCache(field_cache)
|
194
|
+
|
195
|
+
all_fields = {}
|
196
|
+
all_fields.merge!(@check_boxes)
|
197
|
+
all_fields.merge!(@radio_buttons)
|
198
|
+
all_fields.merge!(@signature_fields)
|
199
|
+
all_fields.merge!(@text_fields)
|
200
|
+
|
201
|
+
all_fields.each do |field, value|
|
202
|
+
form.setField(field.to_s, value.to_s)
|
203
|
+
end
|
204
|
+
|
205
|
+
# TODO: do something with @images
|
206
|
+
|
207
|
+
stamper.setFormFlattening(true)
|
208
|
+
stamper.close
|
209
|
+
end
|
210
|
+
|
211
|
+
|
212
|
+
# Renders the template with the given data and returns that buffer.
|
213
|
+
def to_buffer
|
214
|
+
field_cache = HashMap.new
|
215
|
+
reader = PdfReader.new(@template)
|
216
|
+
baos = ByteArrayOutputStream.new
|
217
|
+
stamper = PdfStamper.new( reader, baos )
|
218
|
+
form = stamper.getAcroFields()
|
219
|
+
form.setFieldCache(field_cache)
|
220
|
+
|
221
|
+
all_fields = {}
|
222
|
+
all_fields.merge!(@check_boxes)
|
223
|
+
all_fields.merge!(@radio_buttons)
|
224
|
+
all_fields.merge!(@signature_fields)
|
225
|
+
all_fields.merge!(@text_fields)
|
226
|
+
|
227
|
+
all_fields.each do |field, value|
|
228
|
+
form.setField(field.to_s, value.to_s)
|
229
|
+
end
|
230
|
+
|
231
|
+
# TODO: do something with @images
|
232
|
+
|
233
|
+
stamper.setFormFlattening(true)
|
234
|
+
stamper.close
|
235
|
+
|
236
|
+
return baos.toByteArray()
|
237
|
+
end
|
238
|
+
|
239
|
+
|
240
|
+
include RenoRB::Utils::PrivateMethods
|
241
|
+
|
242
|
+
end # End Page
|
243
|
+
|
244
|
+
end # End PDF
|
245
|
+
|
246
|
+
end # End RenoRB
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
module RenoRB #:nodoc:
|
4
|
+
module PDF #:nodoc:
|
5
|
+
module Acts #:nodoc:
|
6
|
+
module PDFDBMapper # :nodoc:
|
7
|
+
|
8
|
+
def self.included(mod)
|
9
|
+
mod.extend(ClassMethods)
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
|
14
|
+
# Automatically maps database fields to fields found in the template PDF with the same name.
|
15
|
+
# Database fields not found in the template PDF are ignored. If no options are specified then
|
16
|
+
# by default all table fields will attempt to be mapped.
|
17
|
+
#
|
18
|
+
# Configuration options are:
|
19
|
+
#
|
20
|
+
# * :only - Only map the database fields specified. i.e :only => [:first_name, :last_name]
|
21
|
+
# * :except - Map all the table fields except those specified. i.e. :except => [:middle_name]
|
22
|
+
# * :include - Allows for a method to map to a field in the PDF. If you have a method called full_name
|
23
|
+
# that combines the first name and last name, you could map that method to a PDF text field called full_name.
|
24
|
+
# :include => [:full_name].
|
25
|
+
# You could all specify a model attribute/method to map to a different PDF field.
|
26
|
+
# i.e. :include => [{:full_name => :dog_name}]
|
27
|
+
# :include will still work with :only and :except.
|
28
|
+
# * :only_include - Will ignore :only and :except and only includes the manual mappings specified.
|
29
|
+
# i.e. :only_include => [:full_name, {:animal_name => :dog_name}]
|
30
|
+
def acts_as_pdf_db_mapper(*fields)
|
31
|
+
|
32
|
+
# Make sure that the table to be mapped actually exists
|
33
|
+
if self.table_exists?
|
34
|
+
|
35
|
+
# Get a collection of fields to be searched on.
|
36
|
+
if fields.first.class.to_s == 'Hash'
|
37
|
+
|
38
|
+
if fields.first.has_key?(:only_include)
|
39
|
+
fields_to_map = fields.first[:only_include]
|
40
|
+
else
|
41
|
+
if fields.first.has_key?(:only)
|
42
|
+
# only map on these fields.
|
43
|
+
fields_to_map = fields.first[:only]
|
44
|
+
elsif fields.first.has_key?(:except)
|
45
|
+
# Get all the fields and remove any that are in the -except- list.
|
46
|
+
fields_to_map = self.column_names.collect { |column| fields.first[:except].include?(column.to_sym) ? nil : column.to_sym }.compact
|
47
|
+
else
|
48
|
+
fields_to_map = self.column_names.collect { |column| column.to_sym }
|
49
|
+
end
|
50
|
+
|
51
|
+
if fields.first.has_key?(:include)
|
52
|
+
fields_to_map += fields.first[:include]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
else
|
56
|
+
fields_to_map = self.column_names.collect { |column| column.to_sym }
|
57
|
+
end
|
58
|
+
|
59
|
+
# Set the appropriate class attributes.
|
60
|
+
self.cattr_accessor :mapped_fields
|
61
|
+
self.mapped_fields = fields_to_map
|
62
|
+
|
63
|
+
end # End table exists check
|
64
|
+
|
65
|
+
end # acts_as_pdf_db_mapper
|
66
|
+
|
67
|
+
end # ClassMethods
|
68
|
+
|
69
|
+
end # PDFDBMapper
|
70
|
+
end # Acts
|
71
|
+
end # PDF
|
72
|
+
end # RenoRB
|
73
|
+
|
74
|
+
ActiveRecord::Base.send(:include, RenoRB::PDF::Acts::PDFDBMapper)
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module RenoRB #:nodoc: all
|
2
|
+
|
3
|
+
module Utils
|
4
|
+
|
5
|
+
module PrivateMethods
|
6
|
+
|
7
|
+
def build_random_string # :nodoc:
|
8
|
+
letters_array = [('a'..'z'),('A'..'Z')].collect{|i| i.to_a}.flatten
|
9
|
+
(1..10).collect{ letters_array[ rand(letters_array.length) ] }.join
|
10
|
+
end
|
11
|
+
|
12
|
+
def build_random_file_name # :nodoc:
|
13
|
+
build_random_string << '.pdf'
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
# Include these controller methods to prompt the user to download the PDF.
|
20
|
+
#
|
21
|
+
# * include RenoRB::Utils::ControllerMethods
|
22
|
+
module ControllerMethods
|
23
|
+
|
24
|
+
# Used to display the PDF without saving it to disk.
|
25
|
+
#
|
26
|
+
# * buffer - A Page buffer or Book buffer.
|
27
|
+
# * filename - The filename to apply to the buffer when prompted to download.
|
28
|
+
def display_pdf(buffer, filename)
|
29
|
+
send_data(buffer, {:type => 'application/pdf',
|
30
|
+
:disposition => 'attachment',
|
31
|
+
:filename => filename} )
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
# From here: http://railspdfplugin.rubyforge.org/wiki/wiki.pl
|
36
|
+
# Suggested code so errors will always show in browser
|
37
|
+
def rescue_action_in_public(exception) # :nodoc:
|
38
|
+
headers.delete("Content-Disposition")
|
39
|
+
super
|
40
|
+
end
|
41
|
+
|
42
|
+
def rescue_action_locally(exception) # :nodoc:
|
43
|
+
headers.delete("Content-Disposition")
|
44
|
+
super
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
|
2
|
+
|
3
|
+
describe 'Book' do
|
4
|
+
|
5
|
+
it 'should create the book of pages and write to the output directory' do
|
6
|
+
book = RenoRB::PDF::Book.new
|
7
|
+
|
8
|
+
template_file = File.expand_path(File.dirname(__FILE__) + '/../templates/certificate_template.pdf')
|
9
|
+
pdf_book = File.expand_path(File.dirname(__FILE__) + '/../output/certs.pdf')
|
10
|
+
|
11
|
+
page1 = RenoRB::PDF::Page.new(template_file)
|
12
|
+
page1.set_text_field(:full_name, 'Wes Hays')
|
13
|
+
|
14
|
+
page2 = RenoRB::PDF::Page.new(template_file)
|
15
|
+
page2.set_text_field(:full_name, 'Darren Johnson')
|
16
|
+
|
17
|
+
page3 = RenoRB::PDF::Page.new(template_file)
|
18
|
+
page3.set_text_field(:full_name, 'John Dell')
|
19
|
+
|
20
|
+
book.add_page(page1)
|
21
|
+
book.add_page(page2)
|
22
|
+
book.add_page(page3)
|
23
|
+
|
24
|
+
book.save_to(pdf_book)
|
25
|
+
|
26
|
+
File.exist?(pdf_book).should be_true
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should create the book of pages and write to the output directory with Kernel method' do
|
30
|
+
book = PDFBook()
|
31
|
+
|
32
|
+
template_file = File.expand_path(File.dirname(__FILE__) + '/../templates/certificate_template.pdf')
|
33
|
+
pdf_book = File.expand_path(File.dirname(__FILE__) + '/../output/certs.pdf')
|
34
|
+
|
35
|
+
page1 = RenoRB::PDF::Page.new(template_file)
|
36
|
+
page1.set_text_field(:full_name, 'Wes Hays')
|
37
|
+
|
38
|
+
page2 = RenoRB::PDF::Page.new(template_file)
|
39
|
+
page2.set_text_field(:full_name, 'Darren Johnson')
|
40
|
+
|
41
|
+
page3 = RenoRB::PDF::Page.new(template_file)
|
42
|
+
page3.set_text_field(:full_name, 'John Dell')
|
43
|
+
|
44
|
+
book.add_page(page1)
|
45
|
+
book.add_page(page2)
|
46
|
+
book.add_page(page3)
|
47
|
+
|
48
|
+
book.save_to(pdf_book)
|
49
|
+
|
50
|
+
File.exist?(pdf_book).should be_true
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should return the buffer without writing to disk' do
|
54
|
+
book = PDFBook()
|
55
|
+
|
56
|
+
template_file = File.expand_path(File.dirname(__FILE__) + '/../templates/certificate_template.pdf')
|
57
|
+
|
58
|
+
page1 = RenoRB::PDF::Page.new(template_file)
|
59
|
+
page1.set_text_field(:full_name, 'Wes Hays')
|
60
|
+
|
61
|
+
page2 = RenoRB::PDF::Page.new(template_file)
|
62
|
+
page2.set_text_field(:full_name, 'Darren Johnson')
|
63
|
+
|
64
|
+
page3 = RenoRB::PDF::Page.new(template_file)
|
65
|
+
page3.set_text_field(:full_name, 'John Dell')
|
66
|
+
|
67
|
+
book.add_page(page1)
|
68
|
+
book.add_page(page2)
|
69
|
+
book.add_page(page3)
|
70
|
+
|
71
|
+
book.to_buffer.should_not be_blank
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
|
2
|
+
|
3
|
+
describe 'PDF_DB_Mapper' do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
Address.create_corpus!
|
7
|
+
end
|
8
|
+
|
9
|
+
after(:each) do
|
10
|
+
Address.destroy_all
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should allow all database columns to be mapped if no :only or :except is specified' do
|
14
|
+
address = Address.first
|
15
|
+
fields_array = address.mapped_fields.collect{|f| f.to_s}.sort
|
16
|
+
fields_array.should == ['id', 'address1', 'address2', 'city', 'state', 'postal_code'].sort
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should only map the fields specified by :only' do
|
20
|
+
address = ClientAddress.first
|
21
|
+
fields_array = address.mapped_fields.collect{|f| f.to_s}.sort
|
22
|
+
fields_array.should == ['city', 'state'].sort
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should map all the fields except the fields specified by :except' do
|
26
|
+
address = ContactAddress.first
|
27
|
+
fields_array = address.mapped_fields.collect{|f| f.to_s}.sort
|
28
|
+
fields_array.should == ['address2', 'city', 'state'].sort
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should include the additional mappings specified by :include' do
|
32
|
+
address = UserAddress.first
|
33
|
+
fields_array = address.mapped_fields.collect{|f| f.class.to_s == 'Hash' ? f.first.to_a.flatten.join('::') : f.to_s}.sort
|
34
|
+
fields_array.should == ['id', 'address1', 'address2', 'city', 'state', 'postal_code','full_address::address'].sort
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should only include the mappings specified by :only_include' do
|
38
|
+
address = FamilyAddress.first
|
39
|
+
fields_array = address.mapped_fields.collect{|f| f.first.to_a.flatten.join('::')}.sort
|
40
|
+
fields_array.should == ['full_address::address'].sort
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should map the specified fields for a single record to a single page' do
|
44
|
+
page = PDFPage(File.expand_path(File.dirname(__FILE__) + '/../templates/address_template.pdf'))
|
45
|
+
address = Address.first
|
46
|
+
page.map_to_object(address)
|
47
|
+
page.save_to(File.expand_path(File.dirname(__FILE__) + '/../output/db_address.pdf'))
|
48
|
+
File.exist?(File.dirname(__FILE__) + '/../output/db_address.pdf').should be_true
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
|
2
|
+
|
3
|
+
describe 'Page' do
|
4
|
+
|
5
|
+
it 'should create the page and write to the output directory' do
|
6
|
+
page = RenoRB::PDF::Page.new(File.expand_path(File.dirname(__FILE__) + '/../templates/certificate_template.pdf'))
|
7
|
+
page.set_text_field(:full_name, 'Wes Hays')
|
8
|
+
page.save_to(File.expand_path(File.dirname(__FILE__) + '/../output/wes_hays.pdf'))
|
9
|
+
File.exist?(File.dirname(__FILE__) + '/../output/wes_hays.pdf').should be_true
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should create the page and write to the output directory with Kernel method' do
|
13
|
+
page = PDFPage(File.expand_path(File.dirname(__FILE__) + '/../templates/certificate_template.pdf'))
|
14
|
+
page.set_text_field(:full_name, 'Wes Hays')
|
15
|
+
page.save_to(File.expand_path(File.dirname(__FILE__) + '/../output/wes_hays.pdf'))
|
16
|
+
File.exist?(File.dirname(__FILE__) + '/../output/wes_hays.pdf').should be_true
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should find all three fields: text field, checkbox and radio buttons' do
|
20
|
+
page = PDFPage(File.expand_path(File.dirname(__FILE__) + '/../templates/form_template.pdf'))
|
21
|
+
fields = page.get_pdf_fields
|
22
|
+
|
23
|
+
fields.has_key?(:full_name).should be_true
|
24
|
+
fields[:full_name].should == RenoRB::PDF::Page::TEXT_FIELD
|
25
|
+
|
26
|
+
fields.has_key?(:home_owner).should be_true
|
27
|
+
fields[:home_owner].should == RenoRB::PDF::Page::RADIO_BUTTON
|
28
|
+
|
29
|
+
fields.has_key?(:newsletter).should be_true
|
30
|
+
fields[:newsletter].should == RenoRB::PDF::Page::CHECK_BOX
|
31
|
+
|
32
|
+
fields.has_key?(:car_types).should be_true
|
33
|
+
fields[:car_types].should == RenoRB::PDF::Page::LIST
|
34
|
+
|
35
|
+
fields.has_key?(:sibling_count).should be_true
|
36
|
+
fields[:sibling_count].should == RenoRB::PDF::Page::COMBO_BOX
|
37
|
+
|
38
|
+
# fields.has_key?(:owner_signature).should be_true
|
39
|
+
# fields[:owner_signature].should == RenoRB::PDF::Page::SIGNATURE
|
40
|
+
#
|
41
|
+
# fields.has_key?(:submit_button).should be_true
|
42
|
+
# fields[:submit_button].should == RenoRB::PDF::Page::PUSH_BUTTON
|
43
|
+
#
|
44
|
+
# fields.has_key?(:photo).should be_true
|
45
|
+
# fields[:photo].should == RenoRB::PDF::Page::IMAGE
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should find all the valid states for the check box' do
|
49
|
+
page = PDFPage(File.expand_path(File.dirname(__FILE__) + '/../templates/form_template.pdf'))
|
50
|
+
states = page.get_field_states(:newsletter) # Checkbox
|
51
|
+
states.should == ['Yes','Off']
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should find all the valid states for the radio button' do
|
55
|
+
page = PDFPage(File.expand_path(File.dirname(__FILE__) + '/../templates/form_template.pdf'))
|
56
|
+
states = page.get_field_states(:home_owner) # radio button
|
57
|
+
states.should == ['Yes','No','Off'] # Off will not be used but AcroFields returns it anyway.
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should find all the valid states for the list' do
|
61
|
+
page = PDFPage(File.expand_path(File.dirname(__FILE__) + '/../templates/form_template.pdf'))
|
62
|
+
states = page.get_field_states(:car_types) # List
|
63
|
+
states.sort.should == ['Chevy', 'Ford', 'Honda', 'Jeep', 'Toyota'].sort
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'should find all the valid states for the combo box' do
|
67
|
+
page = PDFPage(File.expand_path(File.dirname(__FILE__) + '/../templates/form_template.pdf'))
|
68
|
+
states = page.get_field_states(:sibling_count) # List
|
69
|
+
states.sort.should == ['Zero','One','Two','Three','Four','Five','Six','Seven','Eight','Nine','Ten'].sort
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should fill all fields' do
|
73
|
+
page = PDFPage(File.expand_path(File.dirname(__FILE__) + '/../templates/form_template.pdf'))
|
74
|
+
page.set_text_field(:full_name, 'Anna Hays')
|
75
|
+
page.set_checkbox(:home_owner, 'Yes')
|
76
|
+
page.set_checkbox(:newsletter, 'Yes')
|
77
|
+
page.set_checkbox(:car_types, 'Jeep')
|
78
|
+
page.set_checkbox(:sibling_count, 'One')
|
79
|
+
page.save_to(File.expand_path(File.dirname(__FILE__) + '/../output/form_test.pdf'))
|
80
|
+
File.exist?(File.dirname(__FILE__) + '/../output/form_test.pdf').should be_true
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'should return the buffer without writing to disk' do
|
84
|
+
page = PDFPage(File.expand_path(File.dirname(__FILE__) + '/../templates/certificate_template.pdf'))
|
85
|
+
page.set_text_field(:full_name, 'Wes Hays')
|
86
|
+
pdf_data = page.to_buffer
|
87
|
+
pdf_data.should_not be_blank
|
88
|
+
end
|
89
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'spec'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'ruby-debug'
|
4
|
+
require 'activerecord'
|
5
|
+
|
6
|
+
##################
|
7
|
+
#### <CUSTOM> ####
|
8
|
+
##################
|
9
|
+
# Aliased "lambda" with "doing" so that when checking
|
10
|
+
# whether or not something raises an exception it will
|
11
|
+
# read like other rspec operations. For example:
|
12
|
+
# instead of
|
13
|
+
# lambda { ... }.should_not raise_error
|
14
|
+
# you can have
|
15
|
+
# doing { ... }.should_not raise_error
|
16
|
+
alias :doing :lambda
|
17
|
+
###################
|
18
|
+
#### </CUSTOM> ####
|
19
|
+
###################
|
20
|
+
|
21
|
+
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :dbfile => ":memory:")
|
22
|
+
ActiveRecord::Base.configurations = true
|
23
|
+
|
24
|
+
ActiveRecord::Schema.verbose = false
|
25
|
+
ActiveRecord::Schema.define(:version => 1) do
|
26
|
+
create_table :clients do |t|
|
27
|
+
t.string :first_name
|
28
|
+
t.string :last_name
|
29
|
+
end
|
30
|
+
|
31
|
+
create_table :addresses do |t|
|
32
|
+
t.string :address1
|
33
|
+
t.string :address2
|
34
|
+
t.string :city
|
35
|
+
t.string :state
|
36
|
+
t.string :postal_code
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
41
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
42
|
+
require 'pdf_filler'
|
43
|
+
|
44
|
+
|
45
|
+
module RenoRB
|
46
|
+
module TestData
|
47
|
+
module Addresses
|
48
|
+
def create_corpus!
|
49
|
+
create!(:address1 => '111 AAA St', :address2 => 'Suite 444', :city => 'Reno', :state => 'Nevada', :postal_code => '89506')
|
50
|
+
create!(:address1 => '222 BBB St', :address2 => 'Suite 555', :city => 'Sparks', :state => 'Nevada', :postal_code => '89434')
|
51
|
+
create!(:address1 => '333 CCC St', :address2 => 'Suite 666', :city => 'Fernley', :state => 'Nevada', :postal_code => '89408')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
Spec::Runner.configure do |config|
|
59
|
+
config.before(:each) do
|
60
|
+
class Client < ActiveRecord::Base
|
61
|
+
acts_as_pdf_db_mapper :only => [:first_name, :last_name]
|
62
|
+
has_many :addresses, :dependent => :destroy
|
63
|
+
|
64
|
+
def full_name
|
65
|
+
[self.first_name, self.last_name].join(' ')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class Address < ActiveRecord::Base
|
70
|
+
acts_as_pdf_db_mapper
|
71
|
+
belongs_to :client
|
72
|
+
extend RenoRB::TestData::Addresses
|
73
|
+
end
|
74
|
+
|
75
|
+
class ClientAddress < ActiveRecord::Base
|
76
|
+
set_table_name :addresses
|
77
|
+
acts_as_pdf_db_mapper :only => [:state, :city]
|
78
|
+
end
|
79
|
+
|
80
|
+
class ContactAddress < ActiveRecord::Base
|
81
|
+
set_table_name :addresses
|
82
|
+
acts_as_pdf_db_mapper :except => [:id, :address1, :postal_code]
|
83
|
+
end
|
84
|
+
|
85
|
+
class UserAddress < ActiveRecord::Base
|
86
|
+
set_table_name :addresses
|
87
|
+
acts_as_pdf_db_mapper :include => [{:full_address => :address}]
|
88
|
+
|
89
|
+
def full_address
|
90
|
+
[self.address1, self.address2].join(', ')
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class FamilyAddress < ActiveRecord::Base
|
95
|
+
set_table_name :addresses
|
96
|
+
acts_as_pdf_db_mapper :only_include => [{:full_address => :address}]
|
97
|
+
|
98
|
+
def full_address
|
99
|
+
[self.address1, self.address2].join(', ')
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
Client.destroy_all
|
104
|
+
Address.destroy_all
|
105
|
+
end
|
106
|
+
|
107
|
+
config.after(:each) do
|
108
|
+
Object.send(:remove_const, :Client)
|
109
|
+
Object.send(:remove_const, :Address)
|
110
|
+
end
|
111
|
+
end
|
Binary file
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = 'pdf_filler'
|
8
|
+
#gem.version = '0.1.1' # In version file
|
9
|
+
gem.date = '2009-08-25'
|
10
|
+
|
11
|
+
gem.summary = "A Rails plugin to fill a PDF form using RJB and iText."
|
12
|
+
gem.description = "PDF Filler makes it easy to file your PDFs."
|
13
|
+
|
14
|
+
gem.authors = ['Reno Ruby Group']
|
15
|
+
gem.email = ['renorb@renorb.org']
|
16
|
+
gem.homepage = 'http://wiki.github.com/renorb/pdf_filler'
|
17
|
+
|
18
|
+
gem.has_rdoc = true
|
19
|
+
gem.rdoc_options << '--title' << gem.name << '--main' << 'README.rdoc' << '--line-numbers' << '--inline-source'
|
20
|
+
gem.extra_rdoc_files = ['README.rdoc']
|
21
|
+
|
22
|
+
gem.files = ['LICENSE',
|
23
|
+
'README.rdoc',
|
24
|
+
'Rakefile',
|
25
|
+
'init.rb',
|
26
|
+
'lib/iText-2.1.7.jar',
|
27
|
+
'lib/pdf_filler.rb',
|
28
|
+
'lib/pdf_filler/page.rb',
|
29
|
+
'lib/pdf_filler/book.rb',
|
30
|
+
'lib/pdf_filler/pdf_db_mapper.rb',
|
31
|
+
'lib/pdf_filler/util_methods.rb',
|
32
|
+
'tasks/documentation.rake',
|
33
|
+
'tasks/build_gem.rake',
|
34
|
+
'spec/spec_helper.rb',
|
35
|
+
'spec/lib/pdf_page_spec.rb',
|
36
|
+
'spec/lib/pdf_book_spec.rb',
|
37
|
+
'spec/lib/pdf_db_mapper_spec.rb',
|
38
|
+
'spec/output',
|
39
|
+
'spec/templates/certificate_template.pdf']
|
40
|
+
|
41
|
+
gem.test_files = ['spec/lib/pdf_page_spec.rb',
|
42
|
+
'spec/lib/pdf_book_spec.rb']
|
43
|
+
|
44
|
+
gem.add_dependency 'rjb', '>= 1.1.7'
|
45
|
+
end
|
46
|
+
rescue LoadError
|
47
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
48
|
+
end
|
49
|
+
|
50
|
+
require 'spec/rake/spectask'
|
51
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
52
|
+
spec.libs << 'lib' << 'spec'
|
53
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
54
|
+
end
|
55
|
+
|
56
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
57
|
+
spec.libs << 'lib' << 'spec'
|
58
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
59
|
+
spec.rcov = true
|
60
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
|
4
|
+
desc 'Generate documentation for PDF-Filler.'
|
5
|
+
Rake::RDocTask.new do |rdoc|
|
6
|
+
rdoc.rdoc_dir = 'doc/html'
|
7
|
+
rdoc.title = 'pdf_filler'
|
8
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
9
|
+
rdoc.main = 'README.rdoc'
|
10
|
+
rdoc.rdoc_files.include('LICENSE', 'lib/')
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
begin
|
15
|
+
require 'rcov/rcovtask'
|
16
|
+
Rcov::RcovTask.new do |t|
|
17
|
+
t.test_files = Dir[ "spec/**/*_spec.rb" ]
|
18
|
+
end
|
19
|
+
rescue LoadError
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
|
23
|
+
begin
|
24
|
+
require 'rcov/rcovtask'
|
25
|
+
desc 'Runs spec:rcov and then displays the coverage/index.html file in the browser.'
|
26
|
+
task :rcov_display => [:clobber_rcov, :rcov] do
|
27
|
+
system("open coverage/index.html")
|
28
|
+
end
|
29
|
+
rescue LoadError
|
30
|
+
nil
|
31
|
+
end
|
32
|
+
|
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: renorb-pdf_filler
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Reno Ruby Group
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-08-25 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rjb
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.1.7
|
24
|
+
version:
|
25
|
+
description: PDF Filler makes it easy to file your PDFs.
|
26
|
+
email:
|
27
|
+
- renorb@renorb.org
|
28
|
+
executables: []
|
29
|
+
|
30
|
+
extensions: []
|
31
|
+
|
32
|
+
extra_rdoc_files:
|
33
|
+
- README.rdoc
|
34
|
+
files:
|
35
|
+
- LICENSE
|
36
|
+
- README.rdoc
|
37
|
+
- Rakefile
|
38
|
+
- init.rb
|
39
|
+
- lib/iText-2.1.7.jar
|
40
|
+
- lib/pdf_filler.rb
|
41
|
+
- lib/pdf_filler/book.rb
|
42
|
+
- lib/pdf_filler/page.rb
|
43
|
+
- lib/pdf_filler/pdf_db_mapper.rb
|
44
|
+
- lib/pdf_filler/util_methods.rb
|
45
|
+
- spec/lib/pdf_book_spec.rb
|
46
|
+
- spec/lib/pdf_db_mapper_spec.rb
|
47
|
+
- spec/lib/pdf_page_spec.rb
|
48
|
+
- spec/spec_helper.rb
|
49
|
+
- spec/templates/certificate_template.pdf
|
50
|
+
- tasks/build_gem.rake
|
51
|
+
- tasks/documentation.rake
|
52
|
+
has_rdoc: false
|
53
|
+
homepage: http://wiki.github.com/renorb/pdf_filler
|
54
|
+
post_install_message:
|
55
|
+
rdoc_options:
|
56
|
+
- --charset=UTF-8
|
57
|
+
- --title
|
58
|
+
- pdf_filler
|
59
|
+
- --main
|
60
|
+
- README.rdoc
|
61
|
+
- --line-numbers
|
62
|
+
- --inline-source
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: "0"
|
70
|
+
version:
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: "0"
|
76
|
+
version:
|
77
|
+
requirements: []
|
78
|
+
|
79
|
+
rubyforge_project:
|
80
|
+
rubygems_version: 1.2.0
|
81
|
+
signing_key:
|
82
|
+
specification_version: 3
|
83
|
+
summary: A Rails plugin to fill a PDF form using RJB and iText.
|
84
|
+
test_files:
|
85
|
+
- spec/lib/pdf_page_spec.rb
|
86
|
+
- spec/lib/pdf_book_spec.rb
|