ruport 0.6.1 → 0.7.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.
Files changed (83) hide show
  1. data/AUTHORS +6 -0
  2. data/Rakefile +4 -4
  3. data/TODO +3 -2
  4. data/bin/rope +2 -103
  5. data/examples/pdf_complex_report.rb +53 -0
  6. data/lib/ruport/config.rb +7 -7
  7. data/lib/ruport/data/collection.rb +8 -7
  8. data/lib/ruport/data/groupable.rb +3 -2
  9. data/lib/ruport/data/record.rb +13 -16
  10. data/lib/ruport/data/table.rb +89 -18
  11. data/lib/ruport/format/csv.rb +29 -0
  12. data/lib/ruport/format/html.rb +40 -0
  13. data/lib/ruport/format/latex.rb +50 -0
  14. data/lib/ruport/format/pdf.rb +78 -0
  15. data/lib/ruport/format/plugin.rb +20 -65
  16. data/lib/ruport/format/svg.rb +39 -0
  17. data/lib/ruport/format/text.rb +77 -0
  18. data/lib/ruport/format/xml.rb +32 -0
  19. data/lib/ruport/format.rb +1 -159
  20. data/lib/ruport/generator.rb +158 -0
  21. data/lib/ruport/layout/component.rb +7 -0
  22. data/lib/ruport/layout.rb +1 -0
  23. data/lib/ruport/query.rb +3 -3
  24. data/lib/ruport/renderer/graph.rb +48 -0
  25. data/lib/ruport/renderer/table.rb +132 -0
  26. data/lib/ruport/renderer.rb +193 -0
  27. data/lib/ruport/report/graph.rb +2 -2
  28. data/lib/ruport/report.rb +94 -96
  29. data/lib/ruport/system_extensions.rb +3 -6
  30. data/lib/ruport.rb +6 -4
  31. data/test/samples/dates.csv +1409 -0
  32. data/test/samples/foo.rtxt +3 -0
  33. data/test/test_collection.rb +0 -14
  34. data/test/test_config.rb +6 -6
  35. data/test/test_graph_renderer.rb +97 -0
  36. data/test/test_groupable.rb +1 -0
  37. data/test/test_query.rb +325 -324
  38. data/test/test_record.rb +3 -2
  39. data/test/test_renderer.rb +74 -0
  40. data/test/test_report.rb +29 -26
  41. data/test/test_table.rb +54 -29
  42. data/test/test_table_renderer.rb +93 -0
  43. data/test/test_text_table.rb +61 -0
  44. data/test/unit.log +24 -0
  45. metadata +41 -63
  46. data/CHANGELOG +0 -587
  47. data/examples/basic_grouping.rb +0 -19
  48. data/examples/fieldless_table.rb +0 -13
  49. data/examples/latex_table.rb +0 -17
  50. data/examples/line_graph.rb +0 -22
  51. data/examples/line_graph_report.rb +0 -23
  52. data/examples/line_plotter.rb +0 -46
  53. data/examples/long.txt +0 -24
  54. data/examples/new_plugin.rb +0 -24
  55. data/examples/report.rb +0 -35
  56. data/examples/sample_invoice_report.rb +0 -32
  57. data/examples/simple_mail.rb +0 -15
  58. data/examples/simple_table_interface.rb +0 -20
  59. data/examples/sql_erb.rb +0 -20
  60. data/examples/template.rb +0 -15
  61. data/examples/text_processors.rb +0 -13
  62. data/lib/ruport/format/engine/document.rb +0 -28
  63. data/lib/ruport/format/engine/graph.rb +0 -18
  64. data/lib/ruport/format/engine/invoice.rb +0 -23
  65. data/lib/ruport/format/engine/table.rb +0 -54
  66. data/lib/ruport/format/engine.rb +0 -108
  67. data/lib/ruport/format/plugin/csv_plugin.rb +0 -26
  68. data/lib/ruport/format/plugin/html_plugin.rb +0 -32
  69. data/lib/ruport/format/plugin/latex_plugin.rb +0 -50
  70. data/lib/ruport/format/plugin/pdf_plugin.rb +0 -126
  71. data/lib/ruport/format/plugin/svg_plugin.rb +0 -61
  72. data/lib/ruport/format/plugin/text_plugin.rb +0 -77
  73. data/lib/ruport/meta_tools.rb +0 -66
  74. data/lib/ruport/report/invoice.rb +0 -29
  75. data/test/_test_groupable.rb +0 -0
  76. data/test/test_format.rb +0 -39
  77. data/test/test_format_engine.rb +0 -264
  78. data/test/test_graph.rb +0 -93
  79. data/test/test_invoice.rb +0 -32
  80. data/test/test_latex.rb +0 -20
  81. data/test/test_meta_tools.rb +0 -14
  82. data/test/test_plugin.rb +0 -277
  83. data/test/ts_all.rb +0 -21
