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.
Files changed (76) hide show
  1. data/AUTHORS +48 -0
  2. data/LICENSE +59 -0
  3. data/README +114 -0
  4. data/Rakefile +93 -0
  5. data/examples/RWEmerson.jpg +0 -0
  6. data/examples/anon.rb +43 -0
  7. data/examples/btree/commaleon/commaleon.rb +263 -0
  8. data/examples/btree/commaleon/sample_data/ticket_count.csv +124 -0
  9. data/examples/btree/commaleon/sample_data/ticket_count2.csv +119 -0
  10. data/examples/centered_pdf_text_box.rb +83 -0
  11. data/examples/data/tattle.dump +82 -0
  12. data/examples/example.csv +3 -0
  13. data/examples/line_plotter.rb +61 -0
  14. data/examples/pdf_report_with_common_base.rb +72 -0
  15. data/examples/png_embed.rb +54 -0
  16. data/examples/roadmap.png +0 -0
  17. data/examples/row_renderer.rb +39 -0
  18. data/examples/simple_pdf_lines.rb +25 -0
  19. data/examples/simple_templating_example.rb +34 -0
  20. data/examples/tattle_ruby_version.rb +39 -0
  21. data/examples/tattle_rubygems_version.rb +37 -0
  22. data/examples/trac_ticket_status.rb +59 -0
  23. data/lib/ruport.rb +127 -0
  24. data/lib/ruport/controller.rb +616 -0
  25. data/lib/ruport/controller/grouping.rb +71 -0
  26. data/lib/ruport/controller/table.rb +54 -0
  27. data/lib/ruport/data.rb +4 -0
  28. data/lib/ruport/data/feeder.rb +111 -0
  29. data/lib/ruport/data/grouping.rb +399 -0
  30. data/lib/ruport/data/record.rb +297 -0
  31. data/lib/ruport/data/table.rb +950 -0
  32. data/lib/ruport/extensions.rb +4 -0
  33. data/lib/ruport/formatter.rb +254 -0
  34. data/lib/ruport/formatter/csv.rb +149 -0
  35. data/lib/ruport/formatter/html.rb +161 -0
  36. data/lib/ruport/formatter/pdf.rb +591 -0
  37. data/lib/ruport/formatter/template.rb +187 -0
  38. data/lib/ruport/formatter/text.rb +231 -0
  39. data/lib/uport.rb +1 -0
  40. data/test/controller_test.rb +743 -0
  41. data/test/csv_formatter_test.rb +164 -0
  42. data/test/data_feeder_test.rb +88 -0
  43. data/test/grouping_test.rb +410 -0
  44. data/test/helpers.rb +11 -0
  45. data/test/html_formatter_test.rb +201 -0
  46. data/test/pdf_formatter_test.rb +354 -0
  47. data/test/record_test.rb +332 -0
  48. data/test/samples/addressbook.csv +6 -0
  49. data/test/samples/data.csv +3 -0
  50. data/test/samples/data.tsv +3 -0
  51. data/test/samples/dates.csv +1409 -0
  52. data/test/samples/erb_test.sql +1 -0
  53. data/test/samples/query_test.sql +1 -0
  54. data/test/samples/ruport_test.sql +8 -0
  55. data/test/samples/test.sql +2 -0
  56. data/test/samples/test.yaml +3 -0
  57. data/test/samples/ticket_count.csv +124 -0
  58. data/test/table_pivot_test.rb +134 -0
  59. data/test/table_test.rb +838 -0
  60. data/test/template_test.rb +48 -0
  61. data/test/text_formatter_test.rb +258 -0
  62. data/util/bench/data/record/bench_as_vs_to.rb +18 -0
  63. data/util/bench/data/record/bench_constructor.rb +46 -0
  64. data/util/bench/data/record/bench_indexing.rb +65 -0
  65. data/util/bench/data/record/bench_reorder.rb +35 -0
  66. data/util/bench/data/record/bench_to_a.rb +19 -0
  67. data/util/bench/data/table/bench_column_manip.rb +103 -0
  68. data/util/bench/data/table/bench_dup.rb +24 -0
  69. data/util/bench/data/table/bench_init.rb +67 -0
  70. data/util/bench/data/table/bench_manip.rb +125 -0
  71. data/util/bench/formatter/bench_csv.rb +14 -0
  72. data/util/bench/formatter/bench_html.rb +14 -0
  73. data/util/bench/formatter/bench_pdf.rb +14 -0
  74. data/util/bench/formatter/bench_text.rb +14 -0
  75. data/util/bench/samples/tattle.csv +1237 -0
  76. metadata +176 -0
