ruport 1.7.1 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +38 -0
- data/HACKING +1 -17
- data/{README.rdoc → README.md} +30 -38
- data/Rakefile +0 -10
- data/examples/row_renderer.rb +1 -1
- data/examples/simple_pdf_lines.rb +1 -1
- data/examples/trac_ticket_status.rb +1 -1
- data/lib/ruport/controller.rb +1 -1
- data/lib/ruport/data/grouping.rb +7 -7
- data/lib/ruport/data/record.rb +4 -4
- data/lib/ruport/data/table.rb +9 -9
- data/lib/ruport/formatter/csv.rb +1 -1
- data/lib/ruport/formatter/markdown.rb +105 -0
- data/lib/ruport/formatter/prawn_pdf.rb +96 -9
- data/lib/ruport/formatter/text.rb +1 -1
- data/lib/ruport/formatter.rb +1 -2
- data/lib/ruport/version.rb +1 -1
- data/lib/ruport.rb +7 -11
- data/test/controller_test.rb +107 -109
- data/test/csv_formatter_test.rb +21 -21
- data/test/data_feeder_test.rb +39 -39
- data/test/expected_outputs/prawn_pdf_formatter/pdf_basic.pdf.test +265 -0
- data/test/grouping_test.rb +74 -74
- data/test/helpers.rb +16 -5
- data/test/html_formatter_test.rb +22 -22
- data/test/markdown_formatter_test.rb +142 -0
- data/test/prawn_pdf_formatter_test.rb +108 -0
- data/test/record_test.rb +82 -82
- data/test/table_pivot_test.rb +9 -2
- data/test/table_test.rb +33 -40
- data/test/template_test.rb +12 -12
- data/test/text_formatter_test.rb +34 -34
- data/util/bench/data/table/bench_column_manip.rb +0 -1
- data/util/bench/data/table/bench_dup.rb +0 -1
- data/util/bench/data/table/bench_init.rb +0 -1
- data/util/bench/data/table/bench_manip.rb +0 -1
- data/util/bench/formatter/bench_csv.rb +0 -1
- data/util/bench/formatter/bench_html.rb +0 -1
- data/util/bench/formatter/bench_pdf.rb +0 -1
- data/util/bench/formatter/bench_text.rb +0 -1
- metadata +30 -29
- data/lib/ruport/formatter/pdf.rb +0 -589
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b8b980ae054fa6d3d42e224431277d3deb471aa2e7132ea144bdb63bff3b3642
|
4
|
+
data.tar.gz: 9b5784e616ce0cbce9e218995cb7c3b36eb625cc18a75eea8642092713a391c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5ecded8ff524e85d5c9a5bb6312b7bb50cdd5fa0f74540059c4c41c50d9b4cd3c679d6c176dc0a19564eca53590b77374ef00fe2a9afd9a742f0e35b0b88c79c
|
7
|
+
data.tar.gz: 5045f9a47bee0f414ff26222784ce782f2d01329f7f8448196ba6c91974e160fdfcb1d9fdc95318db4246fc67f0f16804e1a965b2856758bc66431b5c17502c9
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# Changelog
|
2
|
+
All notable changes to this project will be documented in this file.
|
3
|
+
|
4
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
5
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
6
|
+
|
7
|
+
## [Unreleased] - undecided
|
8
|
+
|
9
|
+
## [1.8.0] - 2022-09-20
|
10
|
+
|
11
|
+
### Added
|
12
|
+
|
13
|
+
- Markdown formatter [#54](https://github.com/ruport/ruport/pull/54)
|
14
|
+
- Ruby 3.0 support
|
15
|
+
|
16
|
+
### Changed
|
17
|
+
|
18
|
+
- Reduced allocations to improve performance [#34](https://github.com/ruport/ruport/pull/34)
|
19
|
+
- Update Prawn version to 2.4.0 [#44](https://github.com/ruport/ruport/pull/44) [#57](https://github.com/ruport/ruport/pull/57) [#64](https://github.com/ruport/ruport/pull/64)
|
20
|
+
|
21
|
+
## [1.7.1] - 2017-05-02
|
22
|
+
|
23
|
+
### Changed
|
24
|
+
|
25
|
+
- Improved errors when missing gems.
|
26
|
+
- Added ruby 1.9 support
|
27
|
+
- Removed dependency on `fastercsv` gem
|
28
|
+
|
29
|
+
## [1.7.0] - 2011-01-06
|
30
|
+
|
31
|
+
## [1.6.3] - 2009-12-12
|
32
|
+
|
33
|
+
|
34
|
+
[Unreleased]: https://github.com/ruport/ruport/compare/v1.8.0...HEAD
|
35
|
+
[1.8.0]: https://github.com/ruport/ruport/compare/v1.7.1...v1.8.0
|
36
|
+
[1.7.1]: https://github.com/ruport/ruport/compare/v1.7.0...v1.7.1
|
37
|
+
[1.7.0]: https://github.com/ruport/ruport/compare/v1.6.3...v1.7.0
|
38
|
+
[1.6.3]: https://github.com/ruport/ruport/compare/v1.6.2...v1.6.3
|
data/HACKING
CHANGED
@@ -23,23 +23,7 @@ contributions to our project. Here are a few different ways you can help.
|
|
23
23
|
If any of these things sound appealing to you, there are a few things
|
24
24
|
you should do:
|
25
25
|
|
26
|
-
1)
|
27
|
-
|
28
|
-
2) Post and introduce yourself, letting us know what you'd like to work on OR
|
29
|
-
Find sandal or mikem836 on #ruport
|
30
|
-
|
31
|
-
3) Please read the MakingChangeRequests, ReportingDefects, and
|
32
|
-
SubmittingPatches Trac wiki pages, as appropriate.
|
33
|
-
|
34
|
-
- http://stonecode.svnrepository.com/ruport/trac.cgi/wiki/MakingChangeRequests
|
35
|
-
|
36
|
-
- http://stonecode.svnrepository.com/ruport/trac.cgi/wiki/ReportingDefects
|
37
|
-
|
38
|
-
- http://stonecode.svnrepository.com/ruport/trac.cgi/wiki/SubmittingPatches
|
39
|
-
|
40
|
-
4) Please pull the latest code from SVN trunk:
|
41
|
-
http://stonecode.svnrepository.com/svn/ruport/ruport/trunk
|
42
|
-
|
26
|
+
1) Head over to https://github.com/ruport/ruport
|
43
27
|
|
44
28
|
This should hopefully be enough to get you on the right track. We welcome your
|
45
29
|
questions and ideas, so don't be afraid to contact us.
|
data/{README.rdoc → README.md}
RENAMED
@@ -1,4 +1,7 @@
|
|
1
|
-
|
1
|
+
[![Build Status][BS img]](https://travis-ci.org/ruport/ruport)
|
2
|
+
[![Coverage Status][CS img]](https://coveralls.io/r/ruport/ruport)
|
3
|
+
|
4
|
+
## What Ruport Is
|
2
5
|
|
3
6
|
Ruby Reports (Ruport) is an extensible reporting system.
|
4
7
|
|
@@ -20,9 +23,9 @@ of helper functions that will let you build complex reports while maintaining
|
|
20
23
|
a DRY and consistent interface.
|
21
24
|
|
22
25
|
To get a quick feel for what you can accomplish with Ruport, take a look at
|
23
|
-
a few simple examples provided on our web site
|
26
|
+
a few simple examples provided on our web site:
|
24
27
|
|
25
|
-
|
28
|
+
https://ruport.github.io/examples.html
|
26
29
|
|
27
30
|
Since Ruport's core support is intentionally minimalistic, you may be looking
|
28
31
|
for some higher level support for specific needs such as graphing, invoices,
|
@@ -30,71 +33,57 @@ report mailing support, etc. For this, you may wish to take a look at the
|
|
30
33
|
ruport-util package, which contains some generally useful tools and libraries
|
31
34
|
to extend Ruport's capabilities.
|
32
35
|
|
33
|
-
|
36
|
+
## Installation
|
34
37
|
|
35
38
|
To install ruport via rubygems:
|
36
39
|
|
37
|
-
|
40
|
+
```sh
|
41
|
+
$ sudo gem install ruport
|
42
|
+
```
|
38
43
|
|
39
44
|
Check to see if it installed properly:
|
40
45
|
|
41
|
-
|
46
|
+
```sh
|
47
|
+
$ ruby -e "require 'ruport'; puts Ruport::VERSION"
|
48
|
+
```
|
42
49
|
|
43
50
|
If you get an error, please let us know on our mailing list.
|
44
51
|
|
45
|
-
|
52
|
+
### Dependencies
|
46
53
|
|
47
|
-
|
54
|
+
#### Formatting
|
48
55
|
|
49
56
|
Ruport relies on PDF::Writer for its formatting support.
|
50
57
|
If you want to make use of textile helpers, you'll also need RedCloth.
|
51
58
|
|
52
|
-
|
59
|
+
#### Database interaction
|
53
60
|
|
54
|
-
If you wish to use Ruport to report against a
|
55
|
-
|
56
|
-
ActiveRecord and the acts_as_reportable gem.
|
61
|
+
If you wish to use Ruport to report against a Rails project, you'll need
|
62
|
+
ActiveRecord and the `acts_as_reportable` gem.
|
57
63
|
|
58
64
|
If you want to use Ruport::Query for raw SQL support, you'll need to
|
59
|
-
install ruport-util
|
65
|
+
install `ruport-util`, `RubyDBI` and whatever database drivers you might
|
66
|
+
need.
|
60
67
|
|
61
|
-
|
68
|
+
## Resources
|
62
69
|
|
63
70
|
Our developers have published a free-content book about all things
|
64
71
|
Ruport, including complete coverage of acts_as_reportable and some of
|
65
72
|
ruport-util's features. This book serves as the definitive guide to
|
66
73
|
Ruport, so all users should become acquainted with it:
|
67
74
|
|
68
|
-
|
69
|
-
|
70
|
-
The next best way to get help and make suggestions is the Ruport mailing list.
|
71
|
-
This software is on the move, so the list is the most reliable way of getting
|
72
|
-
up to date information.
|
73
|
-
|
74
|
-
- You can sign up and/or view the archives here:
|
75
|
-
http://groups.google.com/group/ruby-reports
|
75
|
+
https://ruport.github.io
|
76
76
|
|
77
77
|
If you are looking to dig a little deeper, there are a couple more resources
|
78
78
|
that may be helpful to you.
|
79
79
|
|
80
|
-
-
|
81
|
-
|
82
|
-
|
83
|
-
- Our issues tracker is at http://github.com/ruport/ruport/issues
|
80
|
+
- The latest stable API documentation is available at: http://rubydoc.info/gems/ruport/frames
|
81
|
+
- The code repository is on GitHub: https://github.com/ruport/ruport
|
82
|
+
- Our issues tracker is at https://github.com/ruport/ruport/issues
|
84
83
|
|
85
|
-
|
84
|
+
## Hacking
|
86
85
|
|
87
|
-
If you'd like to contribute code to Ruport,
|
88
|
-
mailing list, and let us know what you'd like to do!
|
89
|
-
|
90
|
-
http://groups.google.com/group/ruport-dev
|
91
|
-
|
92
|
-
The main Git repository is on GitHub:
|
93
|
-
http://github.com/ruport/ruport
|
94
|
-
|
95
|
-
It also may be worthwhile to join this list if you plan on running edge
|
96
|
-
versions of Ruport, as this is where we make announcements about major
|
97
|
-
breakage in trunk.
|
86
|
+
If you'd like to contribute code to Ruport, fork the repository and open a PR!
|
98
87
|
|
99
88
|
We are very responsive to contributors, and review every patch we receive
|
100
89
|
fairly quickly. Most contributors who successfully get a patch or two applied
|
@@ -103,3 +92,6 @@ development team. Since we view every user as potential contributor, this
|
|
103
92
|
approach works well for us.
|
104
93
|
|
105
94
|
So if you want to help out with Ruport, we'll happy accept your efforts!
|
95
|
+
|
96
|
+
[BS img]: https://travis-ci.org/ruport/ruport.svg?branch=master
|
97
|
+
[CS img]: https://coveralls.io/repos/ruport/ruport/badge.png?branch=master
|
data/Rakefile
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require "rubygems"
|
2
2
|
require "bundler/setup"
|
3
3
|
|
4
|
-
require "rdoc/task"
|
5
4
|
require "rake/testtask"
|
6
5
|
require 'bundler/gem_tasks'
|
7
6
|
|
@@ -17,15 +16,6 @@ Rake::TestTask.new do |test|
|
|
17
16
|
test.verbose = true
|
18
17
|
end
|
19
18
|
|
20
|
-
RDoc::Task.new do |rdoc|
|
21
|
-
rdoc.rdoc_files.include( "README.rdoc",
|
22
|
-
"AUTHORS", "COPYING",
|
23
|
-
"LICENSE", "lib/" )
|
24
|
-
rdoc.main = "README.rdoc"
|
25
|
-
rdoc.rdoc_dir = "doc/html"
|
26
|
-
rdoc.title = "Ruport Documentation"
|
27
|
-
end
|
28
|
-
|
29
19
|
task :run_benchmarks do
|
30
20
|
files = FileList["util/bench/**/**/*.rb"]
|
31
21
|
files.sort!
|
data/examples/row_renderer.rb
CHANGED
@@ -41,7 +41,7 @@ class TracSummaryReport
|
|
41
41
|
Grouping(table,:by => :date)
|
42
42
|
end
|
43
43
|
|
44
|
-
def renderable_data(
|
44
|
+
def renderable_data(_format)
|
45
45
|
summary = feed_data.summary :date,
|
46
46
|
:opened => lambda { |g| g.sigma { |r| r.opened } },
|
47
47
|
:closed => lambda { |g| g.sigma { |r| r.closed } },
|
data/lib/ruport/controller.rb
CHANGED
@@ -216,7 +216,7 @@ class Ruport::Controller
|
|
216
216
|
def built_in_formats
|
217
217
|
{ :html => Ruport::Formatter::HTML,
|
218
218
|
:csv => Ruport::Formatter::CSV,
|
219
|
-
:pdf => Ruport::Formatter::
|
219
|
+
:pdf => Ruport::Formatter::PrawnPDF,
|
220
220
|
:prawn_pdf => Ruport::Formatter::PrawnPDF,
|
221
221
|
:text => Ruport::Formatter::Text }
|
222
222
|
end
|
data/lib/ruport/data/grouping.rb
CHANGED
@@ -99,7 +99,7 @@ module Ruport::Data
|
|
99
99
|
if @subgroups.empty?
|
100
100
|
@subgroups = grouped_data(group_column)
|
101
101
|
else
|
102
|
-
@subgroups.each {|
|
102
|
+
@subgroups.each {|_name,group|
|
103
103
|
group.send(:create_subgroups, group_column)
|
104
104
|
}
|
105
105
|
end
|
@@ -172,7 +172,7 @@ module Ruport::Data
|
|
172
172
|
cols = Array(options[:by]).dup
|
173
173
|
@data = data.to_group.send(:grouped_data, cols.shift)
|
174
174
|
cols.each do |col|
|
175
|
-
@data.each do |
|
175
|
+
@data.each do |_name,group|
|
176
176
|
group.send(:create_subgroups, col)
|
177
177
|
end
|
178
178
|
end
|
@@ -200,9 +200,9 @@ module Ruport::Data
|
|
200
200
|
#
|
201
201
|
def each
|
202
202
|
if @order.respond_to?(:call)
|
203
|
-
@data.sort_by { |
|
203
|
+
@data.sort_by { |_n,g| @order[g] }.each { |n,g| yield(n,g) }
|
204
204
|
elsif @order == :name
|
205
|
-
@data.sort_by { |n,
|
205
|
+
@data.sort_by { |n,_g| n }.each { |name,group| yield(name,group) }
|
206
206
|
else
|
207
207
|
@data.each { |name,group| yield(name,group) }
|
208
208
|
end
|
@@ -216,7 +216,7 @@ module Ruport::Data
|
|
216
216
|
# by_size = grouping.sort_grouping_by { |g| g.size }
|
217
217
|
def sort_grouping_by(type=nil,&block)
|
218
218
|
a = Grouping.new(:by => @grouped_by, :order => type || block)
|
219
|
-
each { |
|
219
|
+
each { |_n,g| a << g }
|
220
220
|
return a
|
221
221
|
end
|
222
222
|
|
@@ -285,7 +285,7 @@ module Ruport::Data
|
|
285
285
|
else
|
286
286
|
cols = procs.keys + [field]
|
287
287
|
end
|
288
|
-
|
288
|
+
Table.new(:column_names => cols) { |t|
|
289
289
|
each do |name,group|
|
290
290
|
t << procs.inject({field => name}) do |s,r|
|
291
291
|
s.merge(r[0] => r[1].call(group))
|
@@ -327,7 +327,7 @@ module Ruport::Data
|
|
327
327
|
# grouping.sigma { |r| r.col2 + 1 } #=> 15
|
328
328
|
#
|
329
329
|
def sigma(column=nil)
|
330
|
-
inject(0) do |s, (
|
330
|
+
inject(0) do |s, (_group_name, group)|
|
331
331
|
if column
|
332
332
|
s + group.sigma(column)
|
333
333
|
else
|
data/lib/ruport/data/record.rb
CHANGED
@@ -55,10 +55,10 @@ module Ruport::Data
|
|
55
55
|
case(data)
|
56
56
|
when Array
|
57
57
|
@attributes = options[:attributes] || (0...data.length).to_a
|
58
|
-
@data = @attributes.
|
58
|
+
@data = @attributes.each_with_object({}) { |a, h| h[a.freeze] = data.shift }
|
59
59
|
when Hash
|
60
|
-
@data = data
|
61
|
-
@attributes = options[:attributes] || data.keys
|
60
|
+
@data = data
|
61
|
+
@attributes = options[:attributes] || @data.keys
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
@@ -140,7 +140,7 @@ module Ruport::Data
|
|
140
140
|
case name
|
141
141
|
when String,Symbol
|
142
142
|
self[name] || send(name)
|
143
|
-
when
|
143
|
+
when Integer
|
144
144
|
self[name]
|
145
145
|
else
|
146
146
|
raise ArgumentError, "Whatchu Talkin' Bout, Willis?"
|
data/lib/ruport/data/table.rb
CHANGED
@@ -50,7 +50,7 @@ module Ruport::Data
|
|
50
50
|
ordering = self.class.row_order_to_group_order(@pivot_order)
|
51
51
|
pivot_column_grouping.sort_grouping_by!(ordering) if ordering
|
52
52
|
|
53
|
-
@row = pivot_column_grouping.map { |name,
|
53
|
+
@row = pivot_column_grouping.map { |name,_grouping| name }
|
54
54
|
end
|
55
55
|
|
56
56
|
# Column in the first column in the pivoted table (without the group column)
|
@@ -71,10 +71,10 @@ module Ruport::Data
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def values
|
74
|
-
@values ||= Hash.new do |
|
74
|
+
@values ||= Hash.new do |row_values, column_entry|
|
75
75
|
rows_group = rows_groups[column_entry]
|
76
76
|
|
77
|
-
|
77
|
+
row_values[column_entry] =
|
78
78
|
row.inject({}) do |values, row_entry|
|
79
79
|
matching_rows = rows_group.rows_with(@pivot_column => row_entry)
|
80
80
|
values[row_entry] = perform_operation(matching_rows)
|
@@ -132,7 +132,7 @@ module Ruport::Data
|
|
132
132
|
rows && rows.inject(0) { |sum,row| sum+row[summary_column] }
|
133
133
|
end
|
134
134
|
|
135
|
-
def count(rows,
|
135
|
+
def count(rows, _summary_column)
|
136
136
|
rows && rows.length
|
137
137
|
end
|
138
138
|
|
@@ -259,7 +259,7 @@ module Ruport::Data
|
|
259
259
|
table = self.new(options) do |feeder|
|
260
260
|
first_line = true
|
261
261
|
|
262
|
-
::CSV.send(msg,param,options[:csv_options]) do |row|
|
262
|
+
::CSV.send(msg,param, **options[:csv_options]) do |row|
|
263
263
|
if first_line
|
264
264
|
adjust_for_headers(feeder.data,row,options)
|
265
265
|
first_line = false
|
@@ -560,8 +560,8 @@ module Ruport::Data
|
|
560
560
|
# data.add_columns ['new_column_1','new_column_2'], :default => 1
|
561
561
|
#
|
562
562
|
def add_columns(names,options={})
|
563
|
-
raise "Greg isn't smart enough to figure this out.\n"
|
564
|
-
"Send ideas in at
|
563
|
+
raise "Greg isn't smart enough to figure this out.\n" \
|
564
|
+
"Send ideas in at github" if block_given?
|
565
565
|
need_reverse = !!(options[:after] || options[:position])
|
566
566
|
names = names.reverse if need_reverse
|
567
567
|
names.each { |n| add_column(n,options) }
|
@@ -576,7 +576,7 @@ module Ruport::Data
|
|
576
576
|
# table.remove_column("apple") #=> removes column named apple
|
577
577
|
#
|
578
578
|
def remove_column(col)
|
579
|
-
col = column_names[col] if col.kind_of?
|
579
|
+
col = column_names[col] if col.kind_of? Integer
|
580
580
|
column_names.delete(col)
|
581
581
|
each { |r| r.send(:delete,col) }
|
582
582
|
end
|
@@ -666,7 +666,7 @@ module Ruport::Data
|
|
666
666
|
# +-----------+
|
667
667
|
#
|
668
668
|
def swap_column(a,b)
|
669
|
-
if [a,b].all? { |r| r.kind_of?
|
669
|
+
if [a,b].all? { |r| r.kind_of? Integer }
|
670
670
|
col_a,col_b = column_names[a],column_names[b]
|
671
671
|
column_names[a] = col_b
|
672
672
|
column_names[b] = col_a
|
data/lib/ruport/formatter/csv.rb
CHANGED
@@ -55,7 +55,7 @@ module Ruport
|
|
55
55
|
#
|
56
56
|
def csv_writer
|
57
57
|
@csv_writer ||= options.formatter ||
|
58
|
-
::CSV.instance(output, options.format_options || {})
|
58
|
+
::CSV.instance(output, **(options.format_options || {}))
|
59
59
|
end
|
60
60
|
|
61
61
|
# Generates table header by turning column_names into a CSV row.
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ruport
|
4
|
+
# This class produces Markdown table output from Ruport::Table data.
|
5
|
+
#
|
6
|
+
# === Rendering Options
|
7
|
+
# <tt>:alignment:</tt> Default alignment for all columns.
|
8
|
+
# Allowed values are :left, :center and :right. Default is :left.
|
9
|
+
#
|
10
|
+
# <tt>:column_alignments:</tt> Alignments for specific columns.
|
11
|
+
# You can configure alignments by using
|
12
|
+
# Hash (key: column name, value: alignment)
|
13
|
+
class Formatter::MarkDown < Formatter
|
14
|
+
renders :markdown, for: [Controller::Table]
|
15
|
+
|
16
|
+
# Hook for setting available options using a template.
|
17
|
+
def apply_template
|
18
|
+
apply_table_format_template(template.table)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Uses the column names from the given Data::Table to generate
|
22
|
+
# a table header.
|
23
|
+
# If no column names are given, first row will be
|
24
|
+
# treated as table header.
|
25
|
+
def build_table_header
|
26
|
+
names = column_names(data)
|
27
|
+
build_md_row(output, names)
|
28
|
+
build_md_row(output, alignment_strings(names))
|
29
|
+
end
|
30
|
+
|
31
|
+
# Generates body of Markdown table data.
|
32
|
+
# Following characters will be replaced as escape.
|
33
|
+
#
|
34
|
+
# * | -> |
|
35
|
+
# * newline code(\\n) -> \<br>
|
36
|
+
def build_table_body
|
37
|
+
body =
|
38
|
+
if data.column_names && !data.column_names.empty?
|
39
|
+
data
|
40
|
+
else
|
41
|
+
data[1..-1]
|
42
|
+
end
|
43
|
+
body.each { |row| build_md_row(output, row) }
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def column_names(data)
|
49
|
+
if data.column_names && !data.column_names.empty?
|
50
|
+
data.column_names
|
51
|
+
else
|
52
|
+
data[0]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def build_md_row(output, row)
|
57
|
+
output << "|"
|
58
|
+
output << row.to_a.map { |cell| escape(cell.to_s.dup) }.join('|')
|
59
|
+
output << "|\n"
|
60
|
+
end
|
61
|
+
|
62
|
+
def escape(cell)
|
63
|
+
cell.gsub!("|", "|")
|
64
|
+
cell.gsub!("\n", "<br>")
|
65
|
+
cell
|
66
|
+
end
|
67
|
+
|
68
|
+
def alignment_strings(column_names)
|
69
|
+
column_names.map(&method(:alignment_string))
|
70
|
+
end
|
71
|
+
|
72
|
+
def alignment_string(column_name)
|
73
|
+
case column_alignment(column_name)
|
74
|
+
when :right
|
75
|
+
"--:"
|
76
|
+
when :center
|
77
|
+
":-:"
|
78
|
+
else
|
79
|
+
":--"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def column_alignment(column_name)
|
84
|
+
if options.column_alignments && options.column_alignments.key?(column_name)
|
85
|
+
options.column_alignments[column_name]
|
86
|
+
elsif options.alignment
|
87
|
+
options.alignment
|
88
|
+
else
|
89
|
+
:left
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def apply_table_format_template(template)
|
94
|
+
template = (template || {}).merge(options.table_format || {})
|
95
|
+
options.alignment ||= template[:alignment]
|
96
|
+
options.column_alignments =
|
97
|
+
merget_column_alignments(options, template)
|
98
|
+
end
|
99
|
+
|
100
|
+
def merget_column_alignments(options, template)
|
101
|
+
(template[:column_alignments] || {})
|
102
|
+
.merge(options.column_alignments || {})
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -4,7 +4,7 @@ module Ruport
|
|
4
4
|
renders :prawn_pdf, :for =>[Controller::Row, Controller::Table,
|
5
5
|
Controller::Group, Controller::Grouping]
|
6
6
|
|
7
|
-
|
7
|
+
attr_writer :pdf
|
8
8
|
|
9
9
|
def method_missing(id,*args, &block)
|
10
10
|
pdf.send(id,*args, &block)
|
@@ -12,7 +12,7 @@ module Ruport
|
|
12
12
|
|
13
13
|
def initialize
|
14
14
|
require 'prawn'
|
15
|
-
require 'prawn/
|
15
|
+
require 'prawn/table'
|
16
16
|
end
|
17
17
|
|
18
18
|
def pdf
|
@@ -20,7 +20,7 @@ module Ruport
|
|
20
20
|
::Prawn::Document.new(options[:pdf_format] || {} ))
|
21
21
|
end
|
22
22
|
|
23
|
-
def draw_table(table, format_opts={})
|
23
|
+
def draw_table(table, format_opts={}, &block)
|
24
24
|
m = "PDF Formatter requires column_names to be defined"
|
25
25
|
raise FormatterError, m if table.column_names.empty?
|
26
26
|
|
@@ -33,10 +33,10 @@ module Ruport
|
|
33
33
|
if options[:table_format]
|
34
34
|
opt = options[:table_format]
|
35
35
|
else
|
36
|
-
opt =
|
36
|
+
opt = format_opts
|
37
37
|
end
|
38
38
|
|
39
|
-
pdf.table(table_array,opt)
|
39
|
+
pdf.table(table_array, opt, &block)
|
40
40
|
|
41
41
|
end
|
42
42
|
|
@@ -48,15 +48,15 @@ module Ruport
|
|
48
48
|
output << pdf.render
|
49
49
|
end
|
50
50
|
|
51
|
-
def build_table_body
|
52
|
-
draw_table(data)
|
51
|
+
def build_table_body(&block)
|
52
|
+
draw_table(data, &block)
|
53
53
|
end
|
54
54
|
|
55
55
|
def build_group_body
|
56
56
|
render_table data, options.to_hash.merge(:formatter => pdf)
|
57
57
|
end
|
58
58
|
|
59
|
-
def build_grouping_body
|
59
|
+
def build_grouping_body(&block)
|
60
60
|
data.each do |name,group|
|
61
61
|
|
62
62
|
# Group heading
|
@@ -65,8 +65,95 @@ module Ruport
|
|
65
65
|
|
66
66
|
# Table
|
67
67
|
move_down(10)
|
68
|
-
draw_table group
|
68
|
+
draw_table group, &block
|
69
69
|
end
|
70
70
|
end
|
71
|
+
|
72
|
+
# Hook for setting available options using a template. See the template
|
73
|
+
# documentation for the available options and their format.
|
74
|
+
def apply_template
|
75
|
+
apply_page_format_template(template.page)
|
76
|
+
apply_text_format_template(template.text)
|
77
|
+
apply_table_format_template(template.table)
|
78
|
+
apply_column_format_template(template.column)
|
79
|
+
apply_heading_format_template(template.heading)
|
80
|
+
apply_grouping_format_template(template.grouping)
|
81
|
+
end
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
def apply_page_format_template(t)
|
86
|
+
options.pdf_format ||= {}
|
87
|
+
t = (t || {}).merge(options.page_format || {})
|
88
|
+
options.pdf_format[:page_size] ||= t[:size]
|
89
|
+
options.pdf_format[:page_layout] ||= t[:layout]
|
90
|
+
end
|
91
|
+
|
92
|
+
def apply_text_format_template(t)
|
93
|
+
t = (t || {}).merge(options.text_format || {})
|
94
|
+
options.text_format = t unless t.empty?
|
95
|
+
end
|
96
|
+
|
97
|
+
def apply_table_format_template(t)
|
98
|
+
t = (t || {}).merge(options.table_format || {})
|
99
|
+
options.table_format = t unless t.empty?
|
100
|
+
end
|
101
|
+
|
102
|
+
def apply_column_format_template(t)
|
103
|
+
t = (t || {}).merge(options.column_format || {})
|
104
|
+
column_opts = {}
|
105
|
+
column_opts.merge!(:justification => t[:alignment]) if t[:alignment]
|
106
|
+
column_opts.merge!(:width => t[:width]) if t[:width]
|
107
|
+
unless column_opts.empty?
|
108
|
+
if options.table_format
|
109
|
+
if options.table_format[:column_options]
|
110
|
+
options.table_format[:column_options] =
|
111
|
+
column_opts.merge(options.table_format[:column_options])
|
112
|
+
else
|
113
|
+
options.table_format.merge!(:column_options => column_opts)
|
114
|
+
end
|
115
|
+
else
|
116
|
+
options.table_format = { :column_options => column_opts }
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def apply_heading_format_template(t)
|
122
|
+
t = (t || {}).merge(options.heading_format || {})
|
123
|
+
heading_opts = {}
|
124
|
+
heading_opts.merge!(:justification => t[:alignment]) if t[:alignment]
|
125
|
+
heading_opts.merge!(:bold => t[:bold]) unless t[:bold].nil?
|
126
|
+
heading_opts.merge!(:title => t[:title]) if t[:title]
|
127
|
+
unless heading_opts.empty?
|
128
|
+
if options.table_format
|
129
|
+
if options.table_format[:column_options]
|
130
|
+
if options.table_format[:column_options][:heading]
|
131
|
+
options.table_format[:column_options][:heading] =
|
132
|
+
heading_opts.merge(
|
133
|
+
options.table_format[:column_options][:heading]
|
134
|
+
)
|
135
|
+
else
|
136
|
+
options.table_format[:column_options].merge!(
|
137
|
+
:heading => heading_opts
|
138
|
+
)
|
139
|
+
end
|
140
|
+
else
|
141
|
+
options.table_format.merge!(
|
142
|
+
:column_options => { :heading => heading_opts }
|
143
|
+
)
|
144
|
+
end
|
145
|
+
else
|
146
|
+
options.table_format = {
|
147
|
+
:column_options => { :heading => heading_opts }
|
148
|
+
}
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def apply_grouping_format_template(t)
|
154
|
+
t = (t || {}).merge(options.grouping_format || {})
|
155
|
+
options.style ||= t[:style]
|
156
|
+
end
|
157
|
+
|
71
158
|
end
|
72
159
|
end
|