ruport 0.6.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,67 @@
1
+ ***************
2
+ *** 287,294 ****
3
+ # # pass in FasterCSV options, such as column separators
4
+ # table = Table.load('mydata.csv',:csv_opts => { :col_sep => "\t" })
5
+ #
6
+ - def self.load(csv_file, options={})
7
+ - get_table_from_csv(:foreach, csv_file, options)
8
+ end
9
+
10
+ #
11
+ --- 287,294 ----
12
+ # # pass in FasterCSV options, such as column separators
13
+ # table = Table.load('mydata.csv',:csv_opts => { :col_sep => "\t" })
14
+ #
15
+ + def self.load(csv_file, options={},&block)
16
+ + get_table_from_csv(:foreach, csv_file, options,&block)
17
+ end
18
+
19
+ #
20
+ ***************
21
+ *** 297,307 ****
22
+ #
23
+ # table = Table.parse("a,b,c\n1,2,3\n4,5,6\n")
24
+ #
25
+ - def self.parse(string, options={})
26
+ - get_table_from_csv(:parse,string,options)
27
+ end
28
+
29
+ - def self.get_table_from_csv(msg,param,options={}) #:nodoc:
30
+ options = {:has_names => true,
31
+ :csv_options => {} }.merge(options)
32
+ require "fastercsv"
33
+ --- 297,307 ----
34
+ #
35
+ # table = Table.parse("a,b,c\n1,2,3\n4,5,6\n")
36
+ #
37
+ + def self.parse(string, options={},&block)
38
+ + get_table_from_csv(:parse,string,options,&block)
39
+ end
40
+
41
+ + def self.get_table_from_csv(msg,param,options={},&block) #:nodoc:
42
+ options = {:has_names => true,
43
+ :csv_options => {} }.merge(options)
44
+ require "fastercsv"
45
+ ***************
46
+ *** 312,321 ****
47
+ if first_line && options[:has_names]
48
+ loaded_data.column_names = row
49
+ first_line = false
50
+ - elsif !block_given?
51
+ loaded_data << row
52
+ else
53
+ - yield(loaded_data,row)
54
+ end
55
+ end ; loaded_data
56
+ end
57
+ --- 312,321 ----
58
+ if first_line && options[:has_names]
59
+ loaded_data.column_names = row
60
+ first_line = false
61
+ + elsif !block
62
+ loaded_data << row
63
+ else
64
+ + block[loaded_data,row]
65
+ end
66
+ end ; loaded_data
67
+ end
@@ -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 are :data and :column_names.
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
- # Sets the column names for this table. The single parameter should be
58
- # an array listing the names of the columns.
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.
59
73
  #
60
- # tbl = Table.new({:data => [1,2,3], [3,4,5], :column_names => %w[a b c]})
61
- # tbl.column_names = %w[e f g]
62
- def column_names=(other)
74
+ # Example:
75
+ #
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)
63
82
  @column_names.replace(other.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
- # one = Table.new({:data => [1,2], [3,4], :column_names => %w[a b]})
70
- # two = Table.new({:data => [1,2], [3,4], :column_names => %w[a b]})
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
- # Uses Ruport's built-in text plugin to render this table into a string
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({:data => [1,2], [3,4], :column_names => %w[a b]})
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
- # data = Table.new({:data => [1,2], [3,4], :column_names => %w[a b]})
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 << Ruport::Data::Record.new [5,6], :attributes => %w[a b]
128
+ # data << Record.new [5,6], :attributes => %w[a b]
129
+ #
93
130
  def <<(other)
94
131
  case other
95
132
  when Array
@@ -108,24 +145,37 @@ module Ruport::Data
108
145
  self
109
146
  end
110
147
 
111
- # Used to combine two tables. Throws an ArgumentError if the tables don't
148
+ #
149
+ # Used to combine two Tables. Throws an ArgumentError if the Tables don't
112
150
  # have identical columns.
113
151
  #
114
- # inky = Table.new(:data => [[1,2], [3,4]], :column_names => %w[a b])
115
- # blinky = Table.new(:data => [[5,6]], :column_names => %w[a b])
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
- # data = Table.new({:data => [1,2], [3,4], :column_names => %w[a b]})
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
131
181
  if @column_names && !@column_names.empty?
@@ -142,21 +192,34 @@ module Ruport::Data
142
192
  }; self
143
193
  end
144
194
 
145
- # Returns a copy of the table with its columns in the requested order.
146
195
  #
147
- # one = Table.new({:data => [1,2], [3,4], :column_names => %w[a b]})
196
+ # Returns a copy of the Table with its columns in the requested order.
197
+ #
198
+ # Example:
199
+ #
200
+ # one = Table.new :data => [1,2], [3,4],
201
+ # :column_names => %w[a b]
202
+ #
148
203
  # two = one.reorder!([1,0])