data/AUTHORS CHANGED
@@ -35,3 +35,9 @@ Daniel Berger:
35
35
  Marshall T. Vandegrift:
36
36
  - Fixed a bug in Record's struct-like accessors (method_missing)
37
37
  - Provided performance enhancements and tests for query.rb
38
+
39
+ Stefan Mahlitz:
40
+ - Table#sort_rows_by
41
+
42
+ llasram@gmail.com
43
+ - Improved alignment for Text Tables.
data/Rakefile CHANGED
@@ -23,10 +23,10 @@ end
23
23
 
24
24
  spec = Gem::Specification.new do |spec|
25
25
  spec.name = LEAN ? "lean-ruport" : "ruport"
26
- spec.version = "0.6.1"
26
+ spec.version = "0.7.0"
27
27
  spec.platform = Gem::Platform::RUBY
28
28
  spec.summary = "A generalized Ruby report generation and templating engine."
29
- spec.files = Dir.glob("{examples,lib,test,bin}/**/**/**/*") +
29
+ spec.files = Dir.glob("{examples,lib,test,bin}/**/**/*") +
30
30
  ["Rakefile", "setup.rb"]
31
31
 
32
32
  spec.require_path = "lib"
@@ -35,7 +35,7 @@ spec = Gem::Specification.new do |spec|
35
35
  spec.bindir = "bin"
36
36
  spec.executables = FileList["rope"]
37
37
  spec.has_rdoc = true
38
- spec.extra_rdoc_files = %w{README LICENSE TODO AUTHORS CHANGELOG}
38
+ spec.extra_rdoc_files = %w{README LICENSE TODO AUTHORS}
39
39
  spec.rdoc_options << '--title' << 'Ruport Documentation' <<
40
40
  '--main' << 'README' << '-q'
41
41
  unless LEAN
@@ -43,7 +43,7 @@ spec = Gem::Specification.new do |spec|
43
43
  spec.add_dependency('RedCloth', '>= 3.0.0')
44
44
  spec.add_dependency('pdf-writer', '>= 1.1.3')
45
45
  spec.add_dependency("mailfactory", ">= 1.2.2")
46
- spec.add_dependency("scruffy", ">= 0.2.2")
46
+ spec.add_dependency('scruffy', '>= 0.2.2')
47
47
  end
48
48
  spec.author = "Gregory Brown"
49
49
  spec.email = " gregory.t.brown@gmail.com"
data/TODO CHANGED
@@ -1,4 +1,5 @@
1
1
  = TODO
2
2
 
3
- Any future plans are available on Ruports Trac website
4
- = http://stonecode.svnrepository.com/ruport/trac.cgi
3
+ - Any future plans are available on Ruport's Trac website
4
+
5
+ http://stonecode.svnrepository.com/ruport/trac.cgi
data/bin/rope CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
-
3
2
  require "fileutils"
3
+ require "ruport/generator"
4
4
  include FileUtils
5
5
 
6
6
  if ARGV.empty?
@@ -9,105 +9,4 @@ if ARGV.empty?
9
9
  end
10
10
  project = ARGV[0]
