ruport 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|