jsanders-ruport 1.7.1
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 +48 -0
- data/LICENSE +59 -0
- data/README +114 -0
- data/Rakefile +93 -0
- data/examples/RWEmerson.jpg +0 -0
- data/examples/anon.rb +43 -0
- data/examples/btree/commaleon/commaleon.rb +263 -0
- data/examples/btree/commaleon/sample_data/ticket_count.csv +124 -0
- data/examples/btree/commaleon/sample_data/ticket_count2.csv +119 -0
- data/examples/centered_pdf_text_box.rb +83 -0
- data/examples/data/tattle.dump +82 -0
- data/examples/example.csv +3 -0
- data/examples/line_plotter.rb +61 -0
- data/examples/pdf_report_with_common_base.rb +72 -0
- data/examples/png_embed.rb +54 -0
- data/examples/roadmap.png +0 -0
- data/examples/row_renderer.rb +39 -0
- data/examples/simple_pdf_lines.rb +25 -0
- data/examples/simple_templating_example.rb +34 -0
- data/examples/tattle_ruby_version.rb +39 -0
- data/examples/tattle_rubygems_version.rb +37 -0
- data/examples/trac_ticket_status.rb +59 -0
- data/lib/ruport.rb +127 -0
- data/lib/ruport/controller.rb +616 -0
- data/lib/ruport/controller/grouping.rb +71 -0
- data/lib/ruport/controller/table.rb +54 -0
- data/lib/ruport/data.rb +4 -0
- data/lib/ruport/data/feeder.rb +111 -0
- data/lib/ruport/data/grouping.rb +399 -0
- data/lib/ruport/data/record.rb +297 -0
- data/lib/ruport/data/table.rb +950 -0
- data/lib/ruport/extensions.rb +4 -0
- data/lib/ruport/formatter.rb +254 -0
- data/lib/ruport/formatter/csv.rb +149 -0
- data/lib/ruport/formatter/html.rb +161 -0
- data/lib/ruport/formatter/pdf.rb +591 -0
- data/lib/ruport/formatter/template.rb +187 -0
- data/lib/ruport/formatter/text.rb +231 -0
- data/lib/uport.rb +1 -0
- data/test/controller_test.rb +743 -0
- data/test/csv_formatter_test.rb +164 -0
- data/test/data_feeder_test.rb +88 -0
- data/test/grouping_test.rb +410 -0
- data/test/helpers.rb +11 -0
- data/test/html_formatter_test.rb +201 -0
- data/test/pdf_formatter_test.rb +354 -0
- data/test/record_test.rb +332 -0
- data/test/samples/addressbook.csv +6 -0
- data/test/samples/data.csv +3 -0
- data/test/samples/data.tsv +3 -0
- data/test/samples/dates.csv +1409 -0
- data/test/samples/erb_test.sql +1 -0
- data/test/samples/query_test.sql +1 -0
- data/test/samples/ruport_test.sql +8 -0
- data/test/samples/test.sql +2 -0
- data/test/samples/test.yaml +3 -0
- data/test/samples/ticket_count.csv +124 -0
- data/test/table_pivot_test.rb +134 -0
- data/test/table_test.rb +838 -0
- data/test/template_test.rb +48 -0
- data/test/text_formatter_test.rb +258 -0
- data/util/bench/data/record/bench_as_vs_to.rb +18 -0
- data/util/bench/data/record/bench_constructor.rb +46 -0
- data/util/bench/data/record/bench_indexing.rb +65 -0
- data/util/bench/data/record/bench_reorder.rb +35 -0
- data/util/bench/data/record/bench_to_a.rb +19 -0
- data/util/bench/data/table/bench_column_manip.rb +103 -0
- data/util/bench/data/table/bench_dup.rb +24 -0
- data/util/bench/data/table/bench_init.rb +67 -0
- data/util/bench/data/table/bench_manip.rb +125 -0
- data/util/bench/formatter/bench_csv.rb +14 -0
- data/util/bench/formatter/bench_html.rb +14 -0
- data/util/bench/formatter/bench_pdf.rb +14 -0
- data/util/bench/formatter/bench_text.rb +14 -0
- data/util/bench/samples/tattle.csv +1237 -0
- metadata +176 -0
@@ -0,0 +1,164 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "helpers")
|
3
|
+
|
4
|
+
class TestRenderCSVRow < Test::Unit::TestCase
|
5
|
+
def test_render_csv_row
|
6
|
+
actual = Ruport::Controller::Row.render_csv(:data => [1,2,3])
|
7
|
+
assert_equal("1,2,3\n", actual)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class TestRenderCSVTable < Test::Unit::TestCase
|
12
|
+
|
13
|
+
def setup
|
14
|
+
Ruport::Formatter::Template.create(:simple) do |format|
|
15
|
+
format.table = {
|
16
|
+
:show_headings => false
|
17
|
+
}
|
18
|
+
format.grouping = {
|
19
|
+
:style => :justified,
|
20
|
+
:show_headings => false
|
21
|
+
}
|
22
|
+
format.format_options = { :col_sep => ":" }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_render_csv_table
|
27
|
+
actual = Ruport::Controller::Table.render_csv do |r|
|
28
|
+
r.data = Table([], :data => [[1,2,3],[4,5,6]])
|
29
|
+
end
|
30
|
+
assert_equal("1,2,3\n4,5,6\n",actual)
|
31
|
+
|
32
|
+
actual = Ruport::Controller::Table.render_csv do |r|
|
33
|
+
r.data = Table(%w[a b c], :data => [[1,2,3],[4,5,6]])
|
34
|
+
end
|
35
|
+
assert_equal("a,b,c\n1,2,3\n4,5,6\n",actual)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_format_options
|
39
|
+
a = Table(%w[a b c], :data => [[1,2,3],[4,5,6]])
|
40
|
+
assert_equal "a\tb\tc\n1\t2\t3\n4\t5\t6\n",
|
41
|
+
a.as(:csv,:format_options => { :col_sep => "\t" })
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_table_headers
|
45
|
+
actual = Ruport::Controller::Table.
|
46
|
+
render_csv(:show_table_headers => false,
|
47
|
+
:data => Table(%w[a b c], :data => [[1,2,3],[4,5,6]]))
|
48
|
+
assert_equal("1,2,3\n4,5,6\n",actual)
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_render_with_template
|
52
|
+
formatter = Ruport::Formatter::CSV.new
|
53
|
+
formatter.options = Ruport::Controller::Options.new
|
54
|
+
formatter.options.template = :simple
|
55
|
+
formatter.apply_template
|
56
|
+
|
57
|
+
assert_equal false, formatter.options.show_table_headers
|
58
|
+
|
59
|
+
assert_equal :justified, formatter.options.style
|
60
|
+
assert_equal false, formatter.options.show_group_headers
|
61
|
+
|
62
|
+
assert_equal ":", formatter.options.format_options[:col_sep]
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_options_hashes_override_template
|
66
|
+
opts = nil
|
67
|
+
table = Table(%w[a b c])
|
68
|
+
table.to_csv(
|
69
|
+
:template => :simple,
|
70
|
+
:table_format => {
|
71
|
+
:show_headings => true
|
72
|
+
},
|
73
|
+
:grouping_format => {
|
74
|
+
:style => :raw,
|
75
|
+
:show_headings => true
|
76
|
+
}
|
77
|
+
) do |r|
|
78
|
+
opts = r.options
|
79
|
+
end
|
80
|
+
|
81
|
+
assert_equal true, opts.show_table_headers
|
82
|
+
|
83
|
+
assert_equal :raw, opts.style
|
84
|
+
assert_equal true, opts.show_group_headers
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_individual_options_override_template
|
88
|
+
opts = nil
|
89
|
+
table = Table(%w[a b c])
|
90
|
+
table.to_csv(
|
91
|
+
:template => :simple,
|
92
|
+
:show_table_headers => true,
|
93
|
+
:style => :raw,
|
94
|
+
:show_group_headers => true,
|
95
|
+
:format_options => { :col_sep => ";" }
|
96
|
+
) do |r|
|
97
|
+
opts = r.options
|
98
|
+
end
|
99
|
+
|
100
|
+
assert_equal true, opts.show_table_headers
|
101
|
+
|
102
|
+
assert_equal :raw, opts.style
|
103
|
+
assert_equal true, opts.show_group_headers
|
104
|
+
|
105
|
+
assert_equal ";", opts.format_options[:col_sep]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
class TestRenderCSVGroup < Test::Unit::TestCase
|
110
|
+
|
111
|
+
def test_render_csv_group
|
112
|
+
group = Ruport::Data::Group.new(:name => 'test',
|
113
|
+
:data => [[1,2,3],[4,5,6]],
|
114
|
+
:column_names => %w[a b c])
|
115
|
+
actual = Ruport::Controller::Group.
|
116
|
+
render_csv(:data => group, :show_table_headers => false )
|
117
|
+
assert_equal("test\n\n1,2,3\n4,5,6\n",actual)
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
class RenderCSVGrouping < Test::Unit::TestCase
|
123
|
+
def test_render_csv_grouping
|
124
|
+
table = Table(%w[hi red snapper]) << %w[is this annoying] <<
|
125
|
+
%w[is it funny]
|
126
|
+
grouping = Grouping(table,:by => "hi")
|
127
|
+
|
128
|
+
actual = grouping.to_csv
|
129
|
+
|
130
|
+
assert_equal "is\n\nred,snapper\nthis,annoying\nit,funny\n\n", actual
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_render_csv_grouping_without_header
|
134
|
+
table = Table(%w[hi red snapper]) << %w[is this annoying] <<
|
135
|
+
%w[is it funny]
|
136
|
+
grouping = Grouping(table,:by => "hi")
|
137
|
+
|
138
|
+
actual = grouping.to_csv :show_table_headers => false
|
139
|
+
|
140
|
+
assert_equal "is\n\nthis,annoying\nit,funny\n\n", actual
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_alternative_styles
|
144
|
+
g = Grouping((Table(%w[a b c]) << [1,2,3] << [1,1,4] <<
|
145
|
+
[2,1,2] << [1,9,1] ), :by => "a")
|
146
|
+
|
147
|
+
assert_raise(NotImplementedError) { g.to_csv :style => :not_real }
|
148
|
+
|
149
|
+
assert_equal "a,b,c\n1,2,3\n,1,4\n,9,1\n\n2,1,2\n\n",
|
150
|
+
g.to_csv(:style => :justified)
|
151
|
+
|
152
|
+
assert_equal "a,b,c\n1,2,3\n1,1,4\n1,9,1\n\n2,1,2\n\n",
|
153
|
+
g.to_csv(:style => :raw)
|
154
|
+
end
|
155
|
+
|
156
|
+
# -----------------------------------------------------------------------
|
157
|
+
# BUG TRAPS
|
158
|
+
# ------------------------------------------------------------------------
|
159
|
+
|
160
|
+
def test_ensure_group_names_are_converted_to_string
|
161
|
+
g = Grouping((Table(%w[a b c])<<[1,2,3]<<[1,1,4]), :by => "a")
|
162
|
+
assert_equal "1\n\nb,c\n2,3\n1,4\n\n", g.to_csv
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "helpers")
|
3
|
+
|
4
|
+
class DataFeederTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
context "when using a default data feeder" do
|
7
|
+
|
8
|
+
def setup
|
9
|
+
@feeder = Ruport::Data::Feeder.new(Table(%w[a b c]))
|
10
|
+
end
|
11
|
+
|
12
|
+
def specify_data_attribute_should_return_wrapped_data
|
13
|
+
assert_equal Table(%w[a b c]), @feeder.data
|
14
|
+
end
|
15
|
+
|
16
|
+
def specify_append_should_forward_to_wrapped_data_by_default
|
17
|
+
t = Table(%w[a b c])
|
18
|
+
t << [1,2,3] << {"a" => 2, "b" => 3, "c" => 4}
|
19
|
+
@feeder << [1,2,3] << {"a" => 2, "b" => 3, "c" => 4}
|
20
|
+
assert_equal t, @feeder.data
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
context "when using a feeder with a filter" do
|
26
|
+
def setup
|
27
|
+
@feeder = Ruport::Data::Feeder.new(Table(%w[a b c]))
|
28
|
+
@feeder.filter { |r| r.a != 1 }
|
29
|
+
end
|
30
|
+
|
31
|
+
def specify_filter_should_only_append_rows_for_which_block_is_true
|
32
|
+
@feeder << [1,2,3] << [4,1,2] << [3,1,1] << [1,2,5]
|
33
|
+
assert_equal Table(%w[a b c], :data => [[4,1,2],[3,1,1]]), @feeder.data
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "when using a feeder with a transform" do
|
38
|
+
def setup
|
39
|
+
@feeder = Ruport::Data::Feeder.new(Table(%w[a b c]))
|
40
|
+
@feeder.transform { |r| r.a += 1 }
|
41
|
+
end
|
42
|
+
|
43
|
+
def specify_filter_should_be_applied_to_all_rows
|
44
|
+
@feeder << [1,2,3] << [4,1,2] << [3,1,1] << [1,2,5]
|
45
|
+
assert_equal Table(%w[a b c], :data => [[2,2,3],[5,1,2],[4,1,1],[2,2,5]]),
|
46
|
+
@feeder.data
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "when using a feeder and a filter together" do
|
51
|
+
def setup
|
52
|
+
@feeder = Ruport::Data::Feeder.new(Table(%w[a b c]))
|
53
|
+
end
|
54
|
+
|
55
|
+
def specify_filter_is_called_first_when_defined_first
|
56
|
+
@feeder.filter { |r| r.b != 2 }
|
57
|
+
@feeder.transform { |r| r.b += 1 }
|
58
|
+
@feeder << [1,2,3] << [4,1,2] << [3,1,1] << [1,2,5]
|
59
|
+
assert_equal Table(%w[a b c], :data => [[4,2,2],[3,2,1]]),
|
60
|
+
@feeder.data
|
61
|
+
end
|
62
|
+
|
63
|
+
def specify_transform_is_called_first_when_defined_first
|
64
|
+
@feeder.transform { |r| r.b += 1 }
|
65
|
+
@feeder.filter { |r| r.b != 2 }
|
66
|
+
@feeder << [1,2,3] << [4,1,2] << [3,1,1] << [1,2,5]
|
67
|
+
assert_equal Table(%w[a b c], :data => [[1,3,3],[1,3,5]]),
|
68
|
+
@feeder.data
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "when using many feeders and filters together" do
|
73
|
+
def setup
|
74
|
+
@feeder = Ruport::Data::Feeder.new(Table(%w[a b c]))
|
75
|
+
@feeder.transform { |r| r.a += 1 }
|
76
|
+
@feeder.filter { |r| r.a > 5 }
|
77
|
+
@feeder.transform { |r| r.b = r.b.to_s }
|
78
|
+
@feeder.filter { |r| r.b == "3" }
|
79
|
+
end
|
80
|
+
|
81
|
+
def specify_all_blocks_are_executed_in_order
|
82
|
+
@feeder << [1,2,3] << [4,1,9] << [5,3,1] << [2,3,0] << [7,3,5]
|
83
|
+
assert_equal Table(%w[a b c], :data => [[6,"3",1],[8,"3",5]]),
|
84
|
+
@feeder.data
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
@@ -0,0 +1,410 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "helpers")
|
3
|
+
|
4
|
+
class TestGroup < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@group = Ruport::Data::Group.new(:name => 'test',
|
8
|
+
:data => [[1,2,3]],
|
9
|
+
:column_names => %w[a b c])
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_group_constructor
|
13
|
+
group = Ruport::Data::Group.new(:name => 'test',
|
14
|
+
:data => [[1,2,3]],
|
15
|
+
:column_names => %w[a b c])
|
16
|
+
assert_equal 'test', group.name
|
17
|
+
assert_equal Ruport::Data::Record.new([1,2,3],:attributes => %w[a b c]),
|
18
|
+
group.data[0]
|
19
|
+
assert_equal %w[a b c], group.column_names
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_should_copy_group
|
23
|
+
@group.send(:create_subgroups, "a")
|
24
|
+
copy = @group.dup
|
25
|
+
assert_equal 'test', copy.name
|
26
|
+
assert_equal Ruport::Data::Record.new([1,2,3],:attributes => %w[a b c]),
|
27
|
+
copy.data[0]
|
28
|
+
assert_equal %w[a b c], copy.column_names
|
29
|
+
|
30
|
+
b = { 1 => Ruport::Data::Group.new( :data => [[2,3]],
|
31
|
+
:column_names => %w[b c],
|
32
|
+
:name => 1 ) }
|
33
|
+
assert_equal b, copy.subgroups
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_eql
|
37
|
+
table = Table(%w[a b c], :data => [[1,2,3]])
|
38
|
+
|
39
|
+
group2 = Ruport::Data::Group.new(:name => 'test',
|
40
|
+
:data => [[1,2,3]],
|
41
|
+
:column_names => %w[a b c])
|
42
|
+
|
43
|
+
assert_raises(NoMethodError) { @group == table }
|
44
|
+
assert_equal @group, group2
|
45
|
+
assert_equal @group, @group.dup
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_create_subgroups
|
49
|
+
group = @group << [4,5,6]
|
50
|
+
group.send(:create_subgroups, "a")
|
51
|
+
b = { 1 => Ruport::Data::Group.new( :data => [[2,3]],
|
52
|
+
:column_names => %w[b c],
|
53
|
+
:name => 1 ),
|
54
|
+
4 => Ruport::Data::Group.new( :data => [[5,6]],
|
55
|
+
:column_names => %w[b c],
|
56
|
+
:name => 4 ) }
|
57
|
+
assert_equal b, group.subgroups
|
58
|
+
|
59
|
+
group.send(:create_subgroups, "b")
|
60
|
+
c = { 2 => Ruport::Data::Group.new( :data => [[3]],
|
61
|
+
:column_names => %w[c],
|
62
|
+
:name => 2 ) }
|
63
|
+
d = { 5 => Ruport::Data::Group.new( :data => [[6]],
|
64
|
+
:column_names => %w[c],
|
65
|
+
:name => 5 ) }
|
66
|
+
assert_equal c, group.subgroups[1].subgroups
|
67
|
+
assert_equal d, group.subgroups[4].subgroups
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_grouped_data
|
71
|
+
a = @group << [4,5,6]
|
72
|
+
b = { 1 => Ruport::Data::Group.new( :data => [[2,3]],
|
73
|
+
:column_names => %w[b c],
|
74
|
+
:name => 1 ),
|
75
|
+
4 => Ruport::Data::Group.new( :data => [[5,6]],
|
76
|
+
:column_names => %w[b c],
|
77
|
+
:name => 4 ) }
|
78
|
+
assert_equal b, a.send(:grouped_data, "a")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class TestGroupRendering < Test::Unit::TestCase
|
83
|
+
|
84
|
+
def setup
|
85
|
+
@group = Ruport::Data::Group.new(:name => 'test',
|
86
|
+
:data => [[1,2,3]],
|
87
|
+
:column_names => %w[a b c])
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_group_as
|
91
|
+
assert_equal(7, @group.to_text.to_a.length)
|
92
|
+
assert_equal(5, @group.as(:text,
|
93
|
+
:show_table_headers => false).to_a.length)
|
94
|
+
assert_equal(13, @group.to_html.to_a.length)
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_as_throws_proper_errors
|
98
|
+
assert_nothing_raised { @group.as(:csv) }
|
99
|
+
assert_nothing_raised { @group.to_csv }
|
100
|
+
assert_raises(Ruport::Controller::UnknownFormatError) {
|
101
|
+
@group.as(:nothing) }
|
102
|
+
assert_raises(Ruport::Controller::UnknownFormatError) {
|
103
|
+
@group.to_nothing }
|
104
|
+
end
|
105
|
+
|
106
|
+
class MyGroupSub < Ruport::Data::Group; end
|
107
|
+
|
108
|
+
def test_ensure_group_subclasses_render_properly
|
109
|
+
t = MyGroupSub.new(:column_names => %w[b c],:name => "1") << [2,3]
|
110
|
+
assert_equal "1\n\nb,c\n2,3\n", t.to_csv
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
class TestGrouping < Test::Unit::TestCase
|
115
|
+
|
116
|
+
def setup
|
117
|
+
table = Table(%w[a b c], :data => [[1,2,3],[4,5,6]])
|
118
|
+
@grouping = Ruport::Data::Grouping.new(table, :by => "a")
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_grouping_constructor
|
122
|
+
a = Table(%w[a b c], :data => [[1,2,3],[4,5,6]])
|
123
|
+
b = Ruport::Data::Grouping.new(a, :by => "a")
|
124
|
+
c = { 1 => Ruport::Data::Group.new( :data => [[2,3]],
|
125
|
+
:column_names => %w[b c],
|
126
|
+
:name => 1 ),
|
127
|
+
4 => Ruport::Data::Group.new( :data => [[5,6]],
|
128
|
+
:column_names => %w[b c],
|
129
|
+
:name => 4 ) }
|
130
|
+
assert_equal c, b.data
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_empty_grouping
|
134
|
+
a = Ruport::Data::Grouping.new()
|
135
|
+
a << Group("foo",:data => [[1,2,3],[4,5,6]],
|
136
|
+
:column_names => %w[a b c] )
|
137
|
+
assert_equal "foo", a["foo"].name
|
138
|
+
assert_nil a.grouped_by
|
139
|
+
end
|
140
|
+
|
141
|
+
def test_empty_grouping_with_grouped_by
|
142
|
+
a = Ruport::Data::Grouping.new(:by => "nada")
|
143
|
+
a << Group("foo",:data => [[1,2,3],[4,5,6]],
|
144
|
+
:column_names => %w[a b c] )
|
145
|
+
assert_equal "foo", a["foo"].name
|
146
|
+
assert_equal "nada", a.grouped_by
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_grouping_indexing
|
150
|
+
a = [Ruport::Data::Group.new( :data => [[2,3]],
|
151
|
+
:column_names => %w[b c],
|
152
|
+
:name => 1 ),
|
153
|
+
Ruport::Data::Group.new( :data => [[5,6]],
|
154
|
+
:column_names => %w[b c],
|
155
|
+
:name => 4 ),
|
156
|
+
Ruport::Data::Group.new( :data => [],
|
157
|
+
:column_names => %w[b c],
|
158
|
+
:name => 2)]
|
159
|
+
assert_equal a[0], @grouping[1]
|
160
|
+
assert_equal a[1], @grouping[4]
|
161
|
+
assert_raises(IndexError) { @grouping[2] }
|
162
|
+
end
|
163
|
+
|
164
|
+
def test_should_copy_grouping
|
165
|
+
a = { 1 => Ruport::Data::Group.new( :data => [[2,3]],
|
166
|
+
:column_names => %w[b c],
|
167
|
+
:name => 1 ),
|
168
|
+
4 => Ruport::Data::Group.new( :data => [[5,6]],
|
169
|
+
:column_names => %w[b c],
|
170
|
+
:name => 4 ) }
|
171
|
+
copy = @grouping.dup
|
172
|
+
assert_equal a, copy.data
|
173
|
+
assert_equal "a", copy.grouped_by
|
174
|
+
end
|
175
|
+
|
176
|
+
def test_append
|
177
|
+
a = Table(%w[a b c], :data => [[1,2,3],[4,5,6]])
|
178
|
+
@grouping << a.to_group("red snapper")
|
179
|
+
assert_equal @grouping["red snapper"], a.to_group("red snapper")
|
180
|
+
|
181
|
+
assert_raises(ArgumentError) { @grouping << a.to_group("red snapper") }
|
182
|
+
end
|
183
|
+
|
184
|
+
def test_grouped_by
|
185
|
+
assert_equal "a", @grouping.grouped_by
|
186
|
+
end
|
187
|
+
|
188
|
+
def test_grouping_on_multiple_columns
|
189
|
+
a = Table(%w[a b c d], :data => [[1,2,3,4],[4,5,6,7]])
|
190
|
+
b = Ruport::Data::Grouping.new(a, :by => %w[a b c])
|
191
|
+
c = { 1 => Ruport::Data::Group.new( :data => [[2,3,4]],
|
192
|
+
:column_names => %w[b c d],
|
193
|
+
:name => 1 ),
|
194
|
+
4 => Ruport::Data::Group.new( :data => [[5,6,7]],
|
195
|
+
:column_names => %w[b c d],
|
196
|
+
:name => 4 ) }
|
197
|
+
assert_equal c, b.data
|
198
|
+
|
199
|
+
d = { 2 => Ruport::Data::Group.new( :data => [[3,4]],
|
200
|
+
:column_names => %w[c d],
|
201
|
+
:name => 2 ) }
|
202
|
+
e = { 5 => Ruport::Data::Group.new( :data => [[6,7]],
|
203
|
+
:column_names => %w[c d],
|
204
|
+
:name => 5 ) }
|
205
|
+
assert_equal d, b[1].subgroups
|
206
|
+
assert_equal e, b[4].subgroups
|
207
|
+
end
|
208
|
+
|
209
|
+
def test_subgrouping
|
210
|
+
a = Table(%w[first_name last_name id])
|
211
|
+
a << %w[ greg brown awesome ]
|
212
|
+
a << %w[ mike milner schweet ]
|
213
|
+
a << %w[ greg brown sick ]
|
214
|
+
g = Grouping(a,:by => %w[first_name last_name])
|
215
|
+
|
216
|
+
sub = g.subgrouping("greg")["brown"]
|
217
|
+
assert_equal %w[awesome sick], sub.column("id")
|
218
|
+
|
219
|
+
sub = (g / "mike")["milner"]
|
220
|
+
assert_equal %w[schweet], sub.column("id")
|
221
|
+
end
|
222
|
+
|
223
|
+
class TicketStatus < Ruport::Data::Record
|
224
|
+
|
225
|
+
def closed
|
226
|
+
title =~ /Ticket.+(\w+ closed)/ ? 1 : 0
|
227
|
+
end
|
228
|
+
|
229
|
+
def opened
|
230
|
+
title =~ /Ticket.+(\w+ created)|(\w+ reopened)/ ? 1 : 0
|
231
|
+
end
|
232
|
+
|
233
|
+
end
|
234
|
+
|
235
|
+
def test_grouping_summary
|
236
|
+
source = Table(File.join(File.expand_path(File.dirname(__FILE__)),
|
237
|
+
*%w[samples ticket_count.csv]),
|
238
|
+
:record_class => TicketStatus)
|
239
|
+
grouping = Grouping(source,:by => "date")
|
240
|
+
|
241
|
+
expected = Table(:date, :opened,:closed)
|
242
|
+
grouping.each do |date,group|
|
243
|
+
opened = group.sigma { |r| r.opened }
|
244
|
+
closed = group.sigma { |r| r.closed }
|
245
|
+
expected << { :date => date, :opened => opened, :closed => closed }
|
246
|
+
end
|
247
|
+
|
248
|
+
actual = grouping.summary :date,
|
249
|
+
:opened => lambda { |g| g.sigma(:opened) },
|
250
|
+
:closed => lambda { |g| g.sigma(:closed) },
|
251
|
+
:order => [:date,:opened,:closed]
|
252
|
+
|
253
|
+
assert_equal expected, actual
|
254
|
+
|
255
|
+
actual = grouping.summary :date,
|
256
|
+
:opened => lambda { |g| g.sigma(:opened) },
|
257
|
+
:closed => lambda { |g| g.sigma(:closed) }
|
258
|
+
|
259
|
+
assert_equal [], expected.column_names - actual.column_names
|
260
|
+
end
|
261
|
+
|
262
|
+
def test_grouping_sigma
|
263
|
+
assert_respond_to @grouping, :sigma
|
264
|
+
assert_respond_to @grouping, :sum
|
265
|
+
|
266
|
+
expected = {}
|
267
|
+
@grouping.data[@grouping.data.keys.first].column_names.each do |col|
|
268
|
+
expected[col] = @grouping.inject(0) do |s, (group_name, group)|
|
269
|
+
s + group.sigma(col)
|
270
|
+
end
|
271
|
+
end
|
272
|
+
expected.keys.each do |col|
|
273
|
+
assert_equal expected[col], @grouping.sigma(col)
|
274
|
+
end
|
275
|
+
|
276
|
+
expected = {}
|
277
|
+
@grouping.data[@grouping.data.keys.first].column_names.each do |col|
|
278
|
+
expected[col] = @grouping.inject(0) do |s, (group_name, group)|
|
279
|
+
s + group.sigma {|r| r[col] + 2 }
|
280
|
+
end
|
281
|
+
end
|
282
|
+
expected.keys.each do |col|
|
283
|
+
assert_equal expected[col], @grouping.sigma {|r| r[col] + 2 }
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
context "when sorting groupings" do
|
288
|
+
|
289
|
+
def setup
|
290
|
+
@table = Table(%w[a b c]) << ["dog",1,2] << ["cat",3,5] <<
|
291
|
+
["banana",8,1] << ["dog",5,6]
|
292
|
+
end
|
293
|
+
|
294
|
+
def specify_can_set_by_group_name_order_in_constructor
|
295
|
+
a = Grouping(@table, :by => "a", :order => :name)
|
296
|
+
names = %w[banana cat dog]
|
297
|
+
data = [ [[8,1]], [[3,5]], [[1,2],[5,6]] ]
|
298
|
+
a.each do |name,group|
|
299
|
+
assert_equal names.shift, name
|
300
|
+
assert_equal data.shift, group.map { |r| r.to_a }
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
def specify_can_set_by_proc_ordering_in_constructor
|
305
|
+
a = Grouping(@table, :by => "a", :order => lambda { |g| -g.length } )
|
306
|
+
names = %w[dog banana cat]
|
307
|
+
data = [ [[1,2],[5,6]], [[8,1]], [[3,5]] ]
|
308
|
+
a.each do |name,group|
|
309
|
+
assert_equal names.shift, name
|
310
|
+
assert_equal data.shift, group.map { |r| r.to_a }
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
314
|
+
def specify_can_override_sorting
|
315
|
+
a = Grouping(@table, :by => "a", :order => lambda { |g| -g.length } )
|
316
|
+
a.sort_grouping_by!(:name)
|
317
|
+
names = %w[banana cat dog]
|
318
|
+
data = [ [[8,1]], [[3,5]], [[1,2],[5,6]] ]
|
319
|
+
a.each do |name,group|
|
320
|
+
assert_equal names.shift, name
|
321
|
+
assert_equal data.shift, group.map { |r| r.to_a }
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
def specify_can_get_a_new_sorted_grouping
|
326
|
+
a = Grouping(@table, :by => "a", :order => lambda { |g| -g.length } )
|
327
|
+
b = a.sort_grouping_by(:name)
|
328
|
+
|
329
|
+
names = %w[banana cat dog]
|
330
|
+
data = [ [[8,1]], [[3,5]], [[1,2],[5,6]] ]
|
331
|
+
b.each do |name,group|
|
332
|
+
assert_equal names.shift, name
|
333
|
+
assert_equal data.shift, group.map { |r| r.to_a }
|
334
|
+
end
|
335
|
+
|
336
|
+
# assert original retained
|
337
|
+
names = %w[dog banana cat]
|
338
|
+
data = [ [[1,2],[5,6]], [[8,1]], [[3,5]] ]
|
339
|
+
a.each do |name,group|
|
340
|
+
assert_equal names.shift, name
|
341
|
+
assert_equal data.shift, group.map { |r| r.to_a }
|
342
|
+
end
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
class MyRecord < Ruport::Data::Record; end
|
347
|
+
|
348
|
+
def test_grouping_should_set_record_class
|
349
|
+
a = Table(%w[a b c], :record_class => MyRecord) { |t|
|
350
|
+
t << [1,2,3]
|
351
|
+
t << [4,5,6]
|
352
|
+
}
|
353
|
+
b = Ruport::Data::Grouping.new(a, :by => "a")
|
354
|
+
assert_equal MyRecord, b[1].record_class
|
355
|
+
end
|
356
|
+
|
357
|
+
class MyGroupingSub < Ruport::Data::Grouping; end
|
358
|
+
|
359
|
+
def test_ensure_grouping_subclasses_render_properly
|
360
|
+
t = Table(%w[a b c]) << [1,2,3]
|
361
|
+
a = MyGroupingSub.new(t, :by => "a")
|
362
|
+
assert_equal "1\n\nb,c\n2,3\n\n", a.to_csv
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
class TestGroupingRendering < Test::Unit::TestCase
|
367
|
+
|
368
|
+
def setup
|
369
|
+
table = Table(%w[a b c], :data => [[1,2,3],[4,5,6]])
|
370
|
+
@grouping = Ruport::Data::Grouping.new(table, :by => "a")
|
371
|
+
end
|
372
|
+
|
373
|
+
def test_grouping_as
|
374
|
+
assert_equal(16, @grouping.to_text.to_a.length)
|
375
|
+
assert_equal(12, @grouping.as(:text,
|
376
|
+
:show_table_headers => false).to_a.length)
|
377
|
+
end
|
378
|
+
|
379
|
+
def test_as_throws_proper_errors
|
380
|
+
assert_nothing_raised { @grouping.as(:csv) }
|
381
|
+
assert_nothing_raised { @grouping.to_csv }
|
382
|
+
assert_raises(Ruport::Controller::UnknownFormatError) {
|
383
|
+
@grouping.as(:nothing) }
|
384
|
+
assert_raises(Ruport::Controller::UnknownFormatError) {
|
385
|
+
@grouping.to_nothing }
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
class TestGroupingKernelHacks < Test::Unit::TestCase
|
390
|
+
|
391
|
+
def test_group_kernel_hack
|
392
|
+
group = Ruport::Data::Group.new( :name => 'test',
|
393
|
+
:data => [[1,2,3]],
|
394
|
+
:column_names => %w[a b c])
|
395
|
+
assert_equal group, Group('test', :data => [[1,2,3]],
|
396
|
+
:column_names => %w[a b c])
|
397
|
+
end
|
398
|
+
|
399
|
+
def test_grouping_kernel_hack
|
400
|
+
table = Table(%w[a b c], :data => [[1,2,3],[4,5,6]])
|
401
|
+
grouping = Ruport::Data::Grouping.new(table, :by => "a")
|
402
|
+
a = { 1 => Ruport::Data::Group.new( :data => [[2,3]],
|
403
|
+
:column_names => %w[b c],
|
404
|
+
:name => 1 ),
|
405
|
+
4 => Ruport::Data::Group.new( :data => [[5,6]],
|
406
|
+
:column_names => %w[b c],
|
407
|
+
:name => 4 ) }
|
408
|
+
assert_equal a, grouping.data
|
409
|
+
end
|
410
|
+
end
|