ruport 1.7.1 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +38 -0
  3. data/HACKING +1 -17
  4. data/{README.rdoc → README.md} +30 -38
  5. data/Rakefile +0 -10
  6. data/examples/row_renderer.rb +1 -1
  7. data/examples/simple_pdf_lines.rb +1 -1
  8. data/examples/trac_ticket_status.rb +1 -1
  9. data/lib/ruport/controller.rb +1 -1
  10. data/lib/ruport/data/grouping.rb +7 -7
  11. data/lib/ruport/data/record.rb +4 -4
  12. data/lib/ruport/data/table.rb +9 -9
  13. data/lib/ruport/formatter/csv.rb +1 -1
  14. data/lib/ruport/formatter/markdown.rb +105 -0
  15. data/lib/ruport/formatter/prawn_pdf.rb +96 -9
  16. data/lib/ruport/formatter/text.rb +1 -1
  17. data/lib/ruport/formatter.rb +1 -2
  18. data/lib/ruport/version.rb +1 -1
  19. data/lib/ruport.rb +7 -11
  20. data/test/controller_test.rb +107 -109
  21. data/test/csv_formatter_test.rb +21 -21
  22. data/test/data_feeder_test.rb +39 -39
  23. data/test/expected_outputs/prawn_pdf_formatter/pdf_basic.pdf.test +265 -0
  24. data/test/grouping_test.rb +74 -74
  25. data/test/helpers.rb +16 -5
  26. data/test/html_formatter_test.rb +22 -22
  27. data/test/markdown_formatter_test.rb +142 -0
  28. data/test/prawn_pdf_formatter_test.rb +108 -0
  29. data/test/record_test.rb +82 -82
  30. data/test/table_pivot_test.rb +9 -2
  31. data/test/table_test.rb +33 -40
  32. data/test/template_test.rb +12 -12
  33. data/test/text_formatter_test.rb +34 -34
  34. data/util/bench/data/table/bench_column_manip.rb +0 -1
  35. data/util/bench/data/table/bench_dup.rb +0 -1
  36. data/util/bench/data/table/bench_init.rb +0 -1
  37. data/util/bench/data/table/bench_manip.rb +0 -1
  38. data/util/bench/formatter/bench_csv.rb +0 -1
  39. data/util/bench/formatter/bench_html.rb +0 -1
  40. data/util/bench/formatter/bench_pdf.rb +0 -1
  41. data/util/bench/formatter/bench_text.rb +0 -1
  42. metadata +30 -29
  43. data/lib/ruport/formatter/pdf.rb +0 -589
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 636885e1621e78e27ce9148ddbb546346af876f3
4
- data.tar.gz: 71811d3ae2c717ad82b1084a03fb8cc91c559add
2
+ SHA256:
3
+ metadata.gz: b8b980ae054fa6d3d42e224431277d3deb471aa2e7132ea144bdb63bff3b3642
4
+ data.tar.gz: 9b5784e616ce0cbce9e218995cb7c3b36eb625cc18a75eea8642092713a391c4
5
5
  SHA512:
6
- metadata.gz: bf3d70cf7c384439b4584f0d4c6b4f3665753dd343fd35a0b300652be74e4fc92c247c10e706e5ce44e2d437f3fa70ac24ee7500dc22fcd7465c67a52f81ddba
7
- data.tar.gz: 0231ae8d2a78ef511f3429c1159974ba6d07361545c77db0839dcf3d923281607b35f14d768e939f26295e54dc5f04cae831f13ae0e7b43bd6c04e6628377f8d
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) Sign up on the mailing list: http://list.rubyreports.org/
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.
@@ -1,4 +1,7 @@
1
- = What Ruport Is
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
- http://ruport.github.io/examples.html
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
- = Installation
36
+ ## Installation
34
37
 
35
38
  To install ruport via rubygems:
36
39
 
37
- sudo gem install ruport
40
+ ```sh
41
+ $ sudo gem install ruport
42
+ ```
38
43
 
39
44
  Check to see if it installed properly:
40
45
 
41
- ruby -rubygems -e "require 'ruport'; puts Ruport::VERSION"
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
- === Dependencies
52
+ ### Dependencies
46
53
 
47
- ==== Formatting
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
- ==== Database interaction
59
+ #### Database interaction
53
60
 
54
- If you wish to use Ruport to report against a rails project,
55
- a camping project, or do standalone acts_as_reportable reports, you'll need
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, RubyDBI and whatever database drivers you might need.
65
+ install `ruport-util`, `RubyDBI` and whatever database drivers you might
66
+ need.
60
67
 
61
- = Resources
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
- http://ruport.github.io
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
- - The latest stable API documentation is available at:
81
- http://rubydoc.info/gems/ruport/frames
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
- = Hacking
84
+ ## Hacking
86
85
 
87
- If you'd like to contribute code to Ruport, please join our development
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!
@@ -6,7 +6,7 @@ class CSV2Something < Ruport::Controller
6
6
 
7
7
  module Helpers
8
8
  def table_feeder
9
- Table(options.csv_file,:has_names => false) { |t,r| yield(r) }
9
+ Table(options.csv_file,:has_names => false) { |_t,r| yield(r) }
10
10
  end
11
11
  end
12
12
 
@@ -18,7 +18,7 @@ class PDFLines < Ruport::Formatter::PDF
18
18
  end
19
19
 
20
20
  # generate 35 random lines
21
- data = (0..34).inject([]) { |s,r|
21
+ data = (0..34).inject([]) { |s,_r|
22
22
  s << [rand(100),100+rand(400)]
23
23
  }
24
24
 
@@ -41,7 +41,7 @@ class TracSummaryReport
41
41
  Grouping(table,:by => :date)
42
42
  end
43
43
 
44
- def renderable_data(format)
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 } },
@@ -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::PDF,
219
+ :pdf => Ruport::Formatter::PrawnPDF,
220
220
  :prawn_pdf => Ruport::Formatter::PrawnPDF,
221
221
  :text => Ruport::Formatter::Text }
222
222
  end
@@ -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 {|name,group|
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 |name,group|
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 { |n,g| @order[g] }.each { |n,g| yield(n,g) }
203
+ @data.sort_by { |_n,g| @order[g] }.each { |n,g| yield(n,g) }
204
204
  elsif @order == :name
205
- @data.sort_by { |n,g| n }.each { |name,group| yield(name,group) }
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 { |n,g| a << g }
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
- expected = Table.new(:column_names => cols) { |t|
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, (group_name, group)|
330
+ inject(0) do |s, (_group_name, group)|
331
331
  if column
332
332
  s + group.sigma(column)
333
333
  else
@@ -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.inject({}) { |h,a| h.merge(a => data.shift) }
58
+ @data = @attributes.each_with_object({}) { |a, h| h[a.freeze] = data.shift }
59
59
  when Hash
60
- @data = data.dup
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 Fixnum
143
+ when Integer
144
144
  self[name]
145
145
  else
146
146
  raise ArgumentError, "Whatchu Talkin' Bout, Willis?"
@@ -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,grouping| 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 |values, column_entry|
74
+ @values ||= Hash.new do |row_values, column_entry|
75
75
  rows_group = rows_groups[column_entry]
76
76
 
77
- values[column_entry] =
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, summary_column)
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 http://list.rubyreports.org" if block_given?
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? Fixnum
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? Fixnum }
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
@@ -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
+ # * | -> &#124;
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!("|", "&#124;")
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
- attr_accessor :pdf
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/layout'
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