ruport 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
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