11
11
 
12
- RAKEFILE = <<END_RAKEFILE
13
- begin; require "rubygems"; rescue LoadError; end
14
- require "rake/testtask"
15
-
16
- task :default => [:test]
17
-
18
- Rake::TestTask.new do |test|
19
- test.libs << "test"
20
- test.pattern = 'test/**/test_*.rb'
21
- test.verbose = true
22
- end
23
- END_RAKEFILE
24
-
25
- CONFIG = <<END_CONFIG
26
- require "ruport"
27
-
28
- # For details, see Ruport::Config documentation
29
- Ruport.configure { |c|
30
- c.source :default, :user => "root",
31
- :dsn => "dbi:mysql:mydb"
32
- c.log_file "log/ruport.log"
33
- }
34
- END_CONFIG
35
-
36
- BUILD = <<'END_BUILD'
37
- def format_class_name(string)
38
- string.downcase.split("_").map { |s| s.capitalize }.join
39
- end
40
-
41
- unless ARGV.length > 1
42
- puts "usage build.rb [command] [options]"
43
- exit
44
- end
45
-
46
- class_name = format_class_name(ARGV[1])
47
-
48
- exit if File.exist? "app/reports/#{ARGV[1]}.rb"
49
- if ARGV[0].eql? "report"
50
- File.open("app/reports.rb", "a") { |f|
51
- f.puts("require \"app/reports/#{ARGV[1]}\"")
52
- }
53
- REP = <<EOR
54
- begin; require "rubygems"; rescue LoadError; end
55
- require "ruport"
56
- require "config/ruport_config"
57
-
58
- class #{class_name} < Ruport::Report
59
-
60
- #optional
61
- prepare { }
62
-
63
- #mandatory
64
- generate { }
65
-
66
- #optional
67
- cleanup { }
68
-
69
- end
70
-
71
- # uncomment the line below to let the report be run directly
72
- #
73
- # if __FILE__ == $0
74
- # #{class_name}.run { |res| puts res.results }
75
- # end
76
- EOR
77
-
78
- TEST = <<EOR
79
- begin; require "rubygems"; rescue LoadError; end
80
- require "ruport"
81
- require "test/unit"
82
- require "app/reports/#{ARGV[1]}"
83
- require "config/ruport_config"
84
-
85
- class Test#{class_name} < Test::Unit::TestCase
86
- def test_flunk
87
- flunk "Write your real tests here or in any test/test_* file"
88
- end
89
- end
90
- EOR
91
- File.open("app/reports/#{ARGV[1]}.rb", "w") { |f| f << REP }
92
- File.open("test/test_#{ARGV[1]}.rb","w") { |f| f << TEST }
93
- end
94
- END_BUILD
95
-
96
- SQL_EXEC = <<'END_SQL'
97
- begin; require "rubygems"; rescue LoadError; end
98
- require "ruport"
99
- require "config/ruport_config"
100
-
101
- puts Ruport::Query.new(ARGF.read).result
102
- END_SQL
103
-
104
- mkdir project
105
- %w[test config output data app app/reports templates sql log util].each do |d|
106
- mkdir "#{project}/#{d}"
107
- end
108
-
109
- touch("#{project}/app/reports.rb")
110
- File.open("#{project}/config/ruport_config.rb","w") { |f| f << CONFIG }
111
- File.open("#{project}/Rakefile","w") { |f| f << RAKEFILE }
112
- File.open("#{project}/util/build.rb","w") { |f| f << BUILD }
113
- File.open("#{project}/util/sql_exec.rb","w") { |f| f << SQL_EXEC }
12
+ Ruport::Generator.build(ARGV[0])
@@ -0,0 +1,53 @@
1
+ require "ruport"
2
+
3
+ module MyStuff
4
+
5
+ class DocumentRenderer < Ruport::Renderer
6
+ include Ruport::Renderer::Helpers
7
+
8
+ def run
9
+ build [:header,:body,:footer],:document
10
+ finalize :document
11
+ end
12
+
13
+ def table=(t)
14
+ options.table = t
15
+ end
16
+
17
+ def header_text=(t)
18
+ options.header_text=(t)
19
+ end
20
+
21
+ def footer_text=(t)
22
+ options.footer_text=(t)
23
+ end
24
+
25
+ end
26
+
27
+ class PDF < Ruport::Format::PDF
28
+ DocumentRenderer.add_format self, :pdf
29
+
30
+ def build_document_header
31
+ add_text options.header_text, :justification => :center
32
+ end
33
+
34
+ def build_document_body
35
+ pad(10) { draw_table }
36
+ end
37
+
38
+ def build_document_footer
39
+ add_text options.footer_text, :justification => :center
40
+ end
41
+
42
+ def finalize_document
43
+ output << pdf_writer.render
44
+ end
45
+
46
+ end
47
+ end
48
+
49
+ puts MyStuff::DocumentRenderer.render_pdf { |e|
50
+ e.data = [[1,2],[3,4]].to_table(%w[apple banana])
51
+ e.header_text = "foo"
52
+ e.footer_text = "bar"
53
+ }
data/lib/ruport/config.rb CHANGED
@@ -161,16 +161,12 @@ module Ruport
161
161
  def logger; @logger; end