204
+ #
149
205
  def reorder(*indices)
150
206
  dup.reorder!(*indices)
151
207
  end
152
208
 
153
- # Adds an extra column to the table. Accepts an options Hash as its
154
- # only parameter which should contain 2 keys - :name and :fill.
155
- # :name specifies the new columns name, and :fill the default value to
156
- # use for the column in existing rows.
209
+ #
210
+ # Adds an extra column to the Table. Required options:
211
+ #
212
+ # <b><tt>:name</tt></b>:: The new column's name
213
+ # <b><tt>:fill</tt></b>:: The default value to use for the column in
214
+ # existing rows.
157
215
  #
158
- # data = Table.new({:data => [1,2], [3,4], :column_names => %w[a b]})
159
- # data.append_column({:name => 'new_column', :fill => 1)
216
+ # Example:
217
+ #
218
+ # data = Table.new :data => [1,2], [3,4],
219
+ # :column_names => %w[a b]
220
+ #
221
+ # data.append_column :name => 'new_column', :fill => 1
222
+ #
160
223
  def append_column(options={})
161
224
  self.column_names += [options[:name]] if options[:name]
162
225
  if block_given?
@@ -166,17 +229,21 @@ module Ruport::Data
166
229
  end; self
167
230
  end
168
231
 
169
- # Removes a column from the table. Any values in the specified column are
232
+ #
233
+ # Removes a column from the Table. Any values in the specified column are
170
234
  # lost.
171
- # data = Table.new({:data => [1,2], [3,4], :column_names => %w[a b]})
172
- # data.append_column({:name => 'new_column', :fill => 1)
173
- # data.remove_column({:name => 'new_column')
174
- # data == Table.new({:data => [1,2], [3,4], :column_names => %w[a b]})
175
- # #=> true
176
- #
235
+ #
236
+ # Example:
237
+ #
238
+ # data = Table.new :data => [[1,2], [3,4]], :column_names => %w[a b]
239
+ # data.append_column :name => 'new_column', :fill => 1
240
+ # data.remove_column :name => 'new_column'
241
+ # data == Table.new :data => [[1,2], [3,4]],
242
+ # :column_names => %w[a b] #=> true
177
243
  # data = [[1,2],[3,4]].to_table
178
244
  # data.remove_column(1)
179
245
  # data.eql? [[1],[3]].to_table %w[a] #=> true
246
+ #
180
247
  def remove_column(options={})
181
248
  if options.kind_of? Integer
182
249
  return reorder!((0...data[0].length).to_a - [options])
@@ -190,29 +257,38 @@ module Ruport::Data
190
257
  reorder! column_names - [name]
191
258
  end
192
259
 
193
- # Create a shallow copy of the table: the same data elements are referenced
194
- # by both the old and new table.
195
260
  #
196
- # one = Table.new({:data => [1,2], [3,4], :column_names => %w[a b]})
261
+ # Create a shallow copy of the Table: the same data elements are referenced
262
+ # by both the old and new Table.
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
- # Loads a CSV file directly into a table using the fasterCSV library.
276
+ #
277
+ # Loads a CSV file directly into a Table using the FasterCSV library.
278
+ #
279
+ # Example:
205
280
  #
206
- # data = Table.load('mydata.csv')
281
+ # table = Table.load('mydata.csv')
282
+ #
207
283
  def self.load(csv_file, options={})
208
284
  get_table_from_csv(:foreach, csv_file, options)
209
285
  end
210
-
211
- def self.parse(string, options={})
286
+
287
+ def self.parse(string, options={}) #:nodoc:
212
288
  get_table_from_csv(:parse,string,options)
213
289
  end
214
290
 
215
- def self.get_table_from_csv(msg,param,options={})
291
+ def self.get_table_from_csv(msg,param,options={}) #:nodoc:
216
292
  options = {:has_names => true,
217
293
  :csv_options => {} }.merge(options)
218
294
  require "fastercsv"
@@ -231,7 +307,8 @@ module Ruport::Data
231
307
  end ; loaded_data
232
308
  end
233
309
 
234
- # Allows you to split tables into multiple tables for grouping.
310
+ #
311
+ # Allows you to split Tables into multiple Tables for grouping.
235
312
  #
236
313
  # Example:
237
314
  #
@@ -246,8 +323,8 @@ module Ruport::Data
246
323
  # b.greg.eql? [[1,2,3],[7,8,9]].to_table(%w[a b c]) #=> true
247
324
  # b["joe"].eql? [[2,3,4],[1,2,3]].to_table(%w[a b c]) #=> true
