ruport 0.10.0 → 0.11.0

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 (59) hide show
  1. data/LICENSE +55 -9
  2. data/Rakefile +3 -5
  3. data/examples/line_plotter.rb +3 -0
  4. data/examples/pdf_complex_report.rb +0 -1
  5. data/examples/pdf_report_with_common_base.rb +72 -0
  6. data/examples/pdf_styles.rb +16 -0
  7. data/examples/simple_pdf_lines.rb +0 -1
  8. data/lib/ruport.rb +5 -66
  9. data/lib/ruport/acts_as_reportable.rb +122 -51
  10. data/lib/ruport/data/grouping.rb +30 -13
  11. data/lib/ruport/data/record.rb +26 -25
  12. data/lib/ruport/data/table.rb +91 -34
  13. data/lib/ruport/formatter.rb +86 -11
  14. data/lib/ruport/formatter/csv.rb +29 -2
  15. data/lib/ruport/formatter/html.rb +23 -1
  16. data/lib/ruport/formatter/pdf.rb +123 -32
  17. data/lib/ruport/formatter/text.rb +62 -6
  18. data/lib/ruport/query.rb +75 -39
  19. data/lib/ruport/renderer.rb +250 -35
  20. data/lib/ruport/renderer/grouping.rb +2 -2
  21. data/test/html_formatter_test.rb +4 -1
  22. data/test/pdf_formatter_test.rb +30 -7
  23. data/test/query_test.rb +12 -0
  24. data/test/renderer_test.rb +33 -2
  25. data/test/table_test.rb +8 -2
  26. data/test/text_formatter_test.rb +11 -1
  27. metadata +53 -107
  28. data/bin/rope +0 -12
  29. data/examples/rope_examples/itunes/README +0 -12
  30. data/examples/rope_examples/itunes/Rakefile +0 -39
  31. data/examples/rope_examples/itunes/config/environment.rb +0 -4
  32. data/examples/rope_examples/itunes/data/mix.txt +0 -1
  33. data/examples/rope_examples/itunes/lib/helpers.rb +0 -0
  34. data/examples/rope_examples/itunes/lib/init.rb +0 -39
  35. data/examples/rope_examples/itunes/lib/reports.rb +0 -1
  36. data/examples/rope_examples/itunes/lib/reports/playlist.rb +0 -17
  37. data/examples/rope_examples/itunes/log/ruport.log +0 -1
  38. data/examples/rope_examples/itunes/test/test_playlist.rb +0 -8
  39. data/examples/rope_examples/itunes/util/build +0 -96
  40. data/examples/rope_examples/itunes/util/sql_exec +0 -5
  41. data/examples/rope_examples/sales_report/README +0 -4
  42. data/examples/rope_examples/sales_report/Rakefile +0 -39
  43. data/examples/rope_examples/sales_report/config/environment.rb +0 -4
  44. data/examples/rope_examples/sales_report/lib/helpers.rb +0 -0
  45. data/examples/rope_examples/sales_report/lib/init.rb +0 -39
  46. data/examples/rope_examples/sales_report/lib/reports.rb +0 -1
  47. data/examples/rope_examples/sales_report/lib/reports/sales.rb +0 -132
  48. data/examples/rope_examples/sales_report/log/ruport.log +0 -1
  49. data/examples/rope_examples/sales_report/output/books.pdf +0 -170
  50. data/examples/rope_examples/sales_report/output/books.txt +0 -11
  51. data/examples/rope_examples/sales_report/test/test_sales.rb +0 -8
  52. data/examples/rope_examples/sales_report/util/build +0 -96
  53. data/examples/rope_examples/sales_report/util/sql_exec +0 -5
  54. data/examples/sample.rb +0 -16
  55. data/lib/ruport/generator.rb +0 -294
  56. data/lib/ruport/report.rb +0 -262
  57. data/setup.rb +0 -1585
  58. data/test/report_test.rb +0 -218
  59. data/test/samples/foo.rtxt +0 -3
@@ -1,13 +1,27 @@
1
+ # Ruport : Extensible Reporting System
2
+ #
3
+ # data/grouping.rb provides group and grouping data structures for Ruport.
4
+ #
5
+ # Created by Michael Milner / Gregory Brown, 2007
6
+ # Copyright (C) 2007 Michael Milner / Gregory Brown, All Rights Reserved.
7
+ #
8
+ # This is free software distributed under the same terms as Ruby 1.8
9
+ # See LICENSE and COPYING for details.
10
+ #
1
11
  module Ruport::Data