162
162
 
163
163
  # Forces all messages marked <tt>:log_only</tt> to print anyway.
164
- def enable_paranoia; @paranoid = true; end
164
+ # def enable_paranoia; @paranoid = true; end
165
165
 
166
166
  # Disables the printing of <tt>:log_only</tt> messages.
167
- def disable_paranoia; @paranoid = false; end
167
+ #def disable_paranoia; @paranoid = false; end
168
168
 
169
- # Sets paranoid status.
170
- def paranoid=(val); @paranoid = val; end
171
-
172
- # Checks to see if paranoia is enabled.
173
- def paranoid?; !!@paranoid; end
169
+ def debug_mode?; !!@debug_mode; end
174
170
 
175
171
  # Verifies that you have provided a DSN for your source.
176
172
  def check_source(settings,label) # :nodoc:
@@ -193,6 +189,10 @@ module Ruport
193
189
  )
194
190
  end
195
191
  end
192
+
193
+ def debug_mode=(something)
194
+ @debug_mode = !!something
195
+ end
196
196
 
197
197
  end
198
198
  end
@@ -18,8 +18,8 @@ module Ruport::Data
18
18
  extend Forwardable
19
19
  include Enumerable
20
20
  include Taggable
21
-
22
- def initialize(data=nil,options={})
21
+
22
+ def initialize(data=nil,options={}) #:nodoc:
23
23
  @data = data.dup if data
24
24
  end
25
25
 
@@ -29,9 +29,10 @@ module Ruport::Data
29
29
  # Example:
30
30
  # my_collection.as(:csv) #=> "1,2,3\n4,5,6"
31
31
  def as(type)
32
- eng = Ruport::Format.table_object :data => self, :plugin => type
33
- yield(eng) if block_given?
34
- eng.render
32
+ Ruport::Renderer::Table.render(type) do |rend|
33
+ rend.data = self
34
+ yield(rend) if block_given?
35
+ end
35
36
  end
36
37
 
37
38
  # Converts a <tt>Collection</tt> object to a <tt>Data::Set</tt>.
@@ -47,8 +48,8 @@ module Ruport::Data
47
48
  # Provides a shortcut for the <tt>as()</tt> method by converting a call to
48
49
  # <tt>as(:format_name)</tt> into a call to <tt>to_format_name</tt>
49
50
  def method_missing(id,*args)
50
- return as($1.to_sym) if id.to_s =~ /^to_(.*)/
51
- super
51
+ return as($1.to_sym) if id.to_s =~ /^to_(.*)/
52
+ super
52
53
  end
53
54
 
54
55
  attr_reader :data
@@ -44,7 +44,9 @@ module Ruport::Data
44
44
  r_tags = map { |r| r.tags }.flatten.uniq
