ruport 0.6.0 → 0.6.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 +4 -0
- data/CHANGELOG +10 -1
- data/Rakefile +1 -1
- data/examples/simple_table_interface.rb +20 -0
- data/lib/ruport.rb +87 -69
- data/lib/ruport/attempt.rb +1 -1
- data/lib/ruport/config.rb +198 -166
- data/lib/ruport/data.rb +6 -1
- data/lib/ruport/data/collection.rb +15 -8
- data/lib/ruport/data/groupable.rb +68 -6
- data/lib/ruport/data/record.rb +73 -34
- data/lib/ruport/data/record.rb~ +236 -0
- data/lib/ruport/data/set.rb +48 -13
- data/lib/ruport/data/table.rb +164 -74
- data/lib/ruport/data/table.rb.rej +67 -0
- data/lib/ruport/data/table.rb~ +153 -68
- data/lib/ruport/data/taggable.rb +37 -9
- data/lib/ruport/format.rb +1 -1
- data/lib/ruport/mailer.rb +41 -27
- data/lib/ruport/meta_tools.rb +26 -11
- data/lib/ruport/query.rb +102 -68
- data/lib/ruport/query/sql_split.rb +1 -1
- data/lib/ruport/report.rb +84 -58
- data/lib/ruport/report/graph.rb +1 -1
- data/lib/ruport/report/invoice.rb +1 -1
- data/test/test_query.rb +305 -48
- data/test/test_query.rb.rej +161 -0
- data/test/test_query.rb~ +337 -0
- data/test/test_record.rb +6 -0
- data/test/test_table.rb +18 -0
- data/test/test_table.rb~ +336 -0
- data/test/unit.log +180 -6
- metadata +8 -2
data/lib/ruport/data/set.rb
CHANGED
@@ -7,6 +7,9 @@ require 'set'
|
|
7
7
|
|
8
8
|
module Ruport::Data
|
9
9
|
|
10
|
+
#
|
11
|
+
# === Overview
|
12
|
+
#
|
10
13
|
# This class is one of the core classes for building and working with data
|
11
14
|
# in Ruport. The idea is to get your data into a standard form, regardless
|
12
15
|
# of its source (a database, manual arrays, ActiveRecord, CSVs, etc.).
|
@@ -17,19 +20,29 @@ module Ruport::Data
|
|
17
20
|
#
|
18
21
|
# Once your data is in a Ruport::Data::Set object, it can be manipulated
|
19
22
|
# to suit your needs, then used to build a report.
|
23
|
+
#
|
20
24
|
class Set < Collection
|
21
25
|
|
22
|
-
#
|
26
|
+
#
|
27
|
+
# Creates a new Set containing the elements of <tt>options[:data]</tt>.
|
28
|
+
#
|
29
|
+
# Example:
|
23
30
|
#
|
24
31
|
# Set.new :data => [%w[one two three] %w[1 2 3] %w[I II III]]
|
32
|
+
#
|
25
33
|
def initialize(options={})
|
26
34
|
@data = ::Set.new
|
27
35
|
options[:data].each {|e| self << e} if options[:data]
|
28
36
|
end
|
29
37
|
|
30
|
-
#
|
38
|
+
#
|
39
|
+
# Adds the given object to the Set and returns self.
|
40
|
+
#
|
41
|
+
# Example:
|
42
|
+
#
|
31
43
|
# set = Set.new :data => [%w[one two three]]
|
32
44
|
# set << [5,6,7]
|
45
|
+
#
|
33
46
|
def add(other)
|
34
47
|
case other
|
35
48
|
when Record
|
@@ -41,14 +54,18 @@ module Ruport::Data
|
|
41
54
|
end
|
42
55
|
alias_method :<<, :add
|
43
56
|
|
44
|
-
#
|
45
|
-
#
|
57
|
+
#
|
58
|
+
# Produces a shallow copy of the Set: the same data elements are
|
59
|
+
# referenced by both the old and new Sets.
|
60
|
+
#
|
61
|
+
# Example:
|
46
62
|
#
|
47
63
|
# set = Set.new :data => [%w[one two three]]
|
48
64
|
# set2 = set.dup
|
49
65
|
# set == set2 #=> true
|
50
66
|
# set << [8,9,10]
|
51
67
|
# set == set2 #=> false
|
68
|
+
#
|
52
69
|
def dup
|
53
70
|
a = self.class.new(:data=>@data)
|
54
71
|
a.tags = tags.dup
|
@@ -56,62 +73,80 @@ module Ruport::Data
|
|
56
73
|
end
|
57
74
|
alias_method :clone, :dup
|
58
75
|
|
59
|
-
#
|
76
|
+
#
|
77
|
+
# Two Sets are equal if they contain the same set of objects.
|
78
|
+
#
|
79
|
+
# Example:
|
60
80
|
# s1 = Set.new :data => [[1,2,3]]
|
61
81
|
# s2 = Set.new :data => [[1,2,3]]
|
62
82
|
# s1 == s2 #=> true
|
83
|
+
#
|
63
84
|
def ==(other)
|
64
85
|
@data == other.data
|
65
86
|
end
|
66
87
|
|
67
|
-
#
|
68
|
-
# the two
|
88
|
+
# Returns a new Set containing the all of the objects contained in either
|
89
|
+
# of the two Sets.
|
90
|
+
#
|
91
|
+
# Example:
|
69
92
|
#
|
70
93
|
# s1 = Set.new :data => [[1,2,3]]
|
71
94
|
# s2 = Set.new :data => [[4,5,6]]
|
72
95
|
# s3 = s1 | s2
|
73
96
|
# s4 = Set.new :data => [[1,2,3], [4,5,6]]
|
74
97
|
# s3 == s4 #=> true
|
98
|
+
#
|
75
99
|
def |(other)
|
76
100
|
Set.new :data => (@data | other.data)
|
77
101
|
end
|
78
102
|
alias_method :union, :|
|
79
103
|
alias_method :+, :|
|
80
104
|
|
81
|
-
#
|
82
|
-
#
|
105
|
+
#
|
106
|
+
# Returns a new Set containing the objects common to the two Sets.
|
107
|
+
#
|
108
|
+
# Example:
|
83
109
|
#
|
84
110
|
# s1 = Set.new :data => [%w[a b c],[1,2,3]]
|
85
111
|
# s2 = Set.new :data => [%w[a b c],[4,5,6]]
|
86
112
|
# s3 = s1 & s2
|
87
113
|
# s4 = Set.new :data => [%w[a b c]]
|
88
114
|
# s3 == s4 #=> true
|
115
|
+
#
|
89
116
|
def &(other)
|
90
117
|
Set.new :data => (@data & other.data)
|
91
118
|
end
|
92
119
|
alias_method :intersection, :&
|
93
120
|
|
94
|
-
#
|
95
|
-
#
|
121
|
+
#
|
122
|
+
# Returns a new Set containing those objects present in this Set but not
|
123
|
+
# the other.
|
124
|
+
#
|
125
|
+
# Example:
|
96
126
|
#
|
97
127
|
# s1 = Set.new :data => [%w[a b c],[1,2,3]]
|
98
128
|
# s2 = Set.new :data => [%w[a b c],[4,5,6]]
|
99
129
|
# s3 = s1 - s2
|
100
130
|
# s4 = Set.new :data => [[1, 2, 3]]
|
101
131
|
# s3 == s4 #=> true
|
132
|
+
#
|
102
133
|
def -(other)
|
103
134
|
Set.new :data => (@data - other.data)
|
104
135
|
end
|
105
136
|
alias_method :difference, :-
|
106
137
|
|
107
|
-
#
|
108
|
-
#
|
138
|
+
#
|
139
|
+
# Returns a new Set containing those objects that are either in this Set
|
140
|
+
# or the other Set but not in both.
|
141
|
+
#
|
142
|
+
# Example:
|
109
143
|
#
|
110
144
|
# s1 = Set.new :data => [%w[a b c],[1,2,3]]
|
111
145
|
# s2 = Set.new :data => [%w[a b c],[4,5,6]]
|
112
146
|
# s3 = s1 ^ s2
|
113
147
|
# s4 = Set.new :data => [[1, 2, 3],[4,5,6]]
|
114
148
|
# s3 == s4 #=> true
|
149
|
+
#
|
115
150
|
def ^(other)
|
116
151
|
Set.new :data => (@data ^ other.data)
|
117
152
|
end
|
data/lib/ruport/data/table.rb
CHANGED
@@ -5,10 +5,14 @@
|
|
5
5
|
# Copyright 2006 by respective content owners, all rights reserved.
|
6
6
|
|
7
7
|
class Array
|
8
|
+
|
9
|
+
#
|
8
10
|
# Converts an array to a Ruport::Data::Table object, ready to
|
9
11
|
# use in your reports.
|
10
12
|
#
|
13
|
+
# Example:
|
11
14
|
# [[1,2],[3,4]].to_table(%w[a b])
|
15
|
+
#
|
12
16
|
def to_table(options={})
|
13
17
|
options = { :column_names => options } if options.kind_of? Array
|
14
18
|
Ruport::Data::Table.new({:data => self}.merge(options))
|
@@ -16,7 +20,10 @@ class Array
|
|
16
20
|
end
|
17
21
|
|
18
22
|
module Ruport::Data
|
19
|
-
|
23
|
+
|
24
|
+
#
|
25
|
+
# === Overview
|
26
|
+
#
|
20
27
|
# This class is one of the core classes for building and working with data
|
21
28
|
# in Ruport. The idea is to get your data into a standard form, regardless
|
22
29
|
# of its source (a database, manual arrays, ActiveRecord, CSVs, etc.).
|
@@ -28,17 +35,21 @@ module Ruport::Data
|
|
28
35
|
# Once your data is in a Ruport::Data::Table object, it can be manipulated
|
29
36
|
# to suit your needs, then used to build a report.
|
30
37
|
#
|
31
|
-
# Included in this class are methods to create Tables manually and from CSV
|
32
|
-
# files.
|
33
|
-
#
|
34
|
-
# For building a table using ActiveRecord, have a look at Ruport::Reportable.
|
35
38
|
class Table < Collection
|
36
39
|
include Groupable
|
40
|
+
|
41
|
+
#
|
37
42
|
# Creates a new table based on the supplied options.
|
38
|
-
# Valid options
|
43
|
+
# Valid options:
|
44
|
+
# <b><tt>:data</tt></b>:: An Array of Arrays representing the
|
45
|
+
# records in this Table
|
46
|
+
# <b><tt>:column_names</tt></b>:: An Array containing the column names
|
47
|
+
# for this Table.
|
48
|
+
# Example:
|
49
|
+
#
|
50
|
+
# table = Table.new :data => [[1,2,3], [3,4,5]],
|
51
|
+
# :column_names => %w[a b c]
|
39
52
|
#
|
40
|
-
# table = Table.new({:data => [1,2,3], [3,4,5],
|
41
|
-
# :column_names => %w[a b c]})
|
42
53
|
def initialize(options={})
|
43
54
|
@column_names = options[:column_names] ? options[:column_names].dup : []
|
44
55
|
@data = []
|
@@ -52,44 +63,70 @@ module Ruport::Data
|
|
52
63
|
end
|
53
64
|
end
|
54
65
|
|
66
|
+
# This Table's column names.
|
55
67
|
attr_reader :column_names
|
56
68
|
def_delegator :@data, :[]
|
57
|
-
|
58
|
-
#
|
69
|
+
|
70
|
+
#
|
71
|
+
# Sets the column names for this table. <tt>new_column_names</tt> should
|
72
|
+
# be an array listing the names of the columns.
|
73
|
+
#
|
74
|
+
# Example:
|
59
75
|
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
|
63
|
-
|
76
|
+
# table = Table.new :data => [1,2,3], [3,4,5],
|
77
|
+
# :column_names => %w[a b c]
|
78
|
+
#
|
79
|
+
# table.column_names = %w[e f g]
|
80
|
+
#
|
81
|
+
def column_names=(new_column_names)
|
82
|
+
@column_names.replace(new_column_names.dup)
|
64
83
|
end
|
65
84
|
|
66
|
-
# Compares this table to another table and returns true if
|
67
|
-
# both the data and column names are equal
|
68
85
|
#
|
69
|
-
#
|
70
|
-
#
|
86
|
+
# Compares this Table to another Table and returns <tt>true</tt> if
|
87
|
+
# both the <tt>data</tt> and <tt>column_names</tt> are equal.
|
88
|
+
#
|
89
|
+
# Example:
|
90
|
+
#
|
91
|
+
# one = Table.new :data => [1,2], [3,4],
|
92
|
+
# :column_names => %w[a b]
|
93
|
+
#
|
94
|
+
# two = Table.new :data => [1,2], [3,4],
|
95
|
+
# :column_names => %w[a b]
|
96
|
+
#
|
71
97
|
# one.eql?(two) #=> true
|
98
|
+
#
|
72
99
|
def eql?(other)
|
73
100
|
data.eql?(other.data) && column_names.eql?(other.column_names)
|
74
101
|
end
|
75
102
|
|
76
103
|
alias_method :==, :eql?
|
77
104
|
|
78
|
-
#
|
105
|
+
#
|
106
|
+
# Uses Ruport's built-in text plugin to render this Table into a String
|
107
|
+
#
|
108
|
+
# Example:
|
79
109
|
#
|
80
|
-
# data = Table.new
|
110
|
+
# data = Table.new :data => [1,2], [3,4],
|
111
|
+
# :column_names => %w[a b]
|
81
112
|
# puts data.to_s
|
113
|
+
#
|
82
114
|
def to_s
|
83
115
|
as(:text)
|
84
116
|
end
|
85
117
|
|
86
|
-
# Used to add extra data to the table. The single parameter can be an
|
87
|
-
# Array, Hash or Ruport::Data::Record.
|
88
118
|
#
|
89
|
-
#
|
119
|
+
# Used to add extra data to the Table. <tt>other</tt> can be an Array,
|
120
|
+
# Hash or Record.
|
121
|
+
#
|
122
|
+
# Example:
|
123
|
+
#
|
124
|
+
# data = Table.new :data => [1,2], [3,4],
|
125
|
+
# :column_names => %w[a b]
|
90
126
|
# data << [8,9]
|
91
127
|
# data << { :a => 4, :b => 5}
|
92
|
-
# data <<
|
128
|
+
# data << Record.new [5,6], :attributes => %w[a b]
|
129
|
+
#
|
93
130
|
def <<(other)
|
94
131
|
case other
|
95
132
|
when Array
|
@@ -108,26 +145,40 @@ module Ruport::Data
|
|
108
145
|
self
|
109
146
|
end
|
110
147
|
|
111
|
-
#
|
148
|
+
#
|
149
|
+
# Used to combine two Tables. Throws an ArgumentError if the Tables don't
|
112
150
|
# have identical columns.
|
113
151
|
#
|
114
|
-
#
|
115
|
-
#
|
152
|
+
# Example:
|
153
|
+
#
|
154
|
+
# inky = Table.new :data => [[1,2], [3,4]],
|
155
|
+
# :column_names => %w[a b]
|
156
|
+
#
|
157
|
+
# blinky = Table.new :data => [[5,6]],
|
158
|
+
# :column_names => %w[a b]
|
159
|
+
#
|
116
160
|
# sue = inky + blinky
|
117
161
|
# sue.data #=> [[1,2],[3,4],[5,6]]
|
118
|
-
|
162
|
+
#
|
119
163
|
def +(other)
|
120
164
|
raise ArgumentError unless other.column_names == @column_names
|
121
165
|
Table.new(:column_names => @column_names, :data => @data + other.data)
|
122
166
|
end
|
123
167
|
|
124
|
-
# Reorders the columns that exist in the table. Operates directly
|
125
|
-
# on this table.
|
126
168
|
#
|
127
|
-
#
|
169
|
+
# Reorders the columns that exist in the Table. Modifies this Table
|
170
|
+
# in-place.
|
171
|
+
#
|
172
|
+
# Example:
|
173
|
+
#
|
174
|
+
# data = Table.new :data => [1,2], [3,4],
|
175
|
+
# :column_names => %w[a b]
|
176
|
+
#
|
128
177
|
# data.reorder!([1,0])
|
178
|
+
#
|
129
179
|
def reorder!(*indices)
|
130
180
|
indices = indices[0] if indices[0].kind_of? Array
|
181
|
+
|
131
182
|
if @column_names && !@column_names.empty?
|
132
183
|
x = if indices.all? { |i| i.kind_of? Integer }
|
133
184
|
indices.map { |i| @column_names[i] }
|
@@ -142,21 +193,34 @@ module Ruport::Data
|
|
142
193
|
}; self
|
143
194
|
end
|
144
195
|
|
145
|
-
# Returns a copy of the table with its columns in the requested order.
|
146
196
|
#
|
147
|
-
#
|
197
|
+
# Returns a copy of the Table with its columns in the requested order.
|
198
|
+
#
|
199
|
+
# Example:
|
200
|
+
#
|
201
|
+
# one = Table.new :data => [1,2], [3,4],
|
202
|
+
# :column_names => %w[a b]
|
203
|
+
#
|
148
204
|
# two = one.reorder!([1,0])
|
205
|
+
#
|
149
206
|
def reorder(*indices)
|
150
207
|
dup.reorder!(*indices)
|
151
208
|
end
|
152
209
|
|
153
|
-
#
|
154
|
-
#
|
155
|
-
#
|
156
|
-
#
|
210
|
+
#
|
211
|
+
# Adds an extra column to the Table. Available Options:
|
212
|
+
#
|
213
|
+
# <b><tt>:name</tt></b>:: The new column's name (required)
|
214
|
+
# <b><tt>:fill</tt></b>:: The default value to use for the column in
|
215
|
+
# existing rows. Set to nil if not specified.
|
157
216
|
#
|
158
|
-
#
|
159
|
-
#
|
217
|
+
# Example:
|
218
|
+
#
|
219
|
+
# data = Table.new :data => [1,2], [3,4],
|
220
|
+
# :column_names => %w[a b]
|
221
|
+
#
|
222
|
+
# data.append_column :name => 'new_column', :fill => 1
|
223
|
+
#
|
160
224
|
def append_column(options={})
|
161
225
|
self.column_names += [options[:name]] if options[:name]
|
162
226
|
if block_given?
|
@@ -166,17 +230,21 @@ module Ruport::Data
|
|
166
230
|
end; self
|
167
231
|
end
|
168
232
|
|
169
|
-
#
|
233
|
+
#
|
234
|
+
# Removes a column from the Table. Any values in the specified column are
|
170
235
|
# lost.
|
171
|
-
#
|
172
|
-
#
|
173
|
-
#
|
174
|
-
# data
|
175
|
-
#
|
176
|
-
#
|
236
|
+
#
|
237
|
+
# Example:
|
238
|
+
#
|
239
|
+
# data = Table.new :data => [[1,2], [3,4]], :column_names => %w[a b]
|
240
|
+
# data.append_column :name => 'new_column', :fill => 1
|
241
|
+
# data.remove_column :name => 'new_column'
|
242
|
+
# data == Table.new :data => [[1,2], [3,4]],
|
243
|
+
# :column_names => %w[a b] #=> true
|
177
244
|
# data = [[1,2],[3,4]].to_table
|
178
245
|
# data.remove_column(1)
|
179
246
|
# data.eql? [[1],[3]].to_table %w[a] #=> true
|
247
|
+
#
|
180
248
|
def remove_column(options={})
|
181
249
|
if options.kind_of? Integer
|
182
250
|
return reorder!((0...data[0].length).to_a - [options])
|
@@ -190,29 +258,50 @@ module Ruport::Data
|
|
190
258
|
reorder! column_names - [name]
|
191
259
|
end
|
192
260
|
|
193
|
-
# Create a shallow copy of the table: the same data elements are referenced
|
194
|
-
# by both the old and new table.
|
195
261
|
#
|
196
|
-
#
|
262
|
+
# Create a copy of the Table: records will be copied as well.
|
263
|
+
#
|
264
|
+
# Example:
|
265
|
+
#
|
266
|
+
# one = Table.new :data => [1,2], [3,4],
|
267
|
+
# :column_names => %w[a b]
|
197
268
|
# two = one.dup
|
269
|
+
#
|
198
270
|
def dup
|
199
271
|
a = self.class.new(:data => @data, :column_names => @column_names)
|
200
272
|
a.tags = tags.dup
|
201
273
|
return a
|
202
274
|
end
|
203
275
|
|
204
|
-
#
|
276
|
+
#
|
277
|
+
# Loads a CSV file directly into a Table using the FasterCSV library.
|
278
|
+
#
|
279
|
+
# Example:
|
205
280
|
#
|
206
|
-
#
|
207
|
-
|
208
|
-
|
281
|
+
# # treat first row as column_names
|
282
|
+
# table = Table.load('mydata.csv')
|
283
|
+
#
|
284
|
+
# # do not assume the data has column_names
|
285
|
+
# table = Table.load('mydata.csv',:has_names => false)
|
286
|
+
#
|
287
|
+
# # pass in FasterCSV options, such as column separators
|
288
|
+
# table = Table.load('mydata.csv',:csv_opts => { :col_sep => "\t" })
|
289
|
+
#
|
290
|
+
def self.load(csv_file, options={},&block)
|
291
|
+
get_table_from_csv(:foreach, csv_file, options,&block)
|
209
292
|
end
|
210
|
-
|
211
|
-
|
212
|
-
|
293
|
+
|
294
|
+
#
|
295
|
+
# Creates a Table from a CSV string using FasterCSV. See Table.load for
|
296
|
+
# additional examples.
|
297
|
+
#
|
298
|
+
# table = Table.parse("a,b,c\n1,2,3\n4,5,6\n")
|
299
|
+
#
|
300
|
+
def self.parse(string, options={},&block)
|
301
|
+
get_table_from_csv(:parse,string,options,&block)
|
213
302
|
end
|
214
303
|
|
215
|
-
def self.get_table_from_csv(msg,param,options={})
|
304
|
+
def self.get_table_from_csv(msg,param,options={},&block) #:nodoc:
|
216
305
|
options = {:has_names => true,
|
217
306
|
:csv_options => {} }.merge(options)
|
218
307
|
require "fastercsv"
|
@@ -223,15 +312,16 @@ module Ruport::Data
|
|
223
312
|
if first_line && options[:has_names]
|
224
313
|
loaded_data.column_names = row
|
225
314
|
first_line = false
|
226
|
-
elsif !
|
315
|
+
elsif !block
|
227
316
|
loaded_data << row
|
228
317
|
else
|
229
|
-
|
318
|
+
block[loaded_data,row]
|
230
319
|
end
|
231
320
|
end ; loaded_data
|
232
321
|
end
|
233
322
|
|
234
|
-
#
|
323
|
+
#
|
324
|
+
# Allows you to split Tables into multiple Tables for grouping.
|
235
325
|
#
|
236
326
|
# Example:
|
237
327
|
#
|
@@ -246,8 +336,8 @@ module Ruport::Data
|
|
246
336
|
# b.greg.eql? [[1,2,3],[7,8,9]].to_table(%w[a b c]) #=> true
|
247
337
|
# b["joe"].eql? [[2,3,4],[1,2,3]].to_table(%w[a b c]) #=> true
|
248
338
|
#
|
249
|
-
# You can also pass an
|
250
|
-
# the group will be joined by an underscore.
|
339
|
+
# You can also pass an Array to <tt>:group</tt>, and the resulting
|
340
|
+
# attributes in the group will be joined by an underscore.
|
251
341
|
#
|
252
342
|
# Example:
|
253
343
|
#
|
@@ -260,6 +350,7 @@ module Ruport::Data
|
|
260
350
|
# a.greg_brown.length #=> 2
|
261
351
|
# a["greg_gibson"].length #=> 1
|
262
352
|
# a.greg_brown[0].x #=> "foo"
|
353
|
+
#
|
263
354
|
def split(options={})
|
264
355
|
if options[:group].kind_of? Array
|
265
356
|
group = map { |r| options[:group].map { |e| r[e] } }.uniq
|
@@ -292,23 +383,22 @@ module Ruport::Data
|
|
292
383
|
end; rec
|
293
384
|
end
|
294
385
|
|
295
|
-
#
|
386
|
+
#
|
387
|
+
# Calculates sums. If a column name or index is given, it will try to
|
296
388
|
# convert each element of that column to an integer or float
|
297
|
-
# and add
|
298
|
-
#
|
299
|
-
# If a block is given, yields each Record so that you can do a calculation.
|
389
|
+
# and add them together.
|
300
390
|
#
|
391
|
+
# If a block is given, it yields each Record so that you can do your own
|
392
|
+
# calculation.
|
301
393
|
#
|
302
394
|
# Example:
|
303
395
|
#
|
396
|
+
# table = [[1,2],[3,4],[5,6]].to_table(%w[col1 col2])
|
397
|
+
# table.sigma("col1") #=> 9
|
398
|
+
# table.sigma(0) #=> 9
|
399
|
+
# table.sigma { |r| r.col1 + r.col2 } #=> 21
|
400
|
+
# table.sigma { |r| r.col2 + 1 } #=> 15
|
304
401
|
#
|
305
|
-
# table = [[1,2],[3,4],[5,6]].to_table(%w[col1 col2])
|
306
|
-
# table.sigma("col1") #=> 9
|
307
|
-
# table.sigma(0) #=> 9
|
308
|
-
# table.sigma { |r| r.col1 + r.col2 } #=> 21
|
309
|
-
# table.sigma { |r| r.col2 + 1 } #=> 15
|
310
|
-
#
|
311
|
-
# For the non-mathy, this has been aliased as Table#sum
|
312
402
|
def sigma(column=nil)
|
313
403
|
inject(0) { |s,r|
|
314
404
|
if column
|
@@ -329,7 +419,7 @@ module Ruport::Data
|
|
329
419
|
|
330
420
|
end
|
331
421
|
|
332
|
-
module Ruport::Data::TableHelper
|
422
|
+
module Ruport::Data::TableHelper #:nodoc:
|
333
423
|
def table(names=[])
|
334
424
|
t = [].to_table(names)
|
335
425
|
yield(t) if block_given?; t
|