2
12
 
3
13
  # === Overview
4
14
  #
5
15
  # This class implements a group data structure for Ruport. Group is
6
- # simply a subclass of Table that adds a :name attribute.
16
+ # simply a subclass of Table that adds a <tt>:name</tt> attribute.
7
17
  #
8
18
  class Group < Table
9
19
 
10
- attr_reader :name, :subgroups
20
+ # The name of the group
21
+ attr_reader :name
22
+
23
+ # A hash of subgroups
24
+ attr_reader :subgroups
11
25
 
12
26
  # Creates a new Group based on the supplied options.
13
27
  #
@@ -33,11 +47,11 @@ module Ruport::Data
33
47
  include Ruport::Renderer::Hooks
34
48
  renders_as_group
35
49
 
36
- def self.inherited(base)
50
+ def self.inherited(base) #:nodoc:
37
51
  base.renders_as_group
38
52
  end
39
53
 
40
- # Create a copy of the Group: records will be copied as well.
54
+ # Create a copy of the Group. Records will be copied as well.
41
55
  #
42
56
  # Example:
43
57
  #
@@ -94,7 +108,7 @@ module Ruport::Data
94
108
 
95
109
  protected
96
110
 
97
- attr_writer :name, :subgroups
111
+ attr_writer :name, :subgroups #:nodoc:
98
112
 
99
113
  private
100
114
 
@@ -153,7 +167,10 @@ module Ruport::Data
153
167
  end
154
168
  end
155
169
 
156
- attr_accessor :data
170
+ # The grouping's data
171
+ attr_accessor :data
172
+
173
+ # The name of the column used to group the data
157
174
  attr_reader :grouped_by
158
175
 
159
176
  require "forwardable"
@@ -171,7 +188,7 @@ module Ruport::Data
171
188
  raise(IndexError,"Group Not Found")
172
189
  end
173
190
 
174
- # Used to add extra data to the Grouping. <tt>other</tt> should be a Group.
191
+ # Used to add extra data to the Grouping. <tt>group</tt> should be a Group.
175
192
  #
176
193
  # Example:
177
194
  #
@@ -211,10 +228,11 @@ module Ruport::Data
211
228
  # runs the specified procs and returns the results as a Table.
212
229
  #
213
230
  # The following example would show for each date group,
214
- # the sum for the attributes or methods :opened and :closed
215
- # and order them by the :order array.
231
+ # the sum for the attributes or methods <tt>:opened</tt> and
232
+ # <tt>:closed</tt> and order them by the <tt>:order</tt> array.
216
233
  #
217
- # If :order is not specified, you cannot depend on predictable column order
234
+ # If <tt>:order</tt> is not specified, you cannot depend on predictable
235
+ # column order.
218
236
  #
219
237
  # grouping.summary :date,
220
238
  # :opened => lambda { |g| g.sigma(:opened) },
@@ -254,12 +272,11 @@ module Ruport::Data
254
272
  include Ruport::Renderer::Hooks
255
273
  renders_as_grouping
256
274
 
257
- def self.inherited(base)
275
+ def self.inherited(base) #:nodoc:
258
276
  base.renders_as_grouping
259
277
  end
260
-
261
278
 
262
- # Create a copy of the Grouping: groups will be copied as well.
279
+ # Create a copy of the Grouping. Groups will be copied as well.
263
280
  #
264
281
  # Example:
265
282
  #
@@ -1,14 +1,18 @@
1
- # The Ruport Data Collections.
2
- # Authors: Gregory Brown / Dudley Flanders
1
+ # Ruport : Extensible Reporting System
2
+ #
3
+ # data/record.rb provides a record data structure for Ruport.
4
+ #
5
+ # Created by Gregory Brown / Dudley Flanders, 2006
6
+ # Copyright (C) 2006 Gregory Brown / Dudley Flanders, All Rights Reserved.
7
+ #
8
+ # This is free software distributed under the same terms as Ruby 1.8
9
+ # See LICENSE and COPYING for details.
3
10
  #