45
45
  tables_hash = Hash.new { |h,k| h[k] = [].to_table(column_names) }
46
46
  each { |row|
47
- row.tags.each { |t| tables_hash[t] << row }
47
+ row.tags.each { |t|
48
+ tables_hash[t].instance_variable_get(:@data) << row
49
+ }
48
50
  }
49
51
  r = Record.new tables_hash, :attributes => r_tags
50
52
  class << r
@@ -74,7 +76,6 @@ module Ruport::Data
74
76
  #
75
77
  def create_tag_group(label,&block)
76
78
  each { |r| block[r] && r.tag(label) }
77
- #select(&block).each { |r| r.tag label }
78
79
  end
79
80
  alias_method :tag_group, :create_tag_group
80
81
 
@@ -55,11 +55,7 @@ module Ruport::Data
55
55
  end
56
56
  else
57
57
  @data = data.dup
58
- @attributes = if options[:attributes]
59
- options[:attributes]
60
- else
61
- []
62
- end
58
+ @attributes = options[:attributes] || []
63
59
  end
64
60
  end
65
61
 
@@ -81,8 +77,9 @@ module Ruport::Data
81
77
  raise "Invalid index" unless index < @data.length
82
78
  @data[index]
83
79
  else
84
- raise "Invalid index" unless attributes.index(index.to_s)
85
- @data[attributes.index(index.to_s)]
80
+ index = index.to_s
81
+ raise "Invalid index" unless attributes.index(index)
82
+ @data[attributes.index(index)]
86
83
  end
87
84
  end
88
85
 
@@ -100,8 +97,9 @@ module Ruport::Data
100
97
  raise "Invalid index" unless index < @data.length
101
98
  @data[index] = value
102
99
  else
103
- raise "Invalid index" unless attributes.index(index.to_s)
104
- @data[attributes.index(index.to_s)] = value
100
+ index = index.to_s
101
+ raise "Invalid index" unless @attributes.index(index)
102
+ @data[attributes.index(index)] = value
105
103
  end
106
104
  end
107
105
 
@@ -110,9 +108,9 @@ module Ruport::Data
110
108
  # <tt>==</tt> evaluates to true. Otherwise, <tt>==</tt> returns false.
111
109
  #
112
110
  def ==(other)
113
- return false if attributes && !other.attributes
114
- return false if other.attributes && !attributes
115
- attributes == other.attributes && @data == other.data
111
+ return false if @attributes && !other.attributes
112
+ return false if other.attributes && !@attributes
113
+ @attributes == other.attributes && @data == other.data
116
114
  end
117
115
 
118
116
  alias_method :eql?, :==
@@ -135,8 +133,7 @@ module Ruport::Data
135
133
  #
136
134
  # a = Data::Record.new([1,2],:attributes => %w[a b])
137
135
  # a.to_h #=> {"a" => 1, "b" => 2}
138
- #
139
- def to_h; Hash[*attributes.zip(data).flatten] end
136
+ def to_h; Hash[*@attributes.zip(data).flatten] end
140
137
 
141
138
  #
142
139
  # Returns a copy of the <tt>attributes</tt> from this Record.
@@ -175,9 +172,9 @@ module Ruport::Data
175
172
  # Same as Record#reorder but modifies its reciever in place.
176
173
  def reorder!(*indices)
177
174
  indices = reorder_data!(*indices)
178
- if attributes
175
+ if @attributes
179
176
  if indices.all? { |e| e.kind_of? Integer }
180
- @attributes = indices.map { |i| attributes[i] }
177
+ @attributes = indices.map { |i| @attributes[i] }
181
178
  else
182
179
  @attributes = indices
183
180
  end
@@ -4,20 +4,6 @@
4
4
  # This is Free Software. For details, see LICENSE and COPYING
5
5
  # Copyright 2006 by respective content owners, all rights reserved.
6
6
 
