juno-report 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- metadata +5 -41
- data/.gitignore +0 -20
- data/.idea/.name +0 -1
- data/.idea/.rakeTasks +0 -7
- data/.idea/encodings.xml +0 -5
- data/.idea/juno-report.iml +0 -31
- data/.idea/misc.xml +0 -5
- data/.idea/modules.xml +0 -9
- data/.idea/scopes/scope_settings.xml +0 -5
- data/.idea/vcs.xml +0 -7
- data/.idea/workspace.xml +0 -281
- data/.rspec +0 -2
- data/Gemfile +0 -4
- data/Gemfile.lock +0 -52
- data/LICENSE.txt +0 -22
- data/README.md +0 -197
- data/Rakefile +0 -7
- data/juno-report.gemspec +0 -24
- data/lib/juno-report/pdf/behaviors.rb +0 -18
- data/lib/juno-report/pdf.rb +0 -246
- data/lib/juno-report/report_object.rb +0 -9
- data/lib/juno-report/version.rb +0 -3
- data/lib/juno-report.rb +0 -32
- data/report.pdf +0 -153
- data/samples/example.rb +0 -21
- data/samples/report.pdf +0 -972
- data/samples/report.yml +0 -30
- data/spec/data/data1.rb +0 -9
- data/spec/data/rule1.yml +0 -10
- data/spec/default_spec.rb +0 -13
- data/spec/rules_spec.rb +0 -13
- data/spec/spec_helper.rb +0 -11
data/README.md
DELETED
@@ -1,197 +0,0 @@
|
|
1
|
-
# Juno Report
|
2
|
-
|
3
|
-
Cry with Report Generation? Nevermore!
|
4
|
-
|
5
|
-
## Installation
|
6
|
-
|
7
|
-
Add this line to your application's Gemfile:
|
8
|
-
|
9
|
-
gem 'juno-report'
|
10
|
-
|
11
|
-
And then execute:
|
12
|
-
|
13
|
-
$ bundle
|
14
|
-
|
15
|
-
Or install it yourself as:
|
16
|
-
|
17
|
-
$ gem install juno-report
|
18
|
-
|
19
|
-
## Usage
|
20
|
-
|
21
|
-
The generating reports is based on a YAML file with all rules, with the fields and their settings, divided by sections.
|
22
|
-
|
23
|
-
### Body section
|
24
|
-
|
25
|
-
Represents the records which will be iterated to report generating
|
26
|
-
|
27
|
-
```yaml
|
28
|
-
# example.yml
|
29
|
-
body:
|
30
|
-
settings: {posY: 40, height: 25}
|
31
|
-
fields:
|
32
|
-
test_field1: [10]
|
33
|
-
test_field2: [220]
|
34
|
-
test_field3: [430, {column: "Named Test Field 3"}]
|
35
|
-
footer:
|
36
|
-
label_total: [10, {value: "Total"}]
|
37
|
-
totalizer: [220, {behavior: count}]
|
38
|
-
test_field3: [430, {behavior: sum}]
|
39
|
-
```
|
40
|
-
The [body] section ***must*** have three rules:
|
41
|
-
|
42
|
-
* `settings`: Defines some configurations for body, like their height and ypos.
|
43
|
-
* `fields`: Describes each field of record to be iterated.
|
44
|
-
* `footer`: Drawn at the end of all printed records and calculates fields according behavior parameter.
|
45
|
-
|
46
|
-
Each of these rules receives a array, where the first position is an integer representing the field horizontal position and
|
47
|
-
the second position is a hash with some configurations.
|
48
|
-
|
49
|
-
|
50
|
-
##### Settings
|
51
|
-
|
52
|
-
* `height`: Set the of each row at report [Integer].
|
53
|
-
* `posY`: Relative vertical position of last row at report [Integer].
|
54
|
-
* `groups`: Describes which groups will be printed (More bellow) [Array].
|
55
|
-
|
56
|
-
##### Fields
|
57
|
-
|
58
|
-
* `size`: Font size of the field [Integer].
|
59
|
-
* `align`: Defines the text alignment for each value [left|center|right].
|
60
|
-
* `font`: Supports all font type provided by Prawn gem (See more in http://rubydoc.info/gems/prawn/Prawn/Font/AFM).
|
61
|
-
* `style`: Stylistic variations of a font [bold|italic].
|
62
|
-
* `value`: Fixed text to be printed [string].
|
63
|
-
* `column`: The header are "humanized" automatically, but you can set other value manually [string].
|
64
|
-
|
65
|
-
##### Footer
|
66
|
-
|
67
|
-
* `behavior`: Specify a function to be performed, sending as parameter the fieldname value [string].
|
68
|
-
* `label`: Preppends a text to fieldname value specified [string].
|
69
|
-
* `value`: Fixed text to be printed (fieldname value will be ignored) [string].
|
70
|
-
|
71
|
-
With theses configurations already is possible generate a basic report, without groups feature.
|
72
|
-
For this we need call the generate method on JunoReport module:
|
73
|
-
|
74
|
-
```ruby
|
75
|
-
# test.rb
|
76
|
-
require 'juno-report'
|
77
|
-
|
78
|
-
data = [
|
79
|
-
{:test_field1 => 'Test Value 1', :test_field2 => "Test Value 2", :test_field3 => 50},
|
80
|
-
{:test_field1 => 'Test Value 1', :test_field2 => "Test Value 2", :test_field3 => 7},
|
81
|
-
{:test_field1 => 'Test Value 1', :test_field2 => "Test Value 2", :test_field3 => 10},
|
82
|
-
{:test_field1 => 'Test Value 1', :test_field2 => "Test Value 2", :test_field3 => 5},
|
83
|
-
{:test_field1 => 'Test Value 1', :test_field2 => "Test Value 2", :test_field3 => 2},
|
84
|
-
{:test_field1 => 'Test Value 1', :test_field2 => "Test Value 2", :test_field3 => 4},
|
85
|
-
{:test_field1 => 'Test Value 1', :test_field2 => "Test Value 2", :test_field3 => 24}
|
86
|
-
]
|
87
|
-
|
88
|
-
JunoReport::generate(data, :report => 'example')
|
89
|
-
```
|
90
|
-
|
91
|
-
The first parameter must be a set of hash or objects which represent the report data. And the second parameter is a hash
|
92
|
-
with the report settings, that can be:
|
93
|
-
|
94
|
-
* `report`: The source of all rules. Must be a YAML file [string].
|
95
|
-
* `type`: Specify if the report will be writed on the disc or returned to the caller such a stream [:file|:stream]
|
96
|
-
* `filename`: Defines the report name which will be writed on disc. If not specified, the default name is "report.pdf" [string].
|
97
|
-
|
98
|
-
### Page section
|
99
|
-
|
100
|
-
You may want to print a title every time that a page is created. You simply insert a [page] section.
|
101
|
-
|
102
|
-
```yaml
|
103
|
-
# example.yml
|
104
|
-
page:
|
105
|
-
fields:
|
106
|
-
title1: [260, {size: 24, align: center, value: "Test Report"}]
|
107
|
-
subtitle1: [260, {size: 20, posY: 20, align: center, value: "Generated by Juno Report"}]
|
108
|
-
body:
|
109
|
-
settings: {posY: 40, height: 25}
|
110
|
-
fields:
|
111
|
-
test_field1: [10]
|
112
|
-
test_field2: [220]
|
113
|
-
test_field3: [430, {column: "Named Test Field 3"}]
|
114
|
-
footer:
|
115
|
-
label_total: [10, {value: "Total"}]
|
116
|
-
totalizer: [220, {behavior: count}]
|
117
|
-
test_field3: [430, {behavior: sum}]
|
118
|
-
```
|
119
|
-
|
120
|
-
### Groups section
|
121
|
-
|
122
|
-
For each item in groups parameter at body section you should create a section with same name.
|
123
|
-
This section represents the header configurations to every time that the group is printed and behaves like [body] section.
|
124
|
-
|
125
|
-
```yaml
|
126
|
-
# example.yml
|
127
|
-
page:
|
128
|
-
fields:
|
129
|
-
title1: [260, {size: 24, align: center, value: "Test Report"}]
|
130
|
-
subtitle1: [260, {size: 20, posY: 20, align: center, value: "Generated by Juno Report"}]
|
131
|
-
body:
|
132
|
-
settings: {posY: 40, height: 30, groups: [group_field1, group_field2]}
|
133
|
-
fields:
|
134
|
-
test_field1: [10]
|
135
|
-
test_field2: [220]
|
136
|
-
test_field3: [420, {column: "Named Test Field 3"}]
|
137
|
-
footer:
|
138
|
-
label_total: [10, {value: "Total"}]
|
139
|
-
totalizer1: [220, {behavior: count}]
|
140
|
-
test_field3: [420, {behavior: sum}]
|
141
|
-
group_field1:
|
142
|
-
settings: {posY: 30, height: 10}
|
143
|
-
fields:
|
144
|
-
group_field1: [10, size: 25]
|
145
|
-
footer:
|
146
|
-
group_field1: [10, {label: "Total "}]
|
147
|
-
totalizer1: [220, {behavior: count}]
|
148
|
-
test_field3: [420, {behavior: sum}]
|
149
|
-
group_field2:
|
150
|
-
settings: {posY: 30, height: 25}
|
151
|
-
fields:
|
152
|
-
group_field2: [10, size: 17]
|
153
|
-
footer:
|
154
|
-
group_field2: [10, {label: "Total "}]
|
155
|
-
totalizer1: [220, {behavior: count}]
|
156
|
-
test_field3: [420, {behavior: sum}]
|
157
|
-
```
|
158
|
-
|
159
|
-
Every time that a "group field" value changes, the group will be printed.
|
160
|
-
|
161
|
-
```ruby
|
162
|
-
# test.rb
|
163
|
-
require 'juno-report'
|
164
|
-
|
165
|
-
data = [
|
166
|
-
{:test_field1 => 'Test Value 1', :test_field2 => "Test Value 1", :test_field3 => 50, :group_field1 => 'Group 1', :group_field2 => 'Subgroup 1'},
|
167
|
-
{:test_field1 => 'Test Value 2', :test_field2 => "Test Value 2", :test_field3 => 16, :group_field1 => 'Group 1', :group_field2 => 'Subgroup 1'},
|
168
|
-
{:test_field1 => 'Test Value 5', :test_field2 => "Test Value 3", :test_field3 => 7, :group_field1 => 'Group 1', :group_field2 => 'Subgroup 1'},
|
169
|
-
{:test_field1 => 'Test Value 3', :test_field2 => "Test Value 9", :test_field3 => 10, :group_field1 => 'Group 1', :group_field2 => 'Subgroup 2'},
|
170
|
-
{:test_field1 => 'Test Value 3', :test_field2 => "Test Value 2", :test_field3 => 4, :group_field1 => 'Group 1', :group_field2 => 'Subgroup 2'},
|
171
|
-
{:test_field1 => 'Test Value 9', :test_field2 => "Test Value 4", :test_field3 => 10, :group_field1 => 'Group 1', :group_field2 => 'Subgroup 2'},
|
172
|
-
{:test_field1 => 'Test Value 7', :test_field2 => "Test Value 5", :test_field3 => 5, :group_field1 => 'Group 1', :group_field2 => 'Subgroup 3'},
|
173
|
-
{:test_field1 => 'Test Value 3', :test_field2 => "Test Value 5", :test_field3 => 2, :group_field1 => 'Group 1', :group_field2 => 'Subgroup 3'},
|
174
|
-
{:test_field1 => 'Test Value 3', :test_field2 => "Test Value 2", :test_field3 => 27, :group_field1 => 'Group 2', :group_field2 => 'Subgroup 1'},
|
175
|
-
{:test_field1 => 'Test Value 3', :test_field2 => "Test Value 5", :test_field3 => 2, :group_field1 => 'Group 2', :group_field2 => 'Subgroup 1'},
|
176
|
-
{:test_field1 => 'Test Value 0', :test_field2 => "Test Value 4", :test_field3 => 13, :group_field1 => 'Group 2', :group_field2 => 'Subgroup 1'},
|
177
|
-
{:test_field1 => 'Test Value 4', :test_field2 => "Test Value 7", :test_field3 => 7, :group_field1 => 'Group 2', :group_field2 => 'Subgroup 1'},
|
178
|
-
{:test_field1 => 'Test Value 1', :test_field2 => "Test Value 3", :test_field3 => 28, :group_field1 => 'Group 2', :group_field2 => 'Subgroup 1'},
|
179
|
-
{:test_field1 => 'Test Value 4', :test_field2 => "Test Value 5", :test_field3 => 4, :group_field1 => 'Group 2', :group_field2 => 'Subgroup 2'},
|
180
|
-
{:test_field1 => 'Test Value 5', :test_field2 => "Test Value 6", :test_field3 => 24, :group_field1 => 'Group 2', :group_field2 => 'Subgroup 2'}
|
181
|
-
]
|
182
|
-
|
183
|
-
JunoReport::generate(data, :report => 'example', :filename => 'juno-report.pdf')
|
184
|
-
```
|
185
|
-
|
186
|
-
## Contributors
|
187
|
-
|
188
|
-
2. Edson Júnior (http://github.com/ebfjunior)
|
189
|
-
|
190
|
-
## Contributing
|
191
|
-
|
192
|
-
1. Fork it
|
193
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
194
|
-
3. Commit your changes (`git commit -am 'Added some feature'`)
|
195
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
196
|
-
5. Create new Pull Request
|
197
|
-
|
data/Rakefile
DELETED
data/juno-report.gemspec
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
require 'juno-report/version'
|
4
|
-
|
5
|
-
Gem::Specification.new do |gem|
|
6
|
-
gem.name = "juno-report"
|
7
|
-
gem.version = JunoReport::VERSION
|
8
|
-
gem.platform = Gem::Platform::RUBY
|
9
|
-
gem.authors = ["Edson Júnior"]
|
10
|
-
gem.email = ["ejunior.batista@gmail.com"]
|
11
|
-
gem.description = "A simple, but efficient, report genarator yaml based"
|
12
|
-
gem.summary = "Juno Reports generates reports with the minimum configuration and effort"
|
13
|
-
gem.homepage = "http://github.com/ebfjunior/juno-report"
|
14
|
-
|
15
|
-
gem.files = `git ls-files`.split("\n")
|
16
|
-
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
17
|
-
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
-
gem.require_paths = ["lib"]
|
19
|
-
|
20
|
-
gem.add_dependency "prawml"
|
21
|
-
|
22
|
-
gem.add_development_dependency 'rake'
|
23
|
-
gem.add_development_dependency 'rspec'
|
24
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
module JunoReport
|
2
|
-
module Pdf
|
3
|
-
module Behaviors
|
4
|
-
def self.sum old_value, new_value
|
5
|
-
value = (old_value.to_f + new_value.to_f).to_s
|
6
|
-
(/^[0-9]+(?=\.)/.match value).nil? ? value : value[/^[0-9]+(?=\.)/]
|
7
|
-
end
|
8
|
-
|
9
|
-
def self.substract old_value, new_value
|
10
|
-
old_value.to_f - new_value.to_f
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.count old_value, new_value = nil
|
14
|
-
old_value.to_i + 1
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
data/lib/juno-report/pdf.rb
DELETED
@@ -1,246 +0,0 @@
|
|
1
|
-
module JunoReport
|
2
|
-
module Pdf
|
3
|
-
|
4
|
-
#Responsible for generate a report, based on rules passed as parameter in Juno::Report::generate.
|
5
|
-
#Juno Reports has support groups, just by especifying them at the rules file.
|
6
|
-
#Receives a collection as parameter, which should be a Array of records of the report.
|
7
|
-
def generate(collection)
|
8
|
-
@defaults = {
|
9
|
-
:style => :normal,
|
10
|
-
:size => 12,
|
11
|
-
:align => :left,
|
12
|
-
:format => false,
|
13
|
-
:font => 'Times-Roman',
|
14
|
-
:type => :text,
|
15
|
-
:color => '000000',
|
16
|
-
:fixed => false
|
17
|
-
}
|
18
|
-
|
19
|
-
get_sections
|
20
|
-
set_pos_y
|
21
|
-
|
22
|
-
@defaults.merge!(@sections[:defaults]) unless @sections[:defaults].nil?
|
23
|
-
|
24
|
-
collection = [collection] unless collection.is_a?(Array) or collection.is_a?(ActiveRecord::Relation)
|
25
|
-
print_section :page unless @sections[:page].nil?
|
26
|
-
set_pos_y (@sections[:body][:settings][:posY] || 0)
|
27
|
-
@current_groups = {}
|
28
|
-
@footers = {}
|
29
|
-
@count = 0
|
30
|
-
|
31
|
-
unless @sections[:groups].empty?
|
32
|
-
reset_groups_values
|
33
|
-
else
|
34
|
-
draw_columns
|
35
|
-
end
|
36
|
-
|
37
|
-
initialize_footer_values
|
38
|
-
can_print_footer = false
|
39
|
-
|
40
|
-
collection.each do |record|
|
41
|
-
@record = record.is_a?(Hash) ? ReportObject.new(record) : record #Convert the hash on a Object to futurely extend a module
|
42
|
-
|
43
|
-
headers_to_print, headers_height = calculate_header
|
44
|
-
|
45
|
-
unless headers_to_print.empty?
|
46
|
-
@count = 0
|
47
|
-
draw_footer headers_to_print, @sections[:groups] if can_print_footer
|
48
|
-
if @posY - headers_height < 2*@sections[:body][:settings][:height]
|
49
|
-
new_page
|
50
|
-
else
|
51
|
-
headers_to_print.each { |group| print_section group, @record, true }
|
52
|
-
draw_columns
|
53
|
-
end
|
54
|
-
end
|
55
|
-
can_print_footer = true
|
56
|
-
|
57
|
-
update_footer_values
|
58
|
-
print_section :body, @record
|
59
|
-
@count += 1
|
60
|
-
end
|
61
|
-
|
62
|
-
draw_footer(@sections[:body][:settings][:groups].collect {|group| group.to_sym}, @sections[:groups]) if has_groups?
|
63
|
-
draw_footer [:body], @sections
|
64
|
-
|
65
|
-
@pdf
|
66
|
-
end
|
67
|
-
|
68
|
-
protected
|
69
|
-
|
70
|
-
#Creates a new page, restarting the vertical position of the pointer.
|
71
|
-
#Print the whole header for the current groups and the columns of the report.
|
72
|
-
def new_page
|
73
|
-
@pdf.start_new_page
|
74
|
-
set_pos_y
|
75
|
-
print_section :page unless @sections[:page].nil?
|
76
|
-
set_pos_y (@sections[:body][:settings][:posY] || 0)
|
77
|
-
@current_groups.each do |field, value|
|
78
|
-
print_section field.to_sym, @record, true
|
79
|
-
end
|
80
|
-
draw_columns
|
81
|
-
end
|
82
|
-
|
83
|
-
#Generic function to print a section like :body, :page or the group sections.
|
84
|
-
def print_section(section_name, values = nil, group = false)
|
85
|
-
section = !group ? @sections[section_name] : @sections[:groups][section_name]
|
86
|
-
set_pos_y(section[:settings][:posY] || 0) unless section_name.eql?(:body) || section[:settings].nil?
|
87
|
-
new_page if @posY < 30
|
88
|
-
|
89
|
-
if section_name.eql? :body and @count % 2 != 0
|
90
|
-
@pdf.fill_color "F7F7F7"
|
91
|
-
width = @options[:page_layout] == :portrait ? 530 : 770
|
92
|
-
@pdf.fill_rectangle [0, @posY+(section[:settings][:height]/2)], width, section[:settings][:height]
|
93
|
-
end
|
94
|
-
|
95
|
-
section[:fields].each do |field, settings|
|
96
|
-
symbolize! settings[1] unless settings[1].nil?
|
97
|
-
set_pos_y settings[1][:posY] unless settings[1].nil? || settings[1][:posY].nil?
|
98
|
-
settings = [settings[0], @posY, (@defaults.merge (settings[1] || { }))]
|
99
|
-
settings[2][:style] = settings[2][:style].to_sym
|
100
|
-
set_options settings[2]
|
101
|
-
|
102
|
-
value = settings[2][:value].nil? ? (values.respond_to?(field) ? values.send(field) : "") : settings[2][:value]
|
103
|
-
string_cut = settings[2][:cut].nil? ? value : value[0..settings[2][:cut]]
|
104
|
-
draw_text string_cut, settings
|
105
|
-
end
|
106
|
-
set_pos_y (section[:settings][:height]) unless section[:settings].nil? || section[:settings][:height].nil?
|
107
|
-
end
|
108
|
-
|
109
|
-
#Print a horizontal line with the whole width of the page.
|
110
|
-
def draw_line(y)
|
111
|
-
width = @options[:page_layout] == :portrait ? 530 : 770
|
112
|
-
@pdf.stroke { @pdf.horizontal_line 0, width, :at => y }
|
113
|
-
end
|
114
|
-
|
115
|
-
#Update the pointer vertical position to the specified value or 'zero' if the parameter is nil.
|
116
|
-
#Obs: Prawn pointer is decrescent, in other words, the left-top corner position is (0, 750). For
|
117
|
-
#semantic purposes, we set the same corner as (0, 0).
|
118
|
-
def set_pos_y(posY = nil)
|
119
|
-
height = @options[:page_layout] == :portrait ? 750 : 520
|
120
|
-
@posY = height if @posY.nil?
|
121
|
-
@posY = posY.nil? ? height : @posY - posY
|
122
|
-
end
|
123
|
-
|
124
|
-
#Convert to symbol all hash keys, recursively.
|
125
|
-
def symbolize! hash
|
126
|
-
hash.symbolize_keys!
|
127
|
-
hash.values.select{|v| v.is_a? Hash}.each{|h| symbolize!(h)}
|
128
|
-
end
|
129
|
-
|
130
|
-
#Convert the structure of the rules to facilitate the generating proccess.
|
131
|
-
def get_sections
|
132
|
-
symbolize! @rules
|
133
|
-
raise "[body] section on YAML file is needed to generate the report." if @rules[:body].nil?
|
134
|
-
@sections = {:page => @rules[:page], :body => @rules[:body], :defaults => @rules[:defaults], :groups => {}}
|
135
|
-
@sections[:body][:settings][:groups].each { |group| @sections[:groups][group.to_sym] = @rules[group.to_sym] } if has_groups?
|
136
|
-
end
|
137
|
-
|
138
|
-
#@current_groups storages the value for all groups. When a value is changed, the header is printed.
|
139
|
-
#This function set nil value for every item in @current_groups if the parameter is not passed. Otherwise,
|
140
|
-
#only the forward groups will be cleaned to avoid conflict problems with others groups.
|
141
|
-
def reset_groups_values current_group = nil
|
142
|
-
groups = @sections[:body][:settings][:groups]
|
143
|
-
groups.each_with_index do |group, idx|
|
144
|
-
@current_groups[group] = nil if current_group.nil? || groups.index(current_group.to_s) <= idx
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
|
149
|
-
#Calculates the headers which must be printed before print the current record.
|
150
|
-
#The function also returns the current header height to create a new page if the
|
151
|
-
#page remaining space is smaller than (header + a record height)
|
152
|
-
def calculate_header
|
153
|
-
headers = []
|
154
|
-
height = 0
|
155
|
-
@current_groups.each do |field, value|
|
156
|
-
if @record.send(field) != value
|
157
|
-
reset_groups_values field
|
158
|
-
|
159
|
-
headers << field.to_sym
|
160
|
-
height += @sections[:groups][field.to_sym][:settings][:height] + @sections[:groups][field.to_sym][:settings][:posY]
|
161
|
-
|
162
|
-
@current_groups[field] = @record.send(field)
|
163
|
-
end
|
164
|
-
end unless @current_groups.empty?
|
165
|
-
[headers, height]
|
166
|
-
end
|
167
|
-
|
168
|
-
#Create a structure to calculate the footer values for all groups. Appends the footer body to total values too.
|
169
|
-
def initialize_footer_values
|
170
|
-
@sections[:body][:settings][:groups].each do |group|
|
171
|
-
current_footer = {}
|
172
|
-
@sections[:groups][group.to_sym][:footer].each { |field, settings| current_footer[field] = nil } unless @sections[:groups][group.to_sym][:footer].nil?
|
173
|
-
@footers[group.to_sym] = current_footer unless current_footer.empty?
|
174
|
-
end if has_groups?
|
175
|
-
raise "The report must have at least a footer on body section" if @sections[:body][:footer].nil?
|
176
|
-
current_footer = {}
|
177
|
-
@sections[:body][:footer].each { |field, settings| current_footer[field] = nil }
|
178
|
-
@footers[:body] = current_footer unless current_footer.empty?
|
179
|
-
end
|
180
|
-
|
181
|
-
#Call the function that calculates the footer values for all groups and the total body footer, with
|
182
|
-
#different source for each
|
183
|
-
def update_footer_values
|
184
|
-
@sections[:body][:settings][:groups].reverse_each do |group|
|
185
|
-
calculate_footer_values group, @sections[:groups][group.to_sym][:footer]
|
186
|
-
end if has_groups?
|
187
|
-
calculate_footer_values :body, @sections[:body][:footer]
|
188
|
-
end
|
189
|
-
|
190
|
-
#Returns the values to the group passed as parameter. If :behavior setting is used, so a
|
191
|
-
#function in [lib/pdf/behaviors.rb] calculates the value of current field, else the report
|
192
|
-
#method is called
|
193
|
-
def calculate_footer_values group, source
|
194
|
-
@footers[group.to_sym].each do |field, value|
|
195
|
-
footer_rule = source[field]
|
196
|
-
symbolize! footer_rule[1]
|
197
|
-
unless footer_rule[1][:behavior].nil?
|
198
|
-
@footers[group.to_sym][field] = JunoReport::Pdf::Behaviors.send footer_rule[1][:behavior].to_sym, value, (@record.respond_to?(field) ? @record.send(field) : nil)
|
199
|
-
else
|
200
|
-
@footers[group.to_sym][field] = footer_rule[1][:value] || (footer_rule[1][:label].to_s + @record.send(field))
|
201
|
-
end unless @footers[group.to_sym].nil? || footer_rule[1].nil?
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
#Print the footers according to the groups and source specified
|
206
|
-
def draw_footer footers_to_print, source
|
207
|
-
footers_to_print.reverse_each do |group|
|
208
|
-
draw_line(@posY + @sections[:body][:settings][:height]/2)
|
209
|
-
source[group][:footer].each do |field, settings|
|
210
|
-
settings = [settings[0], @posY, (@defaults.merge (settings[1] || { }).symbolize_keys!)]
|
211
|
-
settings[2][:style] = settings[2][:style].to_sym
|
212
|
-
set_options settings[2]
|
213
|
-
draw_text @footers[group][field], settings
|
214
|
-
end
|
215
|
-
draw_line(@posY - @sections[:body][:settings][:height]/4)
|
216
|
-
set_pos_y @sections[:body][:settings][:height]
|
217
|
-
|
218
|
-
reset_footer group
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
#Resets the footer to next groups
|
223
|
-
def reset_footer(group); @footers[group].each { |field, value| @footers[group][field] = nil }; end
|
224
|
-
|
225
|
-
#Based on the Key names of the :body section at the rules, the function draw columns with
|
226
|
-
#baselines on the top and bottom of the header.
|
227
|
-
def draw_columns
|
228
|
-
@sections[:body][:fields].each do |field, settings|
|
229
|
-
settings = [settings[0], @posY, (@defaults.merge (settings[1] || { }).symbolize_keys!)]
|
230
|
-
settings[2][:style] = settings[2][:style].to_sym
|
231
|
-
set_options settings[2]
|
232
|
-
draw_line(@posY + @sections[:body][:settings][:height]/2)
|
233
|
-
field = settings[2][:column] || field.to_s.split('_').inject('') do |str, part|
|
234
|
-
str << part.camelize << " "
|
235
|
-
end
|
236
|
-
draw_text field, settings
|
237
|
-
end
|
238
|
-
draw_line(@posY - @sections[:body][:settings][:height]/2)
|
239
|
-
set_pos_y @sections[:body][:settings][:height]
|
240
|
-
end
|
241
|
-
|
242
|
-
def has_groups?
|
243
|
-
!@sections[:body][:settings][:groups].nil?
|
244
|
-
end
|
245
|
-
end
|
246
|
-
end
|
@@ -1,9 +0,0 @@
|
|
1
|
-
class ReportObject
|
2
|
-
def initialize(hash)
|
3
|
-
hash.each do |k,v|
|
4
|
-
self.instance_variable_set("@#{k}", v)
|
5
|
-
self.class.send(:define_method, k, proc{self.instance_variable_get("@#{k}")})
|
6
|
-
self.class.send(:define_method, "#{k}=", proc{|v| self.instance_variable_set("@#{k}", v)})
|
7
|
-
end
|
8
|
-
end
|
9
|
-
end
|
data/lib/juno-report/version.rb
DELETED
data/lib/juno-report.rb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
require "juno-report/version"
|
2
|
-
require "juno-report/pdf"
|
3
|
-
require "juno-report/pdf/behaviors"
|
4
|
-
require "prawml"
|
5
|
-
|
6
|
-
module JunoReport
|
7
|
-
autoload :ReportObject, 'juno-report/report_object'
|
8
|
-
|
9
|
-
def self.generate(collection, options)
|
10
|
-
rules = (File.open "#{options[:report]}.yml").read
|
11
|
-
|
12
|
-
defaults = {
|
13
|
-
:page_layout => :portrait
|
14
|
-
}
|
15
|
-
|
16
|
-
pdf = Prawml::PDF.new rules, defaults.merge(options)
|
17
|
-
|
18
|
-
pdf.extend JunoReport::Pdf
|
19
|
-
report = pdf.generate(collection)
|
20
|
-
|
21
|
-
options[:type] ||= :file
|
22
|
-
|
23
|
-
if options[:type].eql? :file
|
24
|
-
report.render_file (options[:filename] || "report.pdf")
|
25
|
-
elsif options[:type].eql? :stream
|
26
|
-
return report.render
|
27
|
-
else
|
28
|
-
raise "Type options must be :file or :stream."
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
32
|
-
end
|
data/report.pdf
DELETED
@@ -1,153 +0,0 @@
|
|
1
|
-
%PDF-1.3
|
2
|
-
%����
|
3
|
-
1 0 obj
|
4
|
-
<< /Creator <feff0050007200610077006e>
|
5
|
-
/Producer <feff0050007200610077006e>
|
6
|
-
>>
|
7
|
-
endobj
|
8
|
-
2 0 obj
|
9
|
-
<< /Type /Catalog
|
10
|
-
/Pages 3 0 R
|
11
|
-
>>
|
12
|
-
endobj
|
13
|
-
3 0 obj
|
14
|
-
<< /Type /Pages
|
15
|
-
/Count 1
|
16
|
-
/Kids [5 0 R]
|
17
|
-
>>
|
18
|
-
endobj
|
19
|
-
4 0 obj
|
20
|
-
<< /Length 926
|
21
|
-
>>
|
22
|
-
stream
|
23
|
-
q
|
24
|
-
/DeviceRGB cs
|
25
|
-
0.000 0.000 0.000 scn
|
26
|
-
36.000 758.000 m
|
27
|
-
566.000 758.000 l
|
28
|
-
S
|
29
|
-
|
30
|
-
BT
|
31
|
-
46 746.0 Td
|
32
|
-
/F1.0 12 Tf
|
33
|
-
[<54> 70 <657374204669656c643120>] TJ
|
34
|
-
ET
|
35
|
-
|
36
|
-
0.000 0.000 0.000 scn
|
37
|
-
36.000 758.000 m
|
38
|
-
566.000 758.000 l
|
39
|
-
S
|
40
|
-
|
41
|
-
BT
|
42
|
-
256 746.0 Td
|
43
|
-
/F1.0 12 Tf
|
44
|
-
[<54> 70 <657374204669656c643220>] TJ
|
45
|
-
ET
|
46
|
-
|
47
|
-
0.000 0.000 0.000 scn
|
48
|
-
36.000 758.000 m
|
49
|
-
566.000 758.000 l
|
50
|
-
S
|
51
|
-
|
52
|
-
BT
|
53
|
-
466 746.0 Td
|
54
|
-
/F1.0 12 Tf
|
55
|
-
[<4e616d65642054> 70 <657374204669656c642033>] TJ
|
56
|
-
ET
|
57
|
-
|
58
|
-
36.000 734.000 m
|
59
|
-
566.000 734.000 l
|
60
|
-
S
|
61
|
-
0.000 0.000 0.000 scn
|
62
|
-
|
63
|
-
BT
|
64
|
-
46 721.0 Td
|
65
|
-
/F1.0 12 Tf
|
66
|
-
[<>] TJ
|
67
|
-
ET
|
68
|
-
|
69
|
-
0.000 0.000 0.000 scn
|
70
|
-
|
71
|
-
BT
|
72
|
-
256 721.0 Td
|
73
|
-
/F1.0 12 Tf
|
74
|
-
[<>] TJ
|
75
|
-
ET
|
76
|
-
|
77
|
-
0.000 0.000 0.000 scn
|
78
|
-
|
79
|
-
BT
|
80
|
-
466 721.0 Td
|
81
|
-
/F1.0 12 Tf
|
82
|
-
[<>] TJ
|
83
|
-
ET
|
84
|
-
|
85
|
-
36.000 708.000 m
|
86
|
-
566.000 708.000 l
|
87
|
-
S
|
88
|
-
0.000 0.000 0.000 scn
|
89
|
-
|
90
|
-
BT
|
91
|
-
46 696.0 Td
|
92
|
-
/F1.0 12 Tf
|
93
|
-
[<54> 80 <6f74616c>] TJ
|
94
|
-
ET
|
95
|
-
|
96
|
-
0.000 0.000 0.000 scn
|
97
|
-
|
98
|
-
BT
|
99
|
-
256 696.0 Td
|
100
|
-
/F1.0 12 Tf
|
101
|
-
[<31>] TJ
|
102
|
-
ET
|
103
|
-
|
104
|
-
0.000 0.000 0.000 scn
|
105
|
-
|
106
|
-
BT
|
107
|
-
466 696.0 Td
|
108
|
-
/F1.0 12 Tf
|
109
|
-
[<30>] TJ
|
110
|
-
ET
|
111
|
-
|
112
|
-
36.000 690.000 m
|
113
|
-
566.000 690.000 l
|
114
|
-
S
|
115
|
-
Q
|
116
|
-
|
117
|
-
endstream
|
118
|
-
endobj
|
119
|
-
5 0 obj
|
120
|
-
<< /Type /Page
|
121
|
-
/Parent 3 0 R
|
122
|
-
/MediaBox [0 0 595.28 841.89]
|
123
|
-
/Contents 4 0 R
|
124
|
-
/Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
|
125
|
-
/Font << /F1.0 6 0 R
|
126
|
-
>>
|
127
|
-
>>
|
128
|
-
>>
|
129
|
-
endobj
|
130
|
-
6 0 obj
|
131
|
-
<< /Type /Font
|
132
|
-
/Subtype /Type1
|
133
|
-
/BaseFont /Times-Roman
|
134
|
-
/Encoding /WinAnsiEncoding
|
135
|
-
>>
|
136
|
-
endobj
|
137
|
-
xref
|
138
|
-
0 7
|
139
|
-
0000000000 65535 f
|
140
|
-
0000000015 00000 n
|
141
|
-
0000000109 00000 n
|
142
|
-
0000000158 00000 n
|
143
|
-
0000000215 00000 n
|
144
|
-
0000001192 00000 n
|
145
|
-
0000001372 00000 n
|
146
|
-
trailer
|
147
|
-
<< /Size 7
|
148
|
-
/Root 2 0 R
|
149
|
-
/Info 1 0 R
|
150
|
-
>>
|
151
|
-
startxref
|
152
|
-
1471
|
153
|
-
%%EOF
|