4
- # This is Free Software. For details, see LICENSE and COPYING
5
- # Copyright 2006 by respective content owners, all rights reserved.
6
11
  module Ruport::Data
7
12
 
8
- #
9
13
  # === Overview
10
14
  #
11
- # Data::Records are the work horse of Ruport's data model. These can behave
15
+ # Data::Records are the work-horse of Ruport's data model. These can behave
12
16
  # as Array-like, Hash-like, or Struct-like objects. They are used as the
13
17
  # base element for Data::Table
14
18
  #
@@ -16,7 +20,6 @@ module Ruport::Data
16
20
 
17
21
  include Enumerable
18
22
 
19
- #
20
23
  # Creates a new Record object. If the <tt>:attributes</tt>
21
24
  # keyword is specified, Hash-like and Struct-like
22
25
  # access will be enabled. Otherwise, Record elements may be
@@ -55,7 +58,6 @@ module Ruport::Data
55
58
  end
56
59
  end
57
60
 
58
-
59
61
  ##############
60
62
  # Delegators #
61
63
  ##############
@@ -71,17 +73,14 @@ module Ruport::Data
71
73
  @attributes.dup
72
74
  end
73
75
 
74
- #
75
76
  # Sets the <tt>attribute</tt> list for this Record.
76
77
  # (Dangerous when used within Table objects!)
77
- #
78
- # Example:
79
- #
80
- # my_record.attributes = %w[foo bar baz]
81
- #
82
78
  attr_writer :attributes
83
79
 
84
- attr_reader :data
80
+ # The data for the record
81
+ attr_reader :data
82
+
83
+ # The size of the record (the number of items in the record's data).
85
84
  def size; @data.size; end
86
85
  alias_method :length, :size
87
86
 
@@ -89,7 +88,6 @@ module Ruport::Data
89
88
  # Access Methods #
90
89
  ##################
91
90
 
92
- #
93
91
  # Allows either Array or Hash-like indexing.
94
92
  #
95
93
  # Examples:
@@ -106,7 +104,6 @@ module Ruport::Data
106
104
  end
107
105
  end
108
106
 
109
- #
110
107
  # Allows setting a <tt>value</tt> at an <tt>index</tt>.
111
108
  #
112
109
  # Examples:
@@ -134,6 +131,7 @@ module Ruport::Data
134
131
  # record.get("foo") # looks for an attribute "foo" or :foo
135
132
  #
136
133
  # record.get(0) # Gets the first element
134
+ #
137
135
  def get(name)
138
136
  case name
139
137
  when String,Symbol
@@ -149,7 +147,6 @@ module Ruport::Data
149
147
  # Conversions #
150
148
  ################
151
149
 
152
- #
153
150
  # Converts a Record into an Array.
154
151
  #
155
152
  # Example:
@@ -167,6 +164,7 @@ module Ruport::Data
167
164
  #
168
165
  # a = Data::Record.new([1,2],:attributes => %w[a b])
169
166
  # a.to_hash #=> {"a" => 1, "b" => 2}
167
+ #
170
168
  def to_hash
171
169
  @data.dup
172
170
  end
@@ -175,7 +173,6 @@ module Ruport::Data
175
173
  # Comparisons #
176
174
  ################
177
175
 
178
- #
179
176
  # If <tt>attributes</tt> and <tt>to_a</tt> are equivalent, then
180
177
  # <tt>==</tt> evaluates to true. Otherwise, <tt>==</tt> returns false.
181
178
  #
@@ -184,14 +181,13 @@ module Ruport::Data
184
181
  to_a == other.to_a
185
182
  end
186
183
 
187
- alias_method :eql?, :==
188
-
184
+ alias_method :eql?, :==
189
185
 
190
186
  #############
191
187
  # Iterators #
192
188
  #############
193
189
 
194
- # Yields each element of the Record. Does not provide attribute names
190
+ # Yields each element of the Record. Does not provide attribute names.
195
191
  def each
196
192
  to_a.each { |e| yield(e) }
197
193
  end
@@ -208,7 +204,6 @@ module Ruport::Data
208
204
  @data[new_name] = @data.delete(old_name)
209
205
  end
210
206
 
211
- #
212
207
  # Allows you to change the order of or reduce the number of columns in a