7
- class Array
8
-
9
- #
10
- # Converts an array to a Ruport::Data::Table object, ready to
11
- # use in your reports.
12
- #
13
- # Example:
14
- # [[1,2],[3,4]].to_table(%w[a b])
15
- #
16
- def to_table(options={})
17
- options = { :column_names => options } if options.kind_of? Array
18
- Ruport::Data::Table.new({:data => self}.merge(options))
19
- end
20
- end
21
7
 
22
8
  module Ruport::Data
23
9
 
@@ -415,13 +401,98 @@ module Ruport::Data
415
401
 
416
402
  alias_method :sum, :sigma
417
403
 
404
+ #
405
+ # Returns a sorted table. If col_names is specified,
406
+ # the block is ignored and the table is sorted by the named columns. All
407
+ # options are used in constructing the new Table (see Array#to_table
408
+ # for details).
409
+ #
410
+ # Example:
411
+ #
412
+ # table = [[4, 3], [2, 5], [7, 1]].to_table(%w[col1 col2 ])
413
+ #
414
+ # # returns a new table sorted by col1
415
+ # table.sort_rows_by {|r| r["col1"]}
416
+ #
417
+ # # returns a new table sorted by col2
418
+ # table.sort_rows_by ["col2"]
419
+ #
420
+ # # returns a new table sorted by col1, then col2
421
+ # table.sort_rows_by ["col1", "col2"]
422
+ #
423
+ def sort_rows_by(col_names=nil, &block)
424
+ # stabilizer is needed because of
425
+ # http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/170565
426
+ stabilizer = 0
427
+
428
+ data_array =
429
+ if col_names
430
+ sort_by do |r|
431
+ stabilizer += 1
432
+ [col_names.map {|col| r[col]}, stabilizer]
433
+ end
434
+ else
435
+ sort_by(&block)
436
+ end
437
+
438
+ table =
439
+ data_array.to_table(@column_names)
440
+
441
+ table.tags = self.tags
442
+ return table
443
+ end
444
+
418
445
  end
419
446
 
420
447
  end
421
448
 
422
- module Ruport::Data::TableHelper #:nodoc:
423
- def table(names=[])
424
- t = [].to_table(names)
425
- yield(t) if block_given?; t
449
+
450
+ module Kernel
451
+
452
+ # Shortcut interface for creating Data::Tables
453
+ #
454
+ # Examples:
455
+ #
456
+ # t = Table(%w[a b c]) #=> creates a new empty table w. cols a,b,c
457
+ # t = Table("a","b","c") #=> creates a new empty table w. cols a,b,c
458
+ #
459
+ # # allows building table inside of block, returns table object
460
+ # t = Table(%w[a b c]) { |t| t << [1,2,3] }
461
+ #
462
+ # # allows loading table from CSV
463
+ # # accepts all Data::Table.load options, but block form yields table,
464
+ # # not row!
465
+ #
466
+ # t = Table("foo.csv")
467
+ # t = Table("bar.csv", :has_names => false)
468
+ def Table(*args,&block)
469
+ table=
470
+ case(args[0])
471
+ when Array
472
+ [].to_table(args[0])
473
+ when /\.csv/
474
+ Ruport::Data::Table.load(*args)
475
+ else
476
+ [].to_table(args)
477
+ end
478
+
479
+ block[table] if block
480
+
481
+ return table
482
+ end
483
+ end
484
+
485
+ class Array
486
+
487
+ #
488
+ # Converts an array to a Ruport::Data::Table object, ready to
489
+ # use in your reports.
490
+ #
491
+ # Example:
492
+ # [[1,2],[3,4]].to_table(%w[a b])
493
+ #
494
+ def to_table(column_names=nil)
495
+ Ruport::Data::Table.new({:data => self, :column_names => column_names})
426
496
  end
427
497
  end
498
+
@@ -0,0 +1,29 @@
1
+ module Ruport::Format
2
+
3
+ # This plugin implements the CSV format for tabular data output.
4
+ # See also: Renderer::Table
5
+ class CSV < Plugin
6
+
7
+ # Generates table header by turning column_names into a CSV row.
8
+ # Uses build_csv_row to generate the actual formatted output
9
+ #
10
+ # This method does not do anything if layout.show_table_headers is false or
11
+ # the Data::Table has no column names.
12
+ def build_table_header
13
+ unless data.column_names.empty? || !layout.show_table_headers
14
+ build_csv_row(data.column_names)
15
+ end
16
+ end
17
+
18
+ # Calls build_csv_row for each row in the Data::Table
19
+ def build_table_body
20
+ data.map { |r| build_csv_row(r) }.join("\n")
21
+ end
22
+
23
+ # Produces CSV output for a data row.
24
+ def build_csv_row(row)
25
+ require "fastercsv"
26
+ output << FasterCSV.generate { |csv| csv << row }
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,40 @@
1
+ module Ruport::Format
2
+ # Produces HTML output for tabular data.
3
+ #
4
+ # See also Renderer::Table
5
+ class HTML < Plugin
6
+
7
+ # Generates table headers based on the column names of your Data::Table.
8
+ #
9
+ # This method does not do anything if layout.show_table_headers is false or
10
+ # the Data::Table has no column names.
11
+ def build_table_header
12
+ output << "\t<table>\n"
13
+ unless data.column_names.empty? || !layout.show_table_headers
14
+ output << "\t\t<tr>\n\t\t\t<th>" +
15
+ data.column_names.join("</th>\n\t\t\t<th>") +
16
+ "</th>\n\t\t</tr>\n"
17
+ end
18
+ end
19
+
20
+ # Generates the <tr> and <td> tags for each row, calling to_s on each
21
+ # element of the Record. If the Record has been tagged, the tags will be
22
+ # converted into class attributes in the HTML output.
23
+ #
24
+ def build_table_body
25
+ output << data.inject("") do |s,r|
26
+ row = r.map { |e| e.to_s.empty? ? "&nbsp;" : e }
27
+ classstr = r.tags.inject("") {|cs,c| cs + " class='#{c}'" }
28
+ s + "\t\t<tr#{classstr}>\n\t\t\t<td#{classstr}>" +
29
+ row.to_a.join("</td>\n\t\t\t<td#{classstr}>") +
30
+ "</td>\n\t\t</tr>\n"
31
+ end
32
+ end
33
+
34
+ # Simply closes the table tag.
35
+ def build_table_footer
36
+ output << "\t</table>"
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,50 @@
1
+ module Ruport::Format
2
+ class Latex < Plugin
3
+
4
+ attr_accessor :caption
5
+
6
+ def build_table_header
7
+ output << "\\documentclass[11pt]{article}\n" <<
8
+ "\\RequirePackage{lscape,longtable}\n" <<
9
+ "\\begin{document}\n" <<
10
+ "\\begin{longtable}[c]{ "
11
+
12
+ data.column_names.each do
13
+ output << " p{2cm} "
14
+ end
15
+ output << " }\n"
16
+ output << "\\hline\n"
17
+
18
+ #FIXME: this ain't ruby, jh ;)
19
+ counter = 0
20
+
21
+ data.column_names.each do |t|
22
+ output << " & " unless counter == 0
23
+ output << "\\textsc{#{t}}"
24
+ counter += 1
25
+ end
26
+
27
+ output << "\\\\\n"
28
+ output << "\\hline\n"
29
+ output << "\\endhead\n"
30
+ output << "\\endfoot\n"
31
+ output << "\\hline\n"
32
+ end
33
+
34
+ def build_table_body
35
+ data.each do |r|
36
+ output << r.data.join(" & ") + "\\\\\n"
37
+ output << "\\hline\n"
38
+ end
39
+ if caption
40
+ output << "\\caption[#{caption}]{#{caption}}\n"
41
+ end
42
+ output << "\\end{longtable}\n"
43
+ end
44
+
45
+ def build_table_footer
46
+ output << "\\end{document}\n"
47
+ end
48
+
49
+ end
50
+ end