@@ -0,0 +1 @@
1
+ select * from <%= @table %>
@@ -0,0 +1 @@
1
+ select * from foo
@@ -0,0 +1,8 @@
1
+ create table ruport_test (
2
+ a varchar(55),
3
+ b varchar(55),
4
+ c varchar(55),
5
+ d varchar(55)
6
+ );
7
+ insert into ruport_test values( 'a column, row 1', 'b column, row 1', 'c column, row 1', 'd column, row 1' );
8
+ SELECT * FROM ruport_test;
@@ -0,0 +1,2 @@
1
+ SELECT * FROM ruport_test
2
+
@@ -0,0 +1,3 @@
1
+ :name: Greg
2
+ :friend: Rob
3
+ :job: Programmer
@@ -0,0 +1,124 @@
1
+ title,date
2
+ Ticket #238 (enhancement closed): Table#sort_rows_by!,2007-04-17
3
+ Ticket #225 (task closed): corner bottlenecks with focused benchmarks,2007-04-17
4
+ Ticket #223 (task closed): Identify a small set of key benchmarks,2007-04-17
5
+ Ticket #209 (task closed): Refactor Formatters,2007-04-15
6
+ Ticket #236 (task closed): api.rubyreports.org/edge,2007-04-13
7
+ Ticket #212 (task closed): Users Field Guide,2007-04-13
8
+ Ticket #186 (enhancement closed): simple_html_table,2007-04-13
9
+ Ticket #235 (task closed): Get a big list of all the methods in Ruport. Stare at them. Identify their interface. Cry.,2007-04-13
10
+ Ticket #196 (defect closed): as() returns unintelligible error for non-registered formats,2007-04-13
11
+ Ticket #244 (defect closed): Allow proper copying of Grouping,2007-04-12
12
+ Ticket #249 (enhancement closed): Table#rename_columns should accept a block,2007-04-11
13
+ Ticket #249 (enhancement created): Table#rename_columns should accept a block,2007-04-11
14
+ Ticket #188 (defect closed): class_str broken in 0.9.2,2007-04-11
15
+ Ticket #224 (task closed): Build ruport_bench which will run benchmarks and generate reports,2007-04-11
16
+ Ticket #241 (task closed): rewrite Table/Group dup methods to use initialize_copy instead,2007-04-11
17
+ Ticket #220 (enhancement closed): rope rake tasks for ruport-util,2007-04-10
18
+ Ticket #219 (task closed): XML/FO Formatter,2007-04-07
19
+ Ticket #211 (task closed): Remove Multilevel Grouping Formatters,2007-04-06
20
+ Ticket #248 (task created): AAR Name,2007-04-05
21
+ Ticket #204 (task closed): Merge AAR to Trunk,2007-04-05
22
+ Ticket #203 (task closed): AAR Tests,2007-04-05
23
+ Ticket #226 (task closed): investigate Ara's xx for html helpers.,2007-04-04
24
+ "Ticket #247 (task created): Ruport Utils wiki page, and update of deprecated plugin pages",2007-04-04
25
+ Ticket #245 (task closed): Make initial RubyForge release,2007-04-04
26
+ Ticket #246 (enhancement created): Grouping#summary,2007-04-04
27
+ Ticket #245 (task created): Make initial RubyForge release,2007-04-04
28
+ Ticket #229 (enhancement closed): Add tests for invoice,2007-04-04
29
+ Ticket #231 (enhancement closed): ReportManager tests,2007-04-04
30
+ Ticket #221 (task closed): improve invoice interface,2007-04-04
31
+ Ticket #233 (task closed): ReportManager example,2007-04-04
32
+ Ticket #230 (enhancement closed): Add support for line labels in graph,2007-04-04
33
+ Ticket #242 (task closed): set mike up with stats access,2007-04-04
34
+ Ticket #202 (task closed): AAR Branch,2007-04-04
35
+ Ticket #234 (defect closed): options should not be used as an argument name anywhere in Renderers or Formatters,2007-04-04
36
+ Ticket #244 (defect created): Allow proper copying of Grouping,2007-04-04
37
+ Ticket #240 (task closed): use self.class.new where appropriate,2007-04-04
38
+ Ticket #243 (task closed): fix circular dependency issue in rope,2007-04-04
39
+ Ticket #243 (task created): fix circular dependency issue in rope,2007-04-04
40
+ Ticket #242 (task created): set mike up with stats access,2007-04-03
41
+ Ticket #241 (task created): rewrite Table/Group dup methods to use initialize_copy instead,2007-04-03
42
+ Ticket #237 (task closed): set mike up with all the necessary resource permissions for releases,2007-04-02
43
+ Ticket #227 (task closed): packaging rake task for Release,2007-04-02
44
+ Ticket #240 (task created): use self.class.new where appropriate,2007-04-02
45
+ Ticket #191 (enhancement closed): render_grouping,2007-04-01
46
+ Ticket #239 (enhancement created): Table#sort_rows_by should accept non-array single arg.,2007-04-01
47
+ Ticket #238 (enhancement created): Table#sort_rows_by!,2007-04-01
48
+ Ticket #237 (task created): set mike up with all the necessary resource permissions for releases,2007-04-01
49
+ Ticket #78 (enhancement closed): Do we need to bring back a SQL generator?,2007-03-31
50
+ Ticket #236 (task created): api.rubyreports.org/edge,2007-03-31
51
+ Ticket #235 (task created): Get a big list of all the methods in Ruport. Stare at them. Identify their interface. Cry.,2007-03-31
52
+ Ticket #228 (enhancement closed): Layout method,2007-03-31
53
+ Ticket #234 (defect created): options should not be used as an argument name anywhere in Renderers or Formatters,2007-03-31
54
+ Ticket #217 (task closed): Depluginize initial set of utils,2007-03-31
55
+ Ticket #232 (task closed): ReportManager example,2007-03-31
56
+ Ticket #233 (task created): ReportManager example,2007-03-31
57
+ Ticket #232 (task created): ReportManager example,2007-03-31
58
+ Ticket #231 (enhancement created): ReportManager tests,2007-03-31
59
+ Ticket #230 (enhancement created): Add support for line labels in graph,2007-03-31
60
+ Ticket #216 (task closed): Fix Graphing,2007-03-31
61
+ Ticket #229 (enhancement created): Add tests for invoice,2007-03-31
62
+ Ticket #228 (enhancement created): Layout method,2007-03-31
63
+ Ticket #222 (task closed): add ruport-util component in Trac,2007-03-31
64
+ Ticket #218 (task closed): move svn repository up one level,2007-03-31
65
+ Ticket #227 (task created): packaging rake task for Release,2007-03-31
66
+ Ticket #226 (task created): investigate Ara's xx for html helpers.,2007-03-30
67
+ Ticket #199 (task closed): Update License Information,2007-03-30
68
+ Ticket #178 (task closed): Grouping Renderer,2007-03-30
69
+ Ticket #225 (task created): corner bottlenecks with focused benchmarks,2007-03-30
70
+ Ticket #224 (task created): Build ruport_bench which will run benchmarks and generate reports,2007-03-30
71
+ Ticket #223 (task created): Identify a small set of key benchmarks,2007-03-30
72
+ Ticket #106 (task closed): standardize API documentation format and cleanup where needed,2007-03-30
73
+ Ticket #199 (task closed): Update License Information,2007-03-30
74
+ Ticket #184 (task closed): Consistent Errors,2007-03-30
75
+ Ticket #222 (task created): add ruport-util component in Trac,2007-03-30
76
+ Ticket #221 (task created): improve invoice interface,2007-03-30
77
+ Ticket #220 (enhancement created): rope rake tasks for ruport-util,2007-03-30
78
+ Ticket #219 (task created): XML/FO Formatter,2007-03-30
79
+ Ticket #218 (task created): move svn repository up one level,2007-03-30
80
+ Ticket #217 (task created): Depluginize initial set of utils,2007-03-30
81
+ Ticket #216 (task created): Fix Graphing,2007-03-30
82
+ Ticket #215 (task closed): apply for RubyForge project,2007-03-30
83
+ Ticket #215 (task created): apply for RubyForge project,2007-03-30
84
+ Ticket #214 (task created): Determine if cheatsheets can be released,2007-03-30
85
+ Ticket #213 (task created): Contributors Field Guide,2007-03-30
86
+ Ticket #212 (task created): Users Field Guide,2007-03-30
87
+ Ticket #211 (task created): Remove Multilevel Grouping Formatters,2007-03-30
88
+ Ticket #210 (task created): Formatting Helpers,2007-03-30
89
+ Ticket #209 (task created): Refactor Formatters,2007-03-30
90
+ Ticket #208 (task created): API Stability,2007-03-30
91
+ Ticket #207 (task created): Refactor Unit Tests,2007-03-30
92
+ Ticket #206 (task created): Testing Audit,2007-03-30
93
+ Ticket #205 (task created): Custom Exceptions,2007-03-30
94
+ Ticket #204 (task created): Merge AAR to Trunk,2007-03-30
95
+ Ticket #203 (task created): AAR Tests,2007-03-30
96
+ Ticket #202 (task created): AAR Branch,2007-03-30
97
+ Ticket #201 (task created): Standardize API Docs,2007-03-30
98
+ Ticket #200 (task created): Remove Deprecated Docs,2007-03-30
99
+ Ticket #199 (task created): Update License Information,2007-03-30
100
+ Ticket #198 (task created): rubyreports.org webpage,2007-03-30
101
+ Ticket #197 (task created): Proper Licensing Statements,2007-03-28
102
+ Ticket #196 (defect created): as() returns unintelligible error for non-registered formats,2007-03-28
103
+ Ticket #195 (enhancement closed): Formatter::PDF#draw_table,2007-03-27
104
+ "Ticket #194 (enhancement closed): renders_for should take multiple formats, renderers.",2007-03-26
105
+ Ticket #193 (task closed): Make Renderer.add_format private and remove add_core_format,2007-03-26
106
+ Ticket #195 (enhancement created): Formatter::PDF#draw_table,2007-03-26
107
+ "Ticket #194 (enhancement created): renders_for should take multiple formats, renderers.",2007-03-26
108
+ Ticket #193 (task created): Make Renderer.add_format private and remove add_core_format,2007-03-26
109
+ Ticket #183 (task closed): Remove Shortcuts from Core,2007-03-26
110
+ Ticket #192 (enhancement created): renders_with should take default options,2007-03-26
111
+ Ticket #191 (enhancement created): render_grouping,2007-03-25
112
+ Ticket #190 (enhancement created): Report shortcuts for rendering,2007-03-25
113
+ Ticket #189 (enhancement created): sub_table / reduce should take single arg range,2007-03-25
114
+ Ticket #187 (enhancement closed): Ruport::Format::Plugin becomes Ruport::Formatter,2007-03-24
115
+ Ticket #163 (task closed): Data::Group,2007-03-23
116
+ Ticket #144 (enhancement closed): SQL Formatter?,2007-03-23
117
+ Ticket #188 (defect created): class_str broken in 0.9.2,2007-03-23
118
+ Ticket #187 (enhancement created): Ruport::Format::Plugin becomes Ruport::Formatter,2007-03-23
119
+ Ticket #174 (enhancement closed): Grouping &amp; Group data structures,2007-03-23
120
+ Ticket #186 (enhancement created): simple_html_table,2007-03-23
121
+ Ticket #185 (task created): Sanitize,2007-03-22
122
+ Ticket #184 (task created): Consistent Errors,2007-03-22
123
+ Ticket #183 (task created): Remove Shortcuts from Core,2007-03-22
124
+ Ticket #182 (defect closed): rope does not regenerate deleted test_files when using 'rake build',2007-03-19
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env ruby -w
2
+ require File.join(File.expand_path(File.dirname(__FILE__)), "helpers")
3
+
4
+ class TablePivotSimpleCaseTest < Test::Unit::TestCase
5
+
6
+ def setup
7
+ table = Table('a', 'b', 'c')
8
+ table << [1,3,6]
9
+ table << [1,4,7]
10
+ table << [2,3,8]
11
+ table << [2,4,9]
12
+ @pivoted = table.pivot('b', :group_by => 'a', :values => 'c')
13
+ end
14
+
15
+ def test_produces_correct_columns
16
+ assert_equal(['a', 3, 4], @pivoted.column_names)
17
+ end
18
+
19
+ def test_produces_correct_full_table
20
+ expected = Table("a",3,4) { |t| t << [1,6,7] << [2,8,9] }
21
+ assert_equal(expected, @pivoted)
22
+ end
23
+
24
+ end
25
+
26
+ class PivotConvertRowOrderToGroupOrderTest < Test::Unit::TestCase
27
+
28
+ def convert(src)
29
+ Ruport::Data::Table::Pivot.new(
30
+ nil, nil, nil, nil
31
+ ).convert_row_order_to_group_order(src)
32
+ end
33
+
34
+ def setup
35
+ @group = mock('group')
36
+ @row = mock('row')
37
+ @group.stubs(:[]).with(0).returns(@row)
38
+ end
39
+
40
+ def test_bare_field_name
41
+ converted = convert(:field_name)
42
+ @row.expects(:[]).with(:field_name)
43
+ converted.call(@group)
44
+ end
45
+
46
+ def test_array_of_field_names
47
+ converted = convert([:field1, :field2])
48
+ @row.stubs(:[]).with(:field1).returns('f1val')
49
+ @row.stubs(:[]).with(:field2).returns('f2val')
50
+ assert_equal(['f1val', 'f2val'], converted.call(@group))
51
+ end
52
+
53
+ def test_proc_operating_on_row
54
+ converted = convert(proc {|row| row[:field1] })
55
+ @row.stubs(:[]).with(:field1).returns('f1val')
56
+ assert_equal('f1val', converted.call(@group))
57
+ end
58
+
59
+ def test_nil
60
+ assert_equal(nil, convert(nil))
61
+ end
62
+
63
+ end
64
+
65
+ class PivotPreservesOrdering < Test::Unit::TestCase
66
+
67
+ def test_group_column_entries_preserves_order_of_occurrence
68
+ table = Table('group', 'a', 'b')
69
+ [
70
+ [1, 0, 0],
71
+ [9, 0, 0],
72
+ [1, 0, 0],
73
+ [9, 0, 0],
74
+ [1, 0, 0],
75
+ [8, 0, 0],
76
+ [1, 0, 0]
77
+ ].each {|e| table << e}
78
+ assert_equal([1,9,8],
79
+ Ruport::Data::Table::Pivot.
80
+ new(table, 'group', 'a', 'b').group_column_entries)
81
+ end
82
+
83
+ def test_resulting_columns_preserve_ordering_of_rows
84
+ table = Table('group', 'a', 'b', 'c')
85
+ [
86
+ [200, 1, 2, 1],
87
+ [200, 4, 5, 2],
88
+ [200, 5, 0, 3],
89
+ [100, 1, 8, 4],
90
+ [100, 4,11, 5]
91
+ ].each {|e| table << e}
92
+ assert_equal(
93
+ [1,4,5],
94
+ Ruport::Data::Table::Pivot.new(
95
+ table, 'group', 'a', 'b', :pivot_order => ['c']
96
+ ).columns_from_pivot)
97
+ end
98
+
99
+ def test_preserves_ordering
100
+ table = Table('group', 'a', 'b', 'c')
101
+ [
102
+ [200, 1, 2, 3],
103
+ [200, 4, 5, 6],
104
+ [100, 1, 8, 9],
105
+ [100, 4,11,12]
106
+ ].each {|e| table << e}
107
+ pivoted = table.pivot('a', :group_by => 'group', :values => 'b')
108
+ expected = Table("group",1,4) { |t| t << [200,2,5] << [100,8,11] }
109
+ assert_equal(expected, pivoted)
110
+ end
111
+
112
+ def test_preserves_ordering_on_calculated_column
113
+ table = Table('group', 'a')
114
+ [
115
+ [1, 1], [2, 2], [3, 3]
116
+ ].each {|e| table << e}
117
+ table.add_column('pivotme') {|row| 10 - row.group.to_i}
118
+ pivoted = table.pivot('pivotme', :group_by => 'group', :values => 'a',
119
+ :pivot_order => :name)
120
+ assert_equal(['group', 7, 8, 9], pivoted.column_names)
121
+ end
122
+
123
+ def test_preserves_ordering_on_calculated_column_with_proc_pivot_order
124
+ table = Table('group', 'a')
125
+ [
126
+ [1, 1], [2, 2], [3, 3]
127
+ ].each {|e| table << e}
128
+ table.add_column('pivotme') {|row| 10 - row.group.to_i}
129
+ pivoted = table.pivot('pivotme', :group_by => 'group', :values => 'a',
130
+ :pivot_order => proc {|row, pivot| pivot })
131
+ assert_equal(['group', 7, 8, 9], pivoted.column_names)
132
+ end
133
+
134
+ end
@@ -0,0 +1,838 @@
1
+ #!/usr/bin/env ruby -w
2
+ require File.join(File.expand_path(File.dirname(__FILE__)), "helpers")
3
+ TEST_SAMPLES = File.join(File.expand_path(File.dirname(__FILE__)), "samples")
4
+
5
+ class Person < Ruport::Data::Record
6
+
7
+ def name
8
+ first_name + " " + last_name
9
+ end
10
+
11
+ end
12
+
13
+ class DuckRecord < Ruport::Data::Record; end
14
+
15
+ class TestTable < Test::Unit::TestCase
16
+ def test_constructors
17
+ table = Ruport::Data::Table.new
18
+
19
+ table2 = Ruport::Data::Table.new :column_names => %w[a b c]
20
+ table3 = Ruport::Data::Table.new :data => [[1,2,3]]
21
+ table4 = Ruport::Data::Table.new :column_names => %w[col1 col2 col3],
22
+ :data => [[1,2,3]]
23
+ tables = [table,table2,table3,table4]
24
+
25
+ tables.zip([[],%w[a b c], [], %w[col1 col2 col3]]).each do |t,n|
26
+ assert_equal n, t.column_names
27
+
28
+ t = Table(%w[a b c], :data => [[1,2,3],[4,5,6]])
29
+ table_from_records = Table(t.column_names, :data => t.data)
30
+ end
31
+
32
+ a = Ruport::Data::Record.new [1,2,3]
33
+ b = Ruport::Data::Record.new [1,2,3], :attributes => %w[col1 col2 col3]
34
+ tables.zip([[],[],[a],[b]]).each do |t,n|
35
+ assert_equal n, t.data
36
+ end
37
+ end
38
+
39
+ context "when filtering data" do
40
+
41
+ def setup
42
+ @data = [[1,2,3],[4,5,6],[7,8,9]]
43
+ end
44
+
45
+ def specify_filters_should_discard_unmatched_rows
46
+ table = Ruport::Data::Table.new(:column_names => %w[a b c],
47
+ :data => [[1,2,3],[4,5,6],[7,8,9]],
48
+ :filters => [ lambda { |r| r.a % 2 == 1 } ] )
49
+ assert_equal Table(%w[a b c]) << [1,2,3] << [7,8,9], table
50
+ end
51
+
52
+ def specify_filters_should_work_on_csvs
53
+ only_ids_less_than_3 = lambda { |r| r["id"].to_i < 3 }
54
+ table = Table(File.join(TEST_SAMPLES,"addressbook.csv"),
55
+ :filters => [only_ids_less_than_3])
56
+ assert_equal ["1","2"], table.map { |r| r["id"] }
57
+ end
58
+ end
59
+
60
+ context "when transforming data" do
61
+
62
+ def setup
63
+ @data = [[1,2,3],[4,5,6],[7,8,9]]
64
+ end
65
+
66
+ def specify_transforms_should_modify_table_data
67
+
68
+ stringify_c = lambda { |r| r.c = r.c.to_s }
69
+ add_two_to_all_int_cols = lambda { |r|
70
+ r.each_with_index do |c,i|
71
+ if Fixnum === c
72
+ r[i] += 2
73
+ end
74
+ end
75
+
76
+ }
77
+
78
+ table = Ruport::Data::Table.new(:column_names => %w[a b c],
79
+ :data => @data,
80
+ :transforms => [stringify_c,
81
+ add_two_to_all_int_cols])
82
+ assert_equal Table(%w[a b c]) << [3,4,"3"] << [6,7,"6"] << [9,10,"9"],
83
+ table
84
+
85
+ end
86
+
87
+ def specify_transforms_should_work_on_csvs
88
+ ids_to_i = lambda { |r| r["id"] = r["id"].to_i }
89
+ table = Table(File.join(TEST_SAMPLES,"addressbook.csv"),
90
+ :filters => [ids_to_i])
91
+ assert_equal [1,2,3,4,5], table.map { |r| r["id"] }
92
+ end
93
+ end
94
+
95
+ def test_to_group
96
+ a = Table(%w[a b c], :data => [[1,2,3],[4,5,6]]).to_group("Packrats")
97
+ b = Ruport::Data::Group.new( :data => [[1,2,3],[4,5,6]],
98
+ :column_names => %w[a b c],
99
+ :name => "Packrats" )
100
+ assert_equal a,b
101
+ end
102
+
103
+ def test_rows_with
104
+ table = Table(%w[a b c], :data => [[1,2,3],[1,3,4],[7,8,9]])
105
+
106
+ assert_equal([table[0],table[1]],table.rows_with("a" => 1))
107
+ assert_equal([table[1]],table.rows_with("a" => 1, "b" => 3))
108
+ assert_equal([table[0]],table.rows_with(:a => 1, :b => 2))
109
+ assert_equal([table[2]], table.rows_with_b(8))
110
+ assert_equal [table[1]], table.rows_with(%w[a b]) { |a,b| [a,b] == [1,3] }
111
+ end
112
+
113
+ def test_sigma
114
+ table = Table(%w[col1 col2], :data => [[1,2],[3,4],[5,6]])
115
+ assert table.respond_to?(:sigma)
116
+ assert table.respond_to?(:sum)
117
+ assert_equal(9,table.sigma(0))
118
+ assert_equal(9,table.sigma("col1"))
119
+ assert_equal(21,table.sigma { |r| r.col1 + r.col2 })
120
+ end
121
+
122
+ def test_sub_table
123
+ table = Table(%w[a b c d],
124
+ :data => [ [1,2,3,4],[5,6,7,9],[10,11,12,13],[14,15,16,17] ])
125
+
126
+ assert_equal Table(%w[b c], :data => [[6,7],[11,12]]),
127
+ table.sub_table(%w[b c],1..-2)
128
+
129
+ assert_equal Table(%w[c d a], :data => [[3,4,1],[7,9,5]]),
130
+ table.sub_table(%w[c d a]) { |r| r.a < 10 }
131
+
132
+ assert_equal Table(%w[a c], :data => [[1,3],[5,7],[10,12],[14,16]]),
133
+ table.sub_table(%w[a c])
134
+
135
+ assert_equal Table(%w[a b c d], :data => [[10,11,12,13],[14,15,16,17]]),
136
+ table.sub_table { |r| r.c > 10 }
137
+
138
+ assert_equal Table(%w[a b c d], :data => [[10,11,12,13],[14,15,16,17]]),
139
+ table.sub_table(2..-1)
140
+
141
+ end
142
+
143
+ def test_subtable_records_have_correct_data
144
+ table = Table(%w[a b c d],
145
+ :data => [ [1,2,3,4],[5,6,7,9],[10,11,12,13],[14,15,16,17] ])
146
+ sub = table.sub_table(%w[b c d]) {|r| r.a == 1 }
147
+ assert_equal({"b"=>2, "c"=>3, "d"=>4}, sub[0].data)
148
+ assert_equal(["b", "c", "d"], sub[0].attributes)
149
+ end
150
+
151
+ def test_reduce
152
+ table = Table(%w[a b c d],
153
+ :data => [ [1,2,3,4],[5,6,7,9],[10,11,12,13],[14,15,16,17] ])
154
+
155
+ table.reduce(%w[b c],1..-2)
156
+ assert_equal Table(%w[b c], :data => [[6,7],[11,12]]), table
157
+
158
+ table = Table(%w[a b c d],
159
+ :data => [ [1,2,3,4],[5,6,7,9],[10,11,12,13],[14,15,16,17] ])
160
+ table.reduce(%w[c d a]) { |r| r.a < 10 }
161
+
162
+ assert_equal Table(%w[c d a], :data => [[3,4,1],[7,9,5]]), table
163
+ end
164
+
165
+ def test_reorder
166
+ table = Ruport::Data::Table.load(File.join(TEST_SAMPLES,"data.csv"))
167
+ table.reorder(*%w[col1 col3])
168
+ assert_equal %w[col1 col3], table.column_names
169
+ rows = [%w[a c], %w[d e]]
170
+ table.each { |r| assert_equal rows.shift, r.to_a
171
+ assert_equal %w[col1 col3], r.attributes }
172
+ a = Table(%w[a b c], :data => [[1,2,3],[4,5,6]]).reorder 2,0
173
+ rows = [[3,1],[6,4]]
174
+ a.each { |r| assert_equal rows.shift, r.to_a
175
+ assert_equal %w[c a], r.attributes }
176
+ assert_equal %w[c a], a.column_names
177
+
178
+ b = Table(%w[a b c], :data => [[1,2,3],[4,5,6]]).reorder(%w[a c])
179
+ rows = [[1,3],[4,6]]
180
+ b.each { |r|
181
+ assert_equal rows.shift, r.to_a
182
+ assert_equal %w[a c], r.attributes
183
+ assert_equal b.column_names.object_id,
184
+ r.instance_eval{@attributes}.object_id
185
+ }
186
+ end
187
+
188
+ context "when sorting rows" do
189
+
190
+ def setup
191
+ @table = Table(%w[a b c]) << [1,2,3] << [6,1,8] << [9,1,4]
192
+ @table_with_nils = Table(%w[a b c]) << [1,nil,3] << [9,3,4] << [6,1,8]
193
+ end
194
+
195
+ def specify_should_sort_in_reverse_order_on_descending
196
+ t = @table.sort_rows_by("a", :order => :descending )
197
+ assert_equal Table(%w[a b c]) << [9,1,4] << [6,1,8] << [1,2,3], t
198
+
199
+ t = @table.sort_rows_by("c", :order => :descending )
200
+ assert_equal Table(%w[a b c]) << [6,1,8] << [9,1,4] << [1,2,3], t
201
+ end
202
+
203
+ def specify_show_put_rows_with_nil_columns_after_sorted_rows
204
+ # should not effect when using columns that are all populated
205
+ t = @table_with_nils.sort_rows_by("a")
206
+ assert_equal Table(%w[a b c]) << [1,nil,3] << [6,1,8] << [9,3,4], t
207
+
208
+ t = @table_with_nils.sort_rows_by("b")
209
+ assert_equal Table(%w[a b c]) << [6,1,8] << [9,3,4] << [1,nil,3], t
210
+
211
+ t = @table_with_nils.sort_rows_by("b", :order => :descending)
212
+ assert_equal Table(%w[a b c]) << [1,nil,3] << [9,3,4] << [6,1,8], t
213
+ end
214
+
215
+ def specify_in_place_sort_should_allow_order_by
216
+ @table.sort_rows_by!("a", :order => :descending )
217
+ assert_equal Table(%w[a b c]) << [9,1,4] << [6,1,8] << [1,2,3], @table
218
+ end
219
+
220
+ def specify_sort_rows_by
221
+ table = Ruport::Data::Table.new :column_names => %w[a b c]
222
+ table << [1,2,3] << [6,1,8] << [9,1,4]
223
+
224
+ table2 = Ruport::Data::Table.new :column_names => [:a, :b, :c]
225
+ table2 << [1,2,3] << [6,1,8] << [9,1,4]
226
+
227
+ sorted_table_a = Ruport::Data::Table.new :column_names => %w[a b c]
228
+ sorted_table_a << [1,2,3] << [6,1,8] << [9,1,4]
229
+
230
+ sorted_table_b = Ruport::Data::Table.new :column_names => %w[a b c]
231
+ sorted_table_b << [6,1,8] << [9,1,4] << [1,2,3]
232
+
233
+ sorted_table_bc = Ruport::Data::Table.new :column_names => %w[a b c]
234
+ sorted_table_bc << [9,1,4] << [6,1,8] << [1,2,3]
235
+
236
+ sorted_table_bs = Ruport::Data::Table.new :column_names => [:a, :b, :c]
237
+ sorted_table_bs << [6,1,8] << [9,1,4] << [1,2,3]
238
+
239
+ assert_equal sorted_table_a, table.sort_rows_by {|r| r['a']}
240
+ assert_equal sorted_table_b, table.sort_rows_by(['b'])
241
+ assert_equal sorted_table_bc, table.sort_rows_by(['b', 'c'])
242
+ assert_equal sorted_table_bs, table2.sort_rows_by(:b)
243
+ end
244
+
245
+ def specify_sort_rows_by!
246
+ table = Ruport::Data::Table.new :column_names => %w[a b c]
247
+ table << [1,2,3] << [6,1,8] << [9,1,4]
248
+
249
+ sorted_table_a = Ruport::Data::Table.new :column_names => %w[a b c]
250
+ sorted_table_a << [1,2,3] << [6,1,8] << [9,1,4]
251
+
252
+ sorted_table_b = Ruport::Data::Table.new :column_names => %w[a b c]
253
+ sorted_table_b << [6,1,8] << [9,1,4] << [1,2,3]
254
+
255
+ sorted_table_bc = Ruport::Data::Table.new :column_names => %w[a b c]
256
+ sorted_table_bc << [9,1,4] << [6,1,8] << [1,2,3]
257
+
258
+ table_a = table.dup
259
+ table_a.sort_rows_by! { |r| r['a'] }
260
+
261
+ table_b = table.dup
262
+ table_b.sort_rows_by!("b")
263
+
264
+ table_bc = table.dup
265
+ table_bc.sort_rows_by!(['b', 'c'])
266
+
267
+ assert_equal sorted_table_a, table_a
268
+ assert_equal sorted_table_b, table_b
269
+ assert_equal sorted_table_bc, table_bc
270
+ end
271
+
272
+ end
273
+
274
+ def test_record_class
275
+ a = Ruport::Data::Table.new( :column_names => %w[first_name last_name c],
276
+ :data =>[['joe','loop',3],['jim','blue',6]],
277
+ :record_class => Person )
278
+ assert_equal a, Table(%w[first_name last_name c],
279
+ :data => [ ['joe','loop',3],['jim','blue',6] ])
280
+ assert_kind_of Person, a[0]
281
+ assert_equal 'joe loop', a[0].name
282
+ assert_equal 'jim blue', a[1].name
283
+
284
+ b = Table(%w[first_name last_name], :record_class => Person) do |t|
285
+ t << { 'first_name' => 'joe', 'last_name' => 'frasier' }
286
+ t << { 'first_name' => 'brian', 'last_name' => 'black' }
287
+ end
288
+
289
+ b.each { |r| assert_kind_of Person, r }
290
+
291
+ assert_equal ['joe frasier', 'brian black'], b.map { |r| r.name }
292
+ end
293
+
294
+ ## BUG Traps -------------------------------------------------
295
+
296
+ def test_ensure_table_creation_allows_record_coercion
297
+ table = Table([], :data => [[1,2,3],[4,5,6],[7,8,9]])
298
+ table_with_names = Table(%w[a b c], :data => [[1,2,3],[4,5,6],[7,8,9]])
299
+
300
+ a,b,c = nil
301
+ assert_nothing_raised { a = Table(%w[a b c], :data => table.to_a) }
302
+ assert_nothing_raised { b = Table(%w[d e f], :data => table.to_a) }
303
+ assert_nothing_raised { c = Table(table_with_names.column_names,
304
+ :data => table_with_names.to_a) }
305
+
306
+ [a,b,c].each { |t| assert_equal(3,t.length) }
307
+ assert_equal %w[a b c], a.column_names
308
+ a.each { |r|
309
+ assert_equal %w[a b c], r.attributes
310
+ assert_nothing_raised { r.a; r.b; r.c }
311
+ [r.a,r.b,r.c].each { |i| assert(i.kind_of?(Numeric)) }
312
+ }
313
+ assert_equal %w[d e f], b.column_names
314
+ b.each { |r|
315
+ assert_equal %w[d e f], r.attributes
316
+ assert_nothing_raised { r.d; r.e; r.f }
317
+ [r.d,r.e,r.f].each { |i| assert(i.kind_of?(Numeric)) }
318
+ }
319
+ c.each { |r|
320
+ assert_nothing_raised { r[0]; r[1]; r[2] }
321
+ [r[0],r[1],r[2]].each { |i| assert(i.kind_of?(Numeric)) }
322
+ }
323
+ end
324
+
325
+ def test_ensure_coerce_sum
326
+ s = Table([], :data => [["1"],["3"],["5"]])
327
+ t = Table([], :data => [["1.23"],["1.5"]])
328
+
329
+ assert_equal(9,s.sum(0))
330
+ assert_equal(2.73,t.sum(0))
331
+ end
332
+
333
+ def test_to_yaml
334
+ require "yaml"
335
+ a = Table([])
336
+ assert_nothing_raised { a.to_yaml }
337
+ a = Table(%w[first_name last_name],:record_class => Person) { |t|
338
+ t << %w[joe loop]
339
+ }
340
+ assert_equal "joe loop", a[0].name
341
+ assert_nothing_raised { a.to_yaml }
342
+ end
343
+
344
+ def test_ensure_subtable_works_with_unnamed_tables
345
+ a = Table([], :data => [[1,2,3],[4,5,6]])
346
+ b = a.sub_table { |r| (r[0] % 2).zero? }
347
+ assert_equal Table([], :data => [[4,5,6]]), b
348
+ end
349
+
350
+ def test_ensure_appending_records_works_with_unnamed_tables
351
+ a = Table([], :data => [[1,2,3],[4,5,6]])
352
+ a << Ruport::Data::Record.new([7,8,9])
353
+ assert_equal Table([], :data => [[1,2,3],[4,5,6],[7,8,9]]),a
354
+ end
355
+
356
+ def test_ensure_propagate_record_class
357
+ a = Table(:record_class => DuckRecord)
358
+ assert_equal DuckRecord, a.record_class
359
+
360
+ b = a.dup
361
+ assert_equal DuckRecord, b.record_class
362
+ end
363
+
364
+ def test_ensure_reorder_raises_on_bad_reorder_use
365
+ a = Table() << [1,2,3] << [4,5,6]
366
+ assert_raise(ArgumentError) { a.reorder("a","b","c") }
367
+ assert_raise(ArgumentError) { a.reorder(%w[a b c]) }
368
+ assert_raise(ArgumentError) { a.reorder(2,1,0) }
369
+ end
370
+
371
+ class MySubClass < Ruport::Data::Table; end
372
+
373
+ def test_ensure_table_subclasses_render_properly
374
+ a = MySubClass.new
375
+ a << [1,2,3] << [4,5,6]
376
+ assert_equal("1,2,3\n4,5,6\n",a.as(:csv))
377
+ end
378
+
379
+ end
380
+
381
+ class TestTableAppendOperations < Test::Unit::TestCase
382
+ def test_append_record
383
+ table = Ruport::Data::Table.new :column_names => %w[a b c]
384
+ table << Ruport::Data::Record.new([1,2,3], :attributes => %w[a b c])
385
+ assert_equal([1,2,3],table[0].to_a)
386
+ assert_equal(%w[a b c],table[0].attributes)
387
+ rec = table[0].dup
388
+ rec.attributes = %w[a b c d]
389
+ assert_raise(NoMethodError) { table << Object.new }
390
+ end
391
+
392
+ def test_append_hash
393
+ table = Table(%w[a b c], :data => [[1,2,3],[4,5,6]])
394
+ table << { "a" => 7, "c" => 9, "b" => 8 }
395
+
396
+ assert_equal Table(%w[a b c], :data => [[1,2,3],[4,5,6],[7,8,9]]), table
397
+ end
398
+
399
+ def test_append_table
400
+ first = Ruport::Data::Table.new :column_names => %w[a b c],
401
+ :data => [[1,2,3],[4,5,6]]
402
+
403
+ second = Ruport::Data::Table.new :column_names => %w[a b c],
404
+ :data => [[7,8,9],[10,11,12]]
405
+
406
+ combo = first + second
407
+
408
+ assert_equal Ruport::Data::Table.new(:column_names => %w[a b c],
409
+ :data => [[1,2,3],[4,5,6],[7,8,9],[10,11,12]]), combo
410
+ end
411
+
412
+ def test_append_chain
413
+ table = Ruport::Data::Table.new :column_names => %w[a b c]
414
+ table << [1,2,3] << [4,5,6] << [7,8,9]
415
+ assert_equal 3, table.length
416
+ assert_equal 5, table[1].b
417
+ end
418
+ end
419
+
420
+ class TestTableFormattingHooks < Test::Unit::TestCase
421
+
422
+ def test_to_hack_takes_args
423
+ a = Table(%w[hello mr crowley]) << %w[would you like] << %w[one red cat]
424
+
425
+ assert_equal "would,you,like\none,red,cat\n",
426
+ a.to_csv(:show_table_headers => false)
427
+
428
+ assert_equal "would,you,like\none,red,cat\n",
429
+ a.to_csv { |r| r.options.show_table_headers = false }
430
+
431
+ assert_equal "would\tyou\tlike\none\tred\tcat\n",
432
+ a.to_csv(:show_table_headers => false) { |r|
433
+ r.options.format_options = { :col_sep => "\t" }
434
+ }
435
+ end
436
+
437
+ def test_to_hack
438
+ table = Ruport::Data::Table.new :column_names => %w[a b],
439
+ :data => [[1,2],[3,4],[5,6]]
440
+ assert_equal("a,b\n1,2\n3,4\n5,6\n",table.to_csv)
441
+ assert_raises(Ruport::Controller::UnknownFormatError) { table.to_nothing }
442
+ end
443
+
444
+ def test_as_throws_proper_errors
445
+ a = Table(%w[a b c], :data => [[1,2,3],[4,5,6]])
446
+ assert_nothing_raised { a.as(:csv) }
447
+ assert_nothing_raised { a.to_csv }
448
+ assert_raises(Ruport::Controller::UnknownFormatError) { a.as(:nothing) }
449
+ assert_raises(Ruport::Controller::UnknownFormatError) { a.to_nothing }
450
+ end
451
+
452
+ end
453
+
454
+ class TestTableColumnOperations < Test::Unit::TestCase
455
+
456
+ def test_column
457
+ a = Table(%w[a b c], :data => [[1,2,3],[4,5,6]])
458
+ assert_equal [3,6], a.column(2)
459
+ assert_equal [2,5], a.column("b")
460
+
461
+ assert_raise(ArgumentError) { a.column("d") }
462
+ assert_raise(ArgumentError) { a.column(42) }
463
+
464
+ a = Table([], :data => [[1],[2],[3],[4]])
465
+ assert_equal [1,2,3,4], a.column(0)
466
+ end
467
+
468
+ def test_set_column_names
469
+ a = Table([], :data => [[1,2,3],[4,5,6]])
470
+
471
+ assert_equal([],a.column_names)
472
+ assert_equal([[1,2,3],[4,5,6]],a.map { |r| r.to_a } )
473
+
474
+ a.column_names = %w[a b c]
475
+ assert_equal(%w[a b c],a.column_names)
476
+ a.each { |r| assert_equal(%w[a b c], r.attributes) }
477
+ assert_equal([[1,2,3],[4,5,6]],a.map { |r| r.to_a })
478
+
479
+ a.column_names = %w[d e f]
480
+ assert_equal(%w[d e f],a.column_names)
481
+ a.each { |r| assert_equal(%w[d e f], r.attributes) }
482
+ assert_equal([[1,2,3],[4,5,6]],a.map { |r| r.to_a })
483
+ end
484
+
485
+ def test_add_column
486
+ a = Table(%w[a b], :data => [[1,2],[3,4],[5,6]])
487
+ a.add_column("c")
488
+ assert_equal Table(%w[a b c], :data => [[1,2,nil],[3,4,nil],[5,6,nil]]), a
489
+
490
+ a = Table(%w[a b], :data => [[1,2],[3,4],[5,6]])
491
+ a.add_column("c",:default => "x")
492
+ assert_equal Table(%w[a b c], :data => [[1,2,'x'],[3,4,'x'],[5,6,'x']]), a
493
+
494
+ b = a.dup
495
+ b.add_column("x",:before => "b")
496
+ assert_equal Table(%w[a x b c],
497
+ :data => [[1,nil,2,'x'],[3,nil,4,'x'],[5,nil,6,'x']]), b
498
+
499
+ b = a.dup
500
+ b.add_column("x",:after => "b")
501
+ assert_equal Table(%w[a b x c],
502
+ :data => [[1,2,nil,'x'],[3,4,nil,'x'],[5,6,nil,'x']]), b
503
+
504
+
505
+ a.add_column("d") { |r| r[0]+r[1] }
506
+ assert_equal Table(%w[a b c d],
507
+ :data => [ [1,2,'x',3],[3,4,'x',7],[5,6,'x',11] ]), a
508
+
509
+ a.add_column("x",:position => 1)
510
+ assert_equal Table(%w[a x b c d],
511
+ :data => [ [1,nil,2,'x',3],[3,nil,4,'x',7],[5,nil,6,'x',11] ]), a
512
+ end
513
+
514
+ def test_add_columns
515
+ a = Table(%w[a b], :data => [[1,2],[3,4],[5,6]])
516
+ a.add_columns(%w[c d])
517
+ expected = Table(%w[a b c d],
518
+ :data => [ [1,2,nil,nil],[3,4,nil,nil],[5,6,nil,nil] ])
519
+
520
+ assert_equal expected, a
521
+
522
+ a = Table(%w[a b], :data => [[1,2],[3,4],[5,6]])
523
+
524
+ a.add_columns(%w[c d],:after => "a")
525
+
526
+ expected = Table(%w[a c d b],
527
+ :data => [ [1,nil,nil,2],[3,nil,nil,4],[5,nil,nil,6], ])
528
+
529
+ assert_equal expected, a
530
+
531
+ a.add_columns(%w[x f],:before => "a")
532
+
533
+ expected = Table(%w[x f a c d b],
534
+ :data => [ [nil,nil,1,nil,nil,2],
535
+ [nil,nil,3,nil,nil,4],
536
+ [nil,nil,5,nil,nil,6] ])
537
+
538
+ assert_equal expected, a
539
+
540
+ a = Table(%w[a b c], :data => [[1,2,0],[3,4,0],[5,6,0]])
541
+
542
+ a.add_columns(%w[x y],:default => 9, :position => 1)
543
+
544
+ expected = Table(%w[a x y b c],
545
+ :data => [[1,9,9,2,0],[3,9,9,4,0],[5,9,9,6,0]])
546
+
547
+ assert_equal expected, a
548
+
549
+ a = Table(%w[a b], :data => [[1,2],[3,4],[5,6]])
550
+ a.add_columns(%w[f x],:default => 0)
551
+
552
+ expected = Table(%w[a b f x], :data => [[1,2,0,0],[3,4,0,0],[5,6,0,0]])
553
+ assert_equal expected, a
554
+
555
+ assert_raises(RuntimeError) do
556
+ a.add_columns(%w[a b]) { }
557
+ end
558
+ end
559
+
560
+ def test_remove_column
561
+ a = Table(%w[a b c]) { |t| t << [1,2,3] << [4,5,6] }
562
+ b = a.dup
563
+
564
+ a.remove_column("b")
565
+ assert_equal Table(%w[a c]) { |t| t << [1,3] << [4,6] }, a
566
+
567
+ b.remove_column(2)
568
+ assert_equal Table(%w[a b]) { |t| t << [1,2] << [4,5] }, b
569
+ end
570
+
571
+ def test_remove_columns
572
+ a = Table(%w[a b c d]) { |t| t << [1,2,3,4] << [5,6,7,8] }
573
+ b = a.dup
574
+ a.remove_columns("b","d")
575
+ assert_equal Table(%w[a c]) { |t| t << [1,3] << [5,7] }, a
576
+ b.remove_columns(%w[a c])
577
+ assert_equal Table(%w[b d]) { |t| t << [2,4] << [6,8] }, b
578
+ end
579
+
580
+ def test_rename_column
581
+ a = Table(%w[a b]) { |t| t << [1,2] << [3,4] }
582
+ a.rename_column("b","x")
583
+ assert_equal Table(%w[a x]) { |t| t << [1,2] << [3,4] }, a
584
+ end
585
+
586
+ def test_rename_columns
587
+ a = Table(%w[a b]) { |t| t << [1,2] << [3,4] }
588
+ a.rename_columns(%w[a b], %w[x y])
589
+ assert_equal Table(%w[x y]) { |t| t << [1,2] << [3,4] }, a
590
+
591
+ a = Table(%w[a b]) { |t| t << [1,2] << [3,4] }
592
+ a.rename_columns("a"=>"x","b"=>"y")
593
+ assert_equal Table(%w[x y]) { |t| t << [1,2] << [3,4] }, a
594
+
595
+ a = Table(%w[a b]) { |t| t << [1,2] << [3,4] }
596
+ assert_raise(ArgumentError) { a.rename_columns(%w[a b], %w[x]) }
597
+
598
+ a = Table(%w[a b c]) { |t| t << [1,2,3] << [4,5,6] }
599
+ a.rename_columns { |r| r.to_sym }
600
+ assert_equal(a, Table(:a,:b,:c) { |t| t << [1,2,3] << [4,5,6] })
601
+
602
+ a = Table(%w[a b c]) { |t| t << [1,2,3] << [4,5,6] }
603
+ a.rename_columns(%w[a c]) { |r| r.to_sym }
604
+ assert_equal(a, Table(:a,"b",:c) { |t| t << [1,2,3] << [4,5,6] })
605
+ end
606
+
607
+ def test_swap_column
608
+ a = Table(%w[a b]) { |t| t << [1,2] << [3,4] }
609
+ a.swap_column("a","b")
610
+ assert_equal Table(%w[b a]) { |t| t << [2,1] << [4,3] }, a
611
+ a.swap_column(1,0)
612
+ assert_equal Table(%w[a b]) { |t| t << [1,2] << [3,4] }, a
613
+ end
614
+
615
+ def test_replace_column
616
+ a = Table(%w[a b c]) { |t| t << [1,2,3] << [4,5,6] }
617
+ a.replace_column("b","d") { |r| r.b.to_s }
618
+ assert_equal Table(%w[a d c]) { |t| t << [1,"2",3] << [4,"5",6] }, a
619
+ a.replace_column("d") { |r| r.d.to_i }
620
+ assert_equal Table(%w[a d c]) { |t| t << [1,2,3] << [4,5,6] }, a
621
+ end
622
+
623
+ # --- BUG TRAPS ------------------------------------
624
+
625
+ def test_ensure_setting_column_names_changes_record_attributes
626
+ table = Ruport::Data::Table.new :column_names => %w[a b c],
627
+ :data => [[1,2,3],[4,5,6]]
628
+
629
+ assert_equal %w[a b c], table.column_names
630
+ assert_equal %w[a b c], table.data[0].attributes
631
+ assert_equal %w[a b c], table.data[1].attributes
632
+
633
+ table.column_names = %w[d e f]
634
+
635
+ assert_equal %w[d e f], table.column_names
636
+ assert_equal %w[d e f], table.data[0].attributes
637
+ assert_equal %w[d e f], table.data[1].attributes
638
+ end
639
+
640
+ def test_ensure_setting_column_names_later_does_not_break_replace_column
641
+ a = Table(%w[a b c], :data => [[1,2,3],[4,5,6]])
642
+ a.replace_column("b","q") { |r| r.a + r.c }
643
+ a.column_names = %w[d e f]
644
+ assert_equal Table(%w[d e f], :data => [[1,4,3],[4,10,6]]), a
645
+
646
+ a = Table([], :data => [[1,2,3],[4,5,6]])
647
+
648
+ a.replace_column(1) { |r| r[0] + r[2] }
649
+
650
+ a.column_names = %w[d e f]
651
+ assert_equal Table(%w[d e f], :data => [[1,4,3],[4,10,6]]), a
652
+
653
+ a = Table([], :data => [[1,2,3],[4,5,6]])
654
+
655
+ a.replace_column(2) { |r| r[0] + 5 }
656
+
657
+ a.column_names = %w[a b c]
658
+
659
+ a.replace_column("b") { |r| r.a + 4 }
660
+ a.replace_column("b","foo") { |r| r.b + 1 }
661
+
662
+ assert_equal Table(%w[a foo c], :data => [[1,6,6],[4,9,9]]), a
663
+ end
664
+
665
+ def test_ensure_renaming_a_missing_column_fails_silently
666
+ a = Table(%w[a b c])
667
+ assert_nothing_raised do
668
+ a.rename_column("d", "z")
669
+ end
670
+ end
671
+
672
+ end
673
+
674
+ class TestTableFromCSV < Test::Unit::TestCase
675
+
676
+ def test_csv_load
677
+ table = Ruport::Data::Table.load(File.join(TEST_SAMPLES,"data.csv"))
678
+ assert_equal %w[col1 col2 col3], table.column_names
679
+ rows = [%w[a b c],["d",nil,"e"]]
680
+ table.each { |r| assert_equal rows.shift, r.to_a
681
+ assert_equal %w[col1 col2 col3], r.attributes }
682
+ expected = Table(%w[a b c], :data => [%w[1 2 3],%w[4 5 6]])
683
+
684
+ # ticket:94
685
+ table = Ruport::Data::Table.load( File.join(TEST_SAMPLES,"data.tsv"),
686
+ :csv_options => { :col_sep => "\t" } )
687
+ assert_equal expected, table
688
+
689
+ expected = ['c','e']
690
+
691
+ table = Ruport::Data::Table.load( File.join(TEST_SAMPLES,"data.csv"),
692
+ :csv_options => { :headers => true, :header_converters => :symbol }
693
+ ) do |s,r|
694
+ assert_equal expected.shift, r[:col3]
695
+ end
696
+
697
+ assert_equal [:col1,:col2,:col3], table.column_names
698
+
699
+ expected = ['c','e']
700
+
701
+ Ruport::Data::Table.load( File.join(TEST_SAMPLES,"data.csv"),
702
+ :records => true ) do |s,r|
703
+ assert_equal expected.shift, r.col3
704
+ assert_kind_of Ruport::Data::Record, r
705
+ end
706
+
707
+ table = Ruport::Data::Table.load( File.join(TEST_SAMPLES, "data.csv"),
708
+ :has_names => false )
709
+ assert_equal([],table.column_names)
710
+ assert_equal(Table([],
711
+ :data => [%w[col1 col2 col3],%w[a b c],["d",nil,"e"]]), table)
712
+ end
713
+
714
+ # ticket:76
715
+ def test_parse
716
+ assert_nothing_raised {
717
+ Ruport::Data::Table.parse("a,b,c\n1,2,3\n")
718
+ }
719
+
720
+ table = Ruport::Data::Table.parse("a,b,c\n1,2,3\n4,5,6\n")
721
+ expected = Table(%w[a b c], :data => [%w[1 2 3],%w[4 5 6]])
722
+
723
+ table = Ruport::Data::Table.parse( "a\tb\tc\n1\t2\t3\n4\t5\t6\n",
724
+ :csv_options => { :col_sep => "\t" } )
725
+ assert_equal expected, table
726
+
727
+ table = Ruport::Data::Table.parse( "a,b,c\n1,2,3\n4,5,6\n",
728
+ :has_names => false)
729
+ assert_equal([],table.column_names)
730
+ assert_equal(Table([], :data => [%w[a b c],%w[1 2 3],%w[4 5 6]]), table)
731
+ end
732
+
733
+ def test_csv_block_form
734
+ expected = [%w[a b],%w[1 2],%w[3 4]]
735
+ t = Ruport::Data::Table.send(:get_table_from_csv,
736
+ :parse, "a,b\n1,2\n3,4",
737
+ :has_names => false) do |s,r|
738
+ assert_equal expected.shift, r
739
+ s << r
740
+ end
741
+ assert_equal Table([], :data => [%w[a b],%w[1 2],%w[3 4]]), t
742
+ end
743
+
744
+ # - BUG TRAPS --------------------
745
+
746
+ def test_ensure_using_csv_block_mode_works
747
+ expected = [%w[a b],%w[1 2],%w[3 4]]
748
+ t = Ruport::Data::Table.parse("a,b\n1,2\n3,4",:has_names => false) { |s,r|
749
+ assert_equal expected.shift, r
750
+ s << r
751
+ s << r
752
+ }
753
+ assert_equal Table([],
754
+ :data => [%w[a b],%w[a b],%w[1 2], %w[1 2],%w[3 4],%w[3 4]]), t
755
+ x = Ruport::Data::Table.load(File.join(TEST_SAMPLES,"data.csv")) { |s,r|
756
+ assert_kind_of Ruport::Data::Feeder, s
757
+ assert_kind_of Array, r
758
+ s << r
759
+ s << r
760
+ }
761
+ assert_equal 4, x.length
762
+ end
763
+
764
+ def test_ensure_csv_loading_accepts_table_options
765
+ a = Table(File.join(TEST_SAMPLES,"addressbook.csv"),
766
+ :record_class => DuckRecord)
767
+ a.each { |r| assert_kind_of(DuckRecord,r) }
768
+ end
769
+
770
+ def test_ensure_table_from_csv_accepts_record_class_in_block_usage
771
+ a = Table(File.join(TEST_SAMPLES,"addressbook.csv"),
772
+ :record_class => DuckRecord, :records => true) do |s,r|
773
+ assert_kind_of(DuckRecord,r)
774
+ end
775
+ end
776
+
777
+ end
778
+
779
+ class TestTableKernelHack < Test::Unit::TestCase
780
+
781
+ def test_simple
782
+ assert_equal Ruport::Data::Table.new(:column_names => %w[a b c]),
783
+ Table(%w[a b c])
784
+ assert_equal Ruport::Data::Table.new(:column_names => %w[a b c]),
785
+ Table("a","b","c")
786
+ assert_equal Ruport::Data::Table.load(
787
+ File.join(TEST_SAMPLES,"addressbook.csv")),
788
+ Table(File.join(TEST_SAMPLES,"addressbook.csv"))
789
+ assert_equal Ruport::Data::Table.load(
790
+ File.join(TEST_SAMPLES,"addressbook.csv"), :has_names => false),
791
+ Table(File.join(TEST_SAMPLES,"addressbook.csv"), :has_names => false)
792
+ Table("a","b","c") do |t|
793
+ t << [1,2,3]
794
+ assert_equal(
795
+ Ruport::Data::Table.new(:column_names => %w[a b c], :data => [[1,2,3]]),
796
+ t.data
797
+ )
798
+ end
799
+
800
+ assert_equal Table("a"), Table(%w[a])
801
+ assert_equal Table(:a), Table([:a])
802
+ end
803
+
804
+ def test_iterators
805
+ Table(File.join(TEST_SAMPLES,"addressbook.csv")) do |s,r|
806
+ assert_kind_of(Array,r)
807
+ assert_kind_of(Ruport::Data::Feeder,s)
808
+ end
809
+
810
+ n = 0
811
+
812
+ Table(:string => "a,b,c\n1,2,3\n4,5,6\n") do |s,r|
813
+ assert_kind_of(Array,r)
814
+ assert_kind_of(Ruport::Data::Feeder,s)
815
+ n += 1
816
+ end
817
+
818
+ assert_equal 2, n
819
+ end
820
+
821
+ def test_with_file_arg
822
+ assert_equal Table(File.join(TEST_SAMPLES,"addressbook.csv")),
823
+ Table(:file => File.join(TEST_SAMPLES,"addressbook.csv"))
824
+ end
825
+
826
+ def test_with_string_arg
827
+ csv_string = "id,name\n1,Inky\n2,Blinky\n3,Clyde"
828
+
829
+ assert_equal Ruport::Data::Table.parse(csv_string),
830
+ Table(:string => csv_string)
831
+ end
832
+
833
+ def test_ensure_table_hack_accepts_normal_constructor_args
834
+ assert_equal Ruport::Data::Table.new(:column_names => %w[a b c]),
835
+ Table(:column_names => %w[a b c])
836
+ end
837
+
838
+ end