213
208
  # Record.
214
209
  #
@@ -237,11 +232,10 @@ module Ruport::Data
237
232
  include Ruport::Renderer::Hooks
238
233
  renders_as_row
239
234
 
240
- def self.inherited(base)
235
+ def self.inherited(base) #:nodoc:
241
236
  base.renders_as_row
242
237
  end
243
238
 
244
- #
245
239
  # Provides a unique hash value. If a Record contains the same data and
246
240
  # attributes as another Record, they will hash to the same value, even if
247
241
  # they are not the same object. This is similar to the way Array works,
@@ -251,6 +245,13 @@ module Ruport::Data
251
245
  @attributes.hash + to_a.hash
252
246
  end
253
247
 
248
+ # Create a copy of the Record.
249
+ #
250
+ # Example:
251
+ #
252
+ # one = Record.new([1,2,3,4],:attributes => %w[a b c d])
253
+ # two = one.dup
254
+ #
254
255
  def initialize_copy(from)
255
256
  @data = from.data.dup
256
257
  @attributes = from.attributes.dup
@@ -1,11 +1,14 @@
1
- # The Ruport Data Collections.
2
- # Authors: Gregory Brown / Dudley Flanders
1
+ # Ruport : Extensible Reporting System
3
2
  #
4
- # This is Free Software. For details, see LICENSE and COPYING
5
- # Copyright 2006 by respective content owners, all rights reserved.
6
-
7
- module Ruport::Data
8
-
3
+ # data/table.rb provides a table data structure for Ruport.
4
+ #
5
+ # Created by Gregory Brown / Dudley Flanders, 2006
6
+ # Copyright (C) 2006 Gregory Brown / Dudley Flanders, All Rights Reserved.
7
+ #
8
+ # This is free software distributed under the same terms as Ruby 1.8
9
+ # See LICENSE and COPYING for details.
10
+ #
11
+ module Ruport::Data
9
12
 
10
13
  # === Overview
11
14
  #
@@ -16,11 +19,15 @@ module Ruport::Data
16
19
  # Table is intended to be used as the data store for structured, tabular
17
20
  # data.
18
21
  #
19
- # Once your data is in a Ruport::Data::Table object, it can be manipulated
22
+ # Once your data is in a Table object, it can be manipulated
20
23
  # to suit your needs, then used to build a report.
21
24
  #
22
25
  class Table
23
26
 
27
+ # === Overview
28
+ #
29
+ # This module provides facilities for creating tables from csv data.
30
+ #
24
31
  module FromCSV
25
32
  # Loads a CSV file directly into a Table using the FasterCSV library.
26
33
  #
@@ -83,7 +90,8 @@ module Ruport::Data
83
90
 
84
91
  def handle_csv_row_proc(data,row,options,block)
85
92
  if options[:records]
86
- row = Record.new(row, :attributes => data.column_names)
93
+ rc = options[:record_class] || Record
94
+ row = rc.new(row, :attributes => data.column_names)
87
95
  end
88
96
 
89
97
  block[data,row]
@@ -100,26 +108,25 @@ module Ruport::Data
100
108
  loaded.column_names = row.headers
101
109
  end
102
110
  end
103
-
104
111
  end
105
112
 
106
-
107
113
  include Enumerable
108
114
  extend FromCSV
109
115
 
110
116
  include Ruport::Renderer::Hooks
111
117
  renders_as_table
112
118
 
113
- def self.inherited(base)
119
+ def self.inherited(base) #:nodoc:
114
120
  base.renders_as_table
115
121
  end
116
122
 
117
123
  # Creates a new table based on the supplied options.
118
- # Valid options:
119
- # <b><tt>:data</tt></b>:: An Array of Arrays representing the
120
- # records in this Table
121
- # <b><tt>:column_names</tt></b>:: An Array containing the column names
122
- # for this Table.
124
+ #
125
+ # Valid options:
126
+ # <b><tt>:data</tt></b>:: An Array of Arrays representing the
127
+ # records in this Table.
128
+ # <b><tt>:column_names</tt></b>:: An Array containing the column names
129
+ # for this Table.
123
130
  # Example:
124
131
  #
125
132
  # table = Table.new :data => [[1,2,3], [3,4,5]],