248
325
  #
249
- # You can also pass an array to :group, and the resulting attributes in
250
- # the group will be joined by an underscore.
326
+ # You can also pass an Array to <tt>:group</tt>, and the resulting
327
+ # attributes in the group will be joined by an underscore.
251
328
  #
252
329
  # Example:
253
330
  #
@@ -260,6 +337,7 @@ module Ruport::Data
260
337
  # a.greg_brown.length #=> 2
261
338
  # a["greg_gibson"].length #=> 1
262
339
  # a.greg_brown[0].x #=> "foo"
340
+ #
263
341
  def split(options={})
264
342
  if options[:group].kind_of? Array
265
343
  group = map { |r| options[:group].map { |e| r[e] } }.uniq
@@ -292,23 +370,22 @@ module Ruport::Data
292
370
  end; rec
293
371
  end
294
372
 
295
- # Calculates sums. If a column name or index is given, it will try to
373
+ #
374
+ # Calculates sums. If a column name or index is given, it will try to
296
375
  # convert each element of that column to an integer or float
297
- # and add it together
298
- #
299
- # If a block is given, yields each Record so that you can do a calculation.
376
+ # and add them together.
300
377
  #
378
+ # If a block is given, it yields each Record so that you can do your own
379
+ # calculation.
301
380
  #
302
381
  # Example:
303
382
  #
383
+ # table = [[1,2],[3,4],[5,6]].to_table(%w[col1 col2])
384
+ # table.sigma("col1") #=> 9
385
+ # table.sigma(0) #=> 9
386
+ # table.sigma { |r| r.col1 + r.col2 } #=> 21
387
+ # table.sigma { |r| r.col2 + 1 } #=> 15
304
388
  #
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
389
  def sigma(column=nil)
313
390
  inject(0) { |s,r|
314
391
  if column
@@ -326,4 +403,12 @@ module Ruport::Data
326
403
  alias_method :sum, :sigma
327
404
 
328
405
  end
406
+
407
+ end
408
+
409
+ module Ruport::Data::TableHelper #:nodoc:
410
+ def table(names=[])
411
+ t = [].to_table(names)
412
+ yield(t) if block_given?; t
413
+ end
329
414
  end
@@ -5,38 +5,66 @@
5
5
  # Copyright 2006 by respective content owners, all rights reserved.
6
6
  module Ruport::Data
7
7
 
8
- # This module provides a simple mechanism for tagging arbitrary objects. This
9
- # provides the necessary methods to set and retrieve tags which can consist of
10
- # any Ruby object. This is used by Data::Record and the Ruport Data
11
- # Collections.
8
+ #
9
+ # === Overview
10
+ #
11
+ # This module provides a simple mechanism for tagging arbitrary objects.
12
+ # It provides the necessary methods to set and retrieve tags which can
13
+ # consist of any Ruby object.
14
+ #
12
15
  module Taggable
13
16
 
14
- # Adds a tag to the object
17
+ #
18
+ # Adds a tag to the object.
19
+ #
20
+ # Example:
21
+ #
15
22
  # taggable_obj.tag :spiffy
23
+ #
16
24
  def tag(tag_name)
17
25
  tags << tag_name unless has_tag? tag_name
18
26
  end
19
27
 
20
- # Removes a tag
28
+ #
29
+ # Removes a tag from the object.
30
+ #
31
+ # Example:
32
+ #
21
33
  # taggable_obj.delete_tag :not_so_spiffy
34
+ #
22
35
  def delete_tag(tag_name)
23
36
  tags.delete tag_name
24
37
  end
25
38
 
26
- # Checks to see if a tag is present
39
+ #
40
+ # Checks to see if a tag is present.
41
+ #
42
+ # Example:
43
+ #
27
44
  # taggable_obj.has_tag? :spiffy #=> true
45
+ #
28
46
  def has_tag?(tag_name)
29
47
  tags.include? tag_name
30
48
  end
31
49
 
32
- # Returns an array of tags.
50
+ #
51
+ # Returns an Array of the object's tags.
52
+ #
53
+ # Example:
54
+ #
33
55
  # taggable_obj.tags #=> [:spiffy, :kind_of_spiffy]
56
+ #
34
57
  def tags
35
58
  @ruport_tags ||= []
36
59
  end
37
60
 
38
- # Sets the tags to some array
61
+ #
62
+ # Sets the tags to some Array.
63
+ #
64
+ # Example:
65
+ #
39
66
  # taggable_obj.tags = [:really_dang_spiffy, :the_most_spiffy]
67
+ #
40
68
  def tags=(tags_list)
41
69
  @ruport_tags = tags_list
42
70
  end