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.
- data/AUTHORS +6 -0
- data/Rakefile +4 -4
- data/TODO +3 -2
- data/bin/rope +2 -103
- data/examples/pdf_complex_report.rb +53 -0
- data/lib/ruport/config.rb +7 -7
- data/lib/ruport/data/collection.rb +8 -7
- data/lib/ruport/data/groupable.rb +3 -2
- data/lib/ruport/data/record.rb +13 -16
- data/lib/ruport/data/table.rb +89 -18
- data/lib/ruport/format/csv.rb +29 -0
- data/lib/ruport/format/html.rb +40 -0
- data/lib/ruport/format/latex.rb +50 -0
- data/lib/ruport/format/pdf.rb +78 -0
- data/lib/ruport/format/plugin.rb +20 -65
- data/lib/ruport/format/svg.rb +39 -0
- data/lib/ruport/format/text.rb +77 -0
- data/lib/ruport/format/xml.rb +32 -0
- data/lib/ruport/format.rb +1 -159
- data/lib/ruport/generator.rb +158 -0
- data/lib/ruport/layout/component.rb +7 -0
- data/lib/ruport/layout.rb +1 -0
- data/lib/ruport/query.rb +3 -3
- data/lib/ruport/renderer/graph.rb +48 -0
- data/lib/ruport/renderer/table.rb +132 -0
- data/lib/ruport/renderer.rb +193 -0
- data/lib/ruport/report/graph.rb +2 -2
- data/lib/ruport/report.rb +94 -96
- data/lib/ruport/system_extensions.rb +3 -6
- data/lib/ruport.rb +6 -4
- data/test/samples/dates.csv +1409 -0
- data/test/samples/foo.rtxt +3 -0
- data/test/test_collection.rb +0 -14
- data/test/test_config.rb +6 -6
- data/test/test_graph_renderer.rb +97 -0
- data/test/test_groupable.rb +1 -0
- data/test/test_query.rb +325 -324
- data/test/test_record.rb +3 -2
- data/test/test_renderer.rb +74 -0
- data/test/test_report.rb +29 -26
- data/test/test_table.rb +54 -29
- data/test/test_table_renderer.rb +93 -0
- data/test/test_text_table.rb +61 -0
- data/test/unit.log +24 -0
- metadata +41 -63
- data/CHANGELOG +0 -587
- data/examples/basic_grouping.rb +0 -19
- data/examples/fieldless_table.rb +0 -13
- data/examples/latex_table.rb +0 -17
- data/examples/line_graph.rb +0 -22
- data/examples/line_graph_report.rb +0 -23
- data/examples/line_plotter.rb +0 -46
- data/examples/long.txt +0 -24
- data/examples/new_plugin.rb +0 -24
- data/examples/report.rb +0 -35
- data/examples/sample_invoice_report.rb +0 -32
- data/examples/simple_mail.rb +0 -15
- data/examples/simple_table_interface.rb +0 -20
- data/examples/sql_erb.rb +0 -20
- data/examples/template.rb +0 -15
- data/examples/text_processors.rb +0 -13
- data/lib/ruport/format/engine/document.rb +0 -28
- data/lib/ruport/format/engine/graph.rb +0 -18
- data/lib/ruport/format/engine/invoice.rb +0 -23
- data/lib/ruport/format/engine/table.rb +0 -54
- data/lib/ruport/format/engine.rb +0 -108
- data/lib/ruport/format/plugin/csv_plugin.rb +0 -26
- data/lib/ruport/format/plugin/html_plugin.rb +0 -32
- data/lib/ruport/format/plugin/latex_plugin.rb +0 -50
- data/lib/ruport/format/plugin/pdf_plugin.rb +0 -126
- data/lib/ruport/format/plugin/svg_plugin.rb +0 -61
- data/lib/ruport/format/plugin/text_plugin.rb +0 -77
- data/lib/ruport/meta_tools.rb +0 -66
- data/lib/ruport/report/invoice.rb +0 -29
- data/test/_test_groupable.rb +0 -0
- data/test/test_format.rb +0 -39
- data/test/test_format_engine.rb +0 -264
- data/test/test_graph.rb +0 -93
- data/test/test_invoice.rb +0 -32
- data/test/test_latex.rb +0 -20
- data/test/test_meta_tools.rb +0 -14
- data/test/test_plugin.rb +0 -277
- 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.
|
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
|
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(
|
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
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
|
-
|
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
|
-
|
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
|
-
|
33
|
-
|
34
|
-
|
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
|
-
|
51
|
-
|
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|
|
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
|
|
data/lib/ruport/data/record.rb
CHANGED
@@ -55,11 +55,7 @@ module Ruport::Data
|
|
55
55
|
end
|
56
56
|
else
|
57
57
|
@data = data.dup
|
58
|
-
@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
|
-
|
85
|
-
|
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
|
-
|
104
|
-
@
|
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 &&
|
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
|
data/lib/ruport/data/table.rb
CHANGED
@@ -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
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
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? ? " " : 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
|