@@ -145,8 +152,10 @@ module Ruport::Data
145
152
  end
146
153
  end
147
154
 
148
- # This Table's column names.
155
+ # This Table's column names
149
156
  attr_reader :column_names
157
+
158
+ # This Table's data
150
159
  attr_reader :data
151
160
 
152
161
  require "forwardable"
@@ -199,9 +208,9 @@ module Ruport::Data
199
208
 
200
209
  alias_method :==, :eql?
201
210
 
202
- # Used to add extra data to the Table. <tt>other</tt> can be an Array,
211
+ # Used to add extra data to the Table. <tt>row</tt> can be an Array,
203
212
  # Hash or Record. It also can be anything that implements a meaningful
204
- # to_hash or to_ary
213
+ # to_hash or to_ary.
205
214
  #
206
215
  # Example:
207
216
  #
@@ -225,14 +234,13 @@ module Ruport::Data
225
234
  return self
226
235
  end
227
236
 
228
- # returns the record class constant being used by the table
237
+ # Returns the record class constant being used by the table.
229
238
  def record_class
230
239
  @record_class.split("::").inject(Class) { |c,el| c.send(:const_get,el) }
231
240
  end
232
-
233
241
 
234
242
  # Used to merge two Tables by rows.
235
- # Throws an ArgumentError if the Tables don't have identical columns.
243
+ # Raises an ArgumentError if the Tables don't have identical columns.
236
244
  #
237
245
  # Example:
238
246
  #
@@ -252,7 +260,23 @@ module Ruport::Data
252
260
  :record_class => record_class )
253
261
  end
254
262
 
255
-
263
+ # Allows you to change the order of, or reduce the number of columns in a
264
+ # Table.
265
+ #
266
+ # Example:
267
+ #
268
+ # a = Table.new :data => [[1,2,3],[4,5,6]], :column_names => %w[a b c]
269
+ # a.reorder("b","c","a")
270
+ # a.column_names #=> ["b","c","a"]
271
+ #
272
+ # a = Table.new :data => [[1,2,3],[4,5,6]], :column_names => %w[a b c]
273
+ # a.reorder(1,2,0)
274
+ # a.column_names #=> ["b","c","a"]
275
+ #
276
+ # a = Table.new :data => [[1,2,3],[4,5,6]], :column_names => %w[a b c]
277
+ # a.reorder(0,2)
278
+ # a.column_names #=> ["a","c"]
279
+ #
256
280
  def reorder(*indices)
257
281
  raise(ArgumentError,"Can't reorder without column names set!") if
258
282
  @column_names.empty?
@@ -264,11 +288,11 @@ module Ruport::Data
264
288
  end
265
289
 
266
290
  reduce(indices)
267
- end
268
-
291
+ end
269
292
 
270
- # Adds an extra column to the Table. Available Options:
293
+ # Adds an extra column to the Table.
271
294
  #
295
+ # Available Options:
272
296
  # <b><tt>:default</tt></b>:: The default value to use for the column in
273
297
  # existing rows. Set to nil if not specified.
274
298
  #
@@ -276,13 +300,12 @@ module Ruport::Data
276
300
  # number.
277
301
  #
278
302
  # <b><tt>:before</tt></b>:: Inserts the new column before the column
279
- # indicated. (by name)
303
+ # indicated (by name).
280
304
  #
281
305
  # <b><tt>:after</tt></b>:: Inserts the new column after the column
282
- # indicated. (by name)
306
+ # indicated (by name).
283
307
  #
284
308
  # If a block is provided, it will be used to build up the column.
285
- #
286
309
  #
287
310
  # Example:
288
311
  #
@@ -318,6 +341,15 @@ module Ruport::Data
318
341
  end; self
319
342
  end
320
343
 
344
+ # Add multiple extra columns to the Table. See <tt>add_column</tt> for
345
+ # a list of available options.
346
+ #
347
+ # Example:
348
+ #
349
+ # data = Table("a","b") { |t| t << [1,2] << [3,4] }
350
+ #
351
+ # data.add_columns ['new_column_1','new_column_2'], :default => 1
352
+ #
321
353
  def add_columns(names,options={})
322
354
  raise "Greg isn't smart enough to figure this out.\n"+
323
355
  "Send ideas in at http://list.rubyreports.org" if block_given?
@@ -352,7 +384,7 @@ module Ruport::Data
352
384
  cols.each { |col| remove_column(col) }
353
385
  end
354
386
 
355
- # Renames a column. Will update Record attributes as well
387
+ # Renames a column. Will update Record attributes as well.
356
388
  #
357
389
  # Example:
358
390
  #
@@ -516,6 +548,11 @@ module Ruport::Data
516
548
 
517
549
  # Returns an array of values for the given column name.
518
550
  #
551
+ # Example:
552
+ #
553
+ # table = [[1,2],[3,4],[5,6]].to_table(%w[col1 col2])
554
+ # table.column("col1") #=> [1,3,5]
555
+ #
519
556
  def column(name)
520
557
  case(name)
521
558
  when Integer
@@ -600,12 +637,25 @@ module Ruport::Data
600
637
  return table
601
638
  end
602
639
 
603
- # same as Table#sort_rows_by, but self modifiying
640
+ # Same as Table#sort_rows_by, but self modifying.
641
+ # See <tt>sort_rows_by</tt> for documentation.
642
+ #
604
643
  def sort_rows_by!(col_names=nil,&block)
605
644
  table = sort_rows_by(col_names,&block)
606
645
  @data = table.data
607
646
  end
608
647
 
648
+ # Get an array of records from the Table limited by the criteria specified.
649
+ #
650
+ # Example:
651
+ #
652
+ # table = Table.new :data => [[1,2,3], [1,4,6], [4,5,6]],
653
+ # :column_names => %w[a b c]
654
+ # table.rows_with(:a => 1) #=> [[1,2,3], [1,4,6]]
655
+ # table.rows_with(:a => 1, :b => 4) #=> [[1,4,6]]
656
+ # table.rows_with_a(1) #=> [[1,2,3], [1,4,6]]
657
+ # table.rows_with(%w[a b]) {|a,b| [a,b] == [1,4] } #=> [[1,4,6]]
658
+ #
609
659
  def rows_with(columns,&block)
610
660
  select { |r|
611
661
  if block
@@ -616,7 +666,7 @@ module Ruport::Data
616
666
  }
617
667
  end
618
668
 
619
- # Create a copy of the Table: records will be copied as well.
669
+ # Create a copy of the Table. Records will be copied as well.
620
670
  #
621
671
  # Example:
622
672
  #
@@ -631,7 +681,7 @@ module Ruport::Data
631
681
  from.data.each { |r| self << r.dup }
632
682
  end
633
683
 
634
- # Uses Ruport's built-in text formatter to render this Table into a String
684
+ # Uses Ruport's built-in text formatter to render this Table into a String.
635
685
  #
636
686
  # Example:
637
687
  #
@@ -661,23 +711,30 @@ module Ruport::Data
661
711
 
662
712
  # Provides a shortcut for the <tt>as()</tt> method by converting a call to
663
713
  # <tt>as(:format_name)</tt> into a call to <tt>to_format_name</tt>
714
+ #
715
+ # Also converts a call to <tt>rows_with_columnname</tt> to a call to
716
+ # <tt>rows_with(:columnname => args[0])</tt>.
717
+ #
664
718
  def method_missing(id,*args,&block)
665
719
  return as($1.to_sym,*args,&block) if id.to_s =~ /^to_(.*)/
666
720
  return rows_with($1.to_sym => args[0]) if id.to_s =~ /^rows_with_(.*)/
667
721
  super
668
722
  end
669
723
 
724
+ # Appends an array as a record in the Table.
670
725
  def append_array(array)
671
726
  attributes = @column_names.empty? ? nil : @column_names
672
727
  @data << record_class.new(array.to_ary, :attributes => attributes)
673
728
  end
674
729
 
730
+ # Appends a hash as a record in the Table.
675
731
  def append_hash(hash_obj)
676
732
  hash_obj = hash_obj.to_hash
677
733
  raise ArgumentError unless @column_names
678
734
  @data << record_class.new(hash_obj, :attributes => @column_names)
679
735
  end
680
736
 
737
+ # Appends a record to the Table.
681
738
  def append_record(record)
682
739
  self << record.send(column_names.empty? ? :to_a : :to_hash)
683
740
  end