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,11 +1,55 @@
1
- module Ruport
1
+ # Ruport : Extensible Reporting System
2
+ #
3
+ # formatter/text.rb provides text formatting for Ruport.
4
+ #
5
+ # Created by Gregory Brown, some time around Spring 2006.
6
+ # Copyright (C) 2006-2007, All Rights Reserved.
7
+ #
8
+ # Mathijs Mohlmann and Marshall T. Vandegrift have provided some patches for
9
+ # this class, see AUTHORS file for details.
10
+ #
11
+ # This is free software distributed under the same terms as Ruby 1.8
12
+ # See LICENSE and COPYING for details.
13
+ module Ruport
14
+ # This class provides text output for Ruport's Row,Table,Group, and Grouping
15
+ # renderers
16
+ #
17
+ # It handles things like automatically truncating tables that go off the
18
+ # edge of the screen in the console, proper column alignment, and pretty
19
+ # output that looks something like this:
20
+ #
21
+ # +-----------------------------+
22
+ # | apple | banana | strawberry |
23
+ # +-----------------------------+
24
+ # | yes | no | yes |
25
+ # | yes | yes | god yes |
26
+ # | what | the | f? |
27
+ # +-----------------------------+
28
+ #
29
+ # === Supported Options
30
+ #
31
+ # <tt>:max_col_width:</tt> Ordinal array of column widths. Set automatically
32
+ # but can be overridden
33
+ #
34
+ # <tt>:alignment:</tt> Defaults to left justify text and right justify numbers.
35
+ # centers all fields when set to :center
36
+ #
37
+ # <tt>:table_width:</tt> Will truncate rows at this limit.
38
+ #
39
+ # <tt>:show_table_headers:</tt> Defaults to true
40
+ #
41
+ # <tt>:show_group_headers:</tt> Defaults to true
42
+ #
43
+ # <tt>:ignore_table_width:</tt> When set to true, outputs full table without
44
+ # truncating it. Useful for file output
2
45
  class Formatter::Text < Formatter
3
46
 
4
47
  renders :text, :for => [ Renderer::Row, Renderer::Table,
5
48
  Renderer::Group, Renderer::Grouping ]
6
49
 
7
50
  opt_reader :max_col_width, :alignment, :table_width,
8
- :show_table_headers, :show_group_headers
51
+ :show_table_headers, :show_group_headers,
52
+ :ignore_table_width
9
53
 
10
54
  # Checks to ensure the table is not empty and then calls
11
55
  # calculate_max_col_widths
@@ -47,13 +91,22 @@ module Ruport
47
91
  rend.options do |o|
48
92
  o.max_col_width = max_col_width
49
93
  o.alignment = alignment
50
- o.table_width = table_width
94
+ o.table_width = table_width
95
+ o.ignore_table_width = ignore_table_width
51
96
  end
52
97
  end
53
98
 
54
99
  output << fit_to_width(hr)
55
100
  end
56
-
101
+
102
+ # Generates a formatted text row.
103
+ #
104
+ # Defaults to numeric values being right justified, and other values being
105
+ # left justified. Can be changed to support centering of output by
106
+ # setting options.alignment to :center
107
+ #
108
+ # Uses fit_to_width to truncate table if necessary.
109
+ #
57
110
  def build_row
58
111
  max_col_widths_for_row(data) unless max_col_width
59
112
 
@@ -113,7 +166,8 @@ module Ruport
113
166
  end
114
167
 
115
168
  # Truncates a string so that it does not exceed Text#width
116
- def fit_to_width(s)
169
+ def fit_to_width(s)
170
+ return s if options.ignore_table_width
117
171
  # workaround for Rails setting terminal_width to 1
118
172
  max_width = width < 2 ? 80 : width
119
173
 
@@ -137,7 +191,9 @@ module Ruport
137
191
 
138
192
  data.each { |r| max_col_widths_for_row(r) }
139
193
  end
140
-
194
+
195
+ # used to calculate the <tt>max_col_widths</tt> array.
196
+ # Override this to tweak the automatic column size adjustments.
141
197
  def max_col_widths_for_row(row)
142
198
  options.max_col_width ||= []
143
199
  row.each_with_index do |f,i|
data/lib/ruport/query.rb CHANGED
@@ -1,3 +1,15 @@
1
+ # Ruport : Extensible Reporting System
2
+ #
3
+ # query.rb provides a basic wrapper around RubyDBI for SQL interaction
4
+ #
5
+ # Original work began by Gregory Brown based on ideas from James Edward Gray II
6
+ # in August, 2005.
7
+ #
8
+ # Copyright (C) 2005-2007, Gregory Brown
9
+ # All Rights Reserved.
10
+ #
11
+ # This is free software distributed under the same terms as Ruby 1.8
12
+ # See LICENSE and COPYING for details.
1
13
  require "generator"
2
14
  require "ruport/query/sql_split"
3
15
 
@@ -5,17 +17,18 @@ module Ruport
5
17
 
6
18
  # === Overview
7
19
  #
8
- # Query offers a way to interact with databases via DBI. It supports
9
- # returning result sets in either Ruport's native Data::Table, or in their
20
+ # Query offers a way to interact with databases via RubyDBI. It supports
21
+ # returning result sets in either Ruport's Data::Table, or in their
10
22
  # raw form as DBI::Rows.
11
23
  #
12
- # It offers basic caching support, the ability to instantiate a generator
13
- # for a result set, and the ability to quickly and easily swap between data
14
- # sources.
24
+ # Query allows you to treat your result sets as an Enumerable data structure
25
+ # that plays well with the rest of Ruport.
26
+ #
27
+ # If you are using ActiveRecord, you might prefer our acts_as_reportable
28
+ # extension.
15
29
  #
16
30
  class Query
17
-
18
-
31
+
19
32
  include Enumerable
20
33
 
21
34
  # Ruport::Query provides an interface for dealing with raw SQL queries.
@@ -33,12 +46,8 @@ module Ruport
33
46
  # be set with this option.
34
47
  # <b><tt>:password</tt></b>:: If a DSN is specified, the password
35
48
  # can be set with this option.
36
- # <b><tt>:raw_data</tt></b>:: When set to true, DBI::Rows will be
37
- # returned instead of a Data::Table.
38
- # <b><tt>:cache_enabled</tt></b>:: When set to true, Query will download
39
- # results only once, and then return
40
- # cached values until the cache has been
41
- # cleared.
49
+ # <b><tt>:row_type</tt></b>:: When set to :raw, DBI::Rows will be
50
+ # returned instead of a Data::Table
42
51
  #
43
52
  # Examples:
44
53
  #
@@ -56,12 +65,19 @@ module Ruport
56
65
  # Ruport::Query.new("my_query.sql")
57
66
  #
58
67
  # # explicitly use a file, even if it doesn't end in .sql
59
- # Ruport::Query.new("foo",:origin => :file)
68
+ # Ruport::Query.new(:file => "foo")
60
69
  #
61
- def initialize(sql, options={})
62
- options = { :source => :default, :origin => :string }.merge(options)
63
- options[:origin] = :file if sql =~ /.sql$/
64
- @statements = SqlSplit.new(get_query(options[:origin],sql))
70
+ def initialize(sql, options={})
71
+ if sql.kind_of?(Hash)
72
+ options = { :source => :default }.merge(sql)
73
+ sql = options[:file] || options[:string]
74
+ else
75
+ options = { :source => :default, :string => sql }.merge(options)
76
+ options[:file] = sql if sql =~ /.sql$/
77
+ end
78
+ origin = options[:file] ? :file : :string
79
+
80
+ @statements = SqlSplit.new(get_query(origin,sql))
65
81
  @sql = @statements.join
66
82
 
67
83
  if options[:dsn]
@@ -76,28 +92,43 @@ module Ruport
76
92
  @raw_data = options[:row_type].eql?(:raw)
77
93
  @params = options[:params]
78
94
  end
79
-
95
+
96
+ # Returns an OpenStruct with the configuration options for the default
97
+ # database source.
98
+ #
80
99
  def self.default_source
81
100
  sources[:default]
82
101
  end
83
-
102
+
103
+ # Returns a hash of database sources, keyed by label.
84
104
  def self.sources
85
105
  @sources ||= {}
86
106
  end
87
-
107
+
108
+ # Allows you to add a labeled DBI source configuration.
109
+ #
110
+ # Query objects will use the source labeled <tt>:default</tt>,
111
+ # unless another source is specified.
112
+ #
113
+ # Examples:
114
+ #
115
+ # # a connection to a MySQL database foo with user root, pass chunkybacon
116
+ # Query.add_source :default, :dsn => "dbi:mysql:foo",
117
+ # :user => "root",
118
+ # :password => "chunkybacon"
119
+ #
120
+ #
121
+ # # a second connection to a MySQL database bar
122
+ # Query.add_source :test, :dsn => "dbi:mysql:bar",
123
+ # :user => "tester",
124
+ # :password => "blinky"
125
+ #
126
+ #
88
127
  def self.add_source(name,options={})
89
128
  sources[name] = OpenStruct.new(options)
90
129
  check_source(sources[name],name)
91
130
  end
92
131
 
93
- private
94
-
95
- def self.check_source(settings,label) # :nodoc:
96
- raise ArgumentError unless settings.dsn
97
- end
98
-
99
- public
100
-
101
132
  attr_accessor :raw_data
102
133
 
103
134
  # The original SQL for the Query object
@@ -112,20 +143,20 @@ module Ruport
112
143
  @password = Ruport::Query.sources[label].password
113
144
  end
114
145
 
146
+ # Yields result set by row.
115
147
  def each(&action)
116
148
  raise(LocalJumpError, "No block given!") unless action
117
149
  fetch(&action)
118
150
  self
119
151
  end
120
152
 
153
+ # Runs the SQL query and returns the result set
121
154
  def result; fetch; end
122
155
 
123
156
  # Runs the query without returning its results.
124
157
  def execute; fetch; nil; end
125
158
 
126
159
  # Returns a Data::Table, even if in <tt>raw_data</tt> mode.
127
- # This doesn't work with raw data if the cache is enabled and filled.
128
- #
129
160
  def to_table
130
161
  data_flag, @raw_data = @raw_data, false
131
162
  data = fetch; @raw_data = data_flag; return data
@@ -176,14 +207,6 @@ module Ruport
176
207
  type.eql?(:file) ? load_file( query ) : query
177
208
  end
178
209
 
179
- def load_file(query_file)
180
- begin
181
- File.read( query_file ).strip
182
- rescue
183
- raise LoadError, "Could not open #{query_file}"
184
- end
185
- end
186
-
187
210
  def fetch(&block)
188
211
  data = nil
189
212
  final = @statements.size - 1
@@ -192,5 +215,18 @@ module Ruport
192
215
  end
193
216
  return data
194
217
  end
218
+
219
+ def load_file(query_file)
220
+ begin
221
+ File.read( query_file ).strip
222
+ rescue
223
+ raise LoadError, "Could not open #{query_file}"
224
+ end
225
+ end
226
+
227
+ def self.check_source(settings,label) # :nodoc:
228
+ raise ArgumentError unless settings.dsn
229
+ end
230
+
195
231
  end
196
232
  end
@@ -13,62 +13,156 @@
13
13
  # This class can easily be extended to build custom formatting systems, but if
14
14
  # you do not need that, it may not be relevant to study for your use of Ruport.
15
15
  class Ruport::Renderer
16
-
17
- class RequiredOptionNotSet < RuntimeError; end
18
- class UnknownFormatError < RuntimeError; end
19
- class StageAlreadyDefinedError < RuntimeError; end
20
- class RendererNotSetError < RuntimeError; end
21
-
22
- require "ostruct"
23
- class Options < OpenStruct #:nodoc:
16
+
17
+ class RequiredOptionNotSet < RuntimeError #:nodoc:
18
+ end
19
+ class UnknownFormatError < RuntimeError #:nodoc:
20
+ end
21
+ class StageAlreadyDefinedError < RuntimeError #:nodoc:
22
+ end
23
+ class RendererNotSetError < RuntimeError #:nodoc:
24
+ end
25
+
26
+ require "ostruct"
27
+
28
+ # Structure for holding renderer options.
29
+ # Simplified version of HashWithIndifferentAccess
30
+ class Options < OpenStruct
31
+ # returns a Hash object. Use this if you need methods other than []
24
32
  def to_hash
25
33
  @table
26
- end
34
+ end
35
+ # indifferent lookup of an attribute, e.g.
36
+ #
37
+ # options[:foo] == options["foo"]
27
38
  def [](key)
28
39
  send(key)
29
- end
40
+ end
41
+
42
+ # Sets an attribute, with indifferent access.
43
+ #
44
+ # options[:foo] = "bar"
45
+ #
46
+ # options[:foo] == options["foo"] #=> true
47
+ # options["foo"] == options.foo #=> true
48
+ # options.foo #=> "bar"
30
49
  def []=(key,value)
31
50
  send("#{key}=",value)
32
51
  end
33
52
  end
34
-
35
- module Hooks #:nodoc:
36
- module ClassMethods
53
+
54
+ # This module provides hooks into Ruport's formatting system.
55
+ # It is used to implement the as() method for all of Ruport's datastructures,
56
+ # as well as the renders_with and renders_as_* helpers.
57
+ #
58
+ # You can actually use this with any data structure, it will look for a
59
+ # renderable_data method to pass to the <tt>renderer</tt> you specify,
60
+ # but if that is not defined, it will pass <tt>self</tt>
61
+ #
62
+ # Examples:
63
+ #
64
+ # # Render Arrays with Ruport's Row Renderer
65
+ # class Array
66
+ # include Ruport::Renderer::Hooks
67
+ # renders_as_row
68
+ # end
69
+ #
70
+ # # >> [1,2,3].as(:csv)
71
+ # # => "1,2,3\n"
72
+ #
73
+ # # Render Hashes with Ruport's Row Renderer
74
+ # class Hash
75
+ # include Ruport::Renderer::Hooks
76
+ # renders_as_row
77
+ # attr_accessor :column_order
78
+ # def renderable_data
79
+ # column_order.map { |c| self[c] }
80
+ # end
81
+ # end
82
+ #
83
+ # # >> a = { :a => 1, :b => 2, :c => 3 }
84
+ # # >> a.column_order = [:b,:a,:c]
85
+ # # >> a.as(:csv)
86
+ # # => "2,1,3\n"
87
+ module Hooks
88
+ module ClassMethods
89
+
90
+ # Tells the class which renderer as() will forward to.
91
+ #
92
+ # usage:
93
+ #
94
+ # class MyStructure
95
+ # include Renderer::Hooks
96
+ # renders_with CustomRenderer
97
+ # end
98
+ #
99
+ # You can also specify default rendering options, which will be used
100
+ # if they are not overriden by the options passed to as()
101
+ #
102
+ # class MyStructure
103
+ # include Renderer::Hooks
104
+ # renders_with CustomRenderer, :font_size => 14
105
+ # end
37
106
  def renders_with(renderer,opts={})
38
107
  @renderer = renderer.name
39
108
  @rendering_options=opts
40
109
  end
41
-
110
+
111
+ # The default rendering options for a class, stored as a hash.
42
112
  def rendering_options
43
113
  @rendering_options
44
114
  end
45
-
115
+
116
+ # Shortcut for renders_with(Ruport::Renderer::Table), you
117
+ # may wish to override this if you build a custom table renderer.
46
118
  def renders_as_table(options={})
47
119
  renders_with Ruport::Renderer::Table,options
48
120
  end
49
-
121
+
122
+ # Shortcut for renders_with(Ruport::Renderer::Row), you
123
+ # may wish to override this if you build a custom row renderer.
50
124
  def renders_as_row(options={})
51
125
  renders_with Ruport::Renderer::Row, options
52
126
  end
53
-
127
+
128
+ # Shortcut for renders_with(Ruport::Renderer::Group), you
129
+ # may wish to override this if you build a custom group renderer.
54
130
  def renders_as_group(options={})
55
131
  renders_with Ruport::Renderer::Group,options
56
132
  end
57
133
 
134
+ # Shortcut for renders_with(Ruport::Renderer::Grouping), you
135
+ # may wish to override this if you build a custom grouping renderer.
58
136
  def renders_as_grouping(options={})
59
137
  renders_with Ruport::Renderer::Grouping,options
60
138
  end
61
-
139
+
140
+ # The class of the renderer object for the base class.
141
+ #
142
+ # Example
143
+ #
144
+ # >> Ruport::Data::Table.renderer
145
+ # => Ruport::Renderer::Table
62
146
  def renderer
63
147
  return unless @renderer
64
148
  @renderer.split("::").inject(Class) { |c,el| c.const_get(el) }
65
149
  end
66
150
  end
67
151
 
68
- def self.included(base)
152
+ def self.included(base) #:nodoc:
69
153
  base.extend(ClassMethods)
70
154
  end
71
-
155
+
156
+ # Uses the Renderer specified by renders_with to generate formatted
157
+ # output. Passes the return value of the <tt>renderable_data</tt> method if
158
+ # the method is defined, otherwise passes <tt>self</tt> as :data
159
+ #
160
+ # The remaining options are converted to a Renderer::Options object and
161
+ # accessible in both the renderer and formatter.
162
+ #
163
+ # Example:
164
+ #
165
+ # table.as(:csv, :show_table_headers => false)
72
166
  def as(format,options={})
73
167
  raise RendererNotSetError unless self.class.renderer
74
168
  unless self.class.renderer.formats.include?(format)
@@ -122,28 +216,125 @@ class Ruport::Renderer
122
216
  class << self
123
217
 
124
218
  attr_accessor :first_stage,:final_stage,:required_options,:stages #:nodoc:
125
-
219
+
220
+ # Registers a hook to look for in the Formatter object when the render()
221
+ # method is called.
222
+ #
223
+ # Usage:
224
+ #
225
+ # class MyRenderer < Ruport::Renderer
226
+ # # other details omitted...
227
+ # finalize :apple
228
+ # end
229
+ #
230
+ # class MyFormatter < Ruport::Formatter
231
+ # renders :example, :for => MyRenderer
232
+ #
233
+ # # other details omitted...
234
+ #
235
+ # def finalize_apple
236
+ # # this method will be called when MyRenderer tries to render
237
+ # # the :example format
238
+ # end
239
+ # end
240
+ #
241
+ # If a formatter does not implement this hook, it is simply ignored.
126
242
  def finalize(stage)
127
243
  if final_stage
128
244
  raise StageAlreadyDefinedError, 'final stage already defined'
129
245
  end
130
246
  self.final_stage = stage
131
247
  end
132
-
248
+
249
+ # Registers a hook to look for in the Formatter object when the render()
250
+ # method is called.
251
+ #
252
+ # Usage:
253
+ #
254
+ # class MyRenderer < Ruport::Renderer
255
+ # # other details omitted...
256
+ # prepare :apple
257
+ # end
258
+ #
259
+ # class MyFormatter < Ruport::Formatter
260
+ # renders :example, :for => MyRenderer
261
+ #
262
+ # def prepare_apple
263
+ # # this method will be called when MyRenderer tries to render
264
+ # # the :example format
265
+ # end
266
+ #
267
+ # # other details omitted...
268
+ # end
269
+ #
270
+ # If a formatter does not implement this hook, it is simply ignored.
133
271
  def prepare(stage)
134
272
  if first_stage
135
273
  raise StageAlreadyDefinedError, "prepare stage already defined"
136
274
  end
137
275
  self.first_stage = stage
138
276
  end
139
-
277
+
278
+ # Registers hooks to look for in the Formatter object when the render()
279
+ # method is called.
280
+ #
281
+ # Usage:
282
+ #
283
+ # class MyRenderer < Ruport::Renderer
284
+ # # other details omitted...
285
+ # stage :apple,:banana
286
+ # end
287
+ #
288
+ # class MyFormatter < Ruport::Formatter
289
+ # renders :example, :for => MyRenderer
290
+ #
291
+ # def build_apple
292
+ # # this method will be called when MyRenderer tries to render
293
+ # # the :example format
294
+ # end
295
+ #
296
+ # def build_banana
297
+ # # this method will be called when MyRenderer tries to render
298
+ # # the :example format
299
+ # end
300
+ #
301
+ # # other details omitted...
302
+ # end
303
+ #
304
+ # If a formatter does not implement these hooks, they are simply ignored.
305
+ def stage(*stage_list)
306
+ self.stages ||= []
307
+ stage_list.each { |stage|
308
+ self.stages << stage.to_s
309
+ }
310
+ end
311
+
312
+ # Defines attribute writers for the Renderer::Options object shared
313
+ # between Renderer and Formatter
314
+ #
315
+ # usage:
316
+ #
317
+ # class MyRenderer < Ruport::Renderer
318
+ # option :font_size, :font_style
319
+ # # other details omitted
320
+ # end
140
321
  def option(*opts)
141
322
  opts.each do |opt|
142
323
  opt = "#{opt}="
143
324
  define_method(opt) {|t| options.send(opt, t) }
144
325
  end
145
326
  end
146
-
327
+
328
+ # Defines attribute writers for the Renderer::Options object shared
329
+ # between Renderer and Formatter. Will throw an error if the user does
330
+ # not provide values for these options upon rendering.
331
+ #
332
+ # usage:
333
+ #
334
+ # class MyRenderer < Ruport::Renderer
335
+ # required_option :employee_name, :address
336
+ # # other details omitted
337
+ # end
147
338
  def required_option(*opts)
148
339
  self.required_options ||= []
149
340
  opts.each do |opt|
@@ -151,18 +342,38 @@ class Ruport::Renderer
151
342
  option opt
152
343
  end
153
344
  end
345
+
154
346
 
155
- def stage(*stage_list)
156
- self.stages ||= []
157
- stage_list.each { |stage|
158
- self.stages << stage.to_s
159
- }
160
- end
161
-
347
+ # Lists the formatters that are currently registered on a renderer,
348
+ # as a hash keyed by format name.
349
+ #
350
+ # Example:
351
+ #
352
+ # >> Ruport::Renderer::Table.formats
353
+ # => {:html=>Ruport::Formatter::HTML,
354
+ # ?> :csv=>Ruport::Formatter::CSV,
355
+ # ?> :text=>Ruport::Formatter::Text,
356
+ # ?> :pdf=>Ruport::Formatter::PDF}
162
357
  def formats
163
358
  @formats ||= {}
164
359
  end
165
-
360
+
361
+ # Builds up a renderer object, looks up the appropriate formatter,
362
+ # sets the data and options, and then does the following process:
363
+ #
364
+ # * If the renderer contains a module Helpers, mix it in to the instance.
365
+ # * If a setup() method is defined on the Renderer, call it
366
+ # * If a block is given, yield the Renderer instance
367
+ # * If the renderer has defined a run() method, call it, otherwise,
368
+ # include Renderer::AutoRunner. (you usually won't need a run() method )
369
+ # * call _run_ if it exists (This is provided by default, by AutoRunner)
370
+ # * return the results of formatter.output
371
+ #
372
+ # Note that the only time you will need a run() method is if you can't
373
+ # do what you need to via a helpers module or via setup()
374
+ #
375
+ # Please see the examples/ directory for custom renderer examples, because
376
+ # this is not nearly as complicated as it sounds in most cases.
166
377
  def render(*args)
167
378
  rend = build(*args) { |r|
168
379
  r.setup if r.respond_to? :setup
@@ -230,10 +441,14 @@ class Ruport::Renderer
230
441
  end
231
442
 
232
443
  end
233
-
234
- attr_accessor :format
444
+
445
+ # The name of format being used
446
+ attr_accessor :format
447
+
448
+ # The formatter object being used
235
449
  attr_writer :formatter
236
-
450
+
451
+ # The +data+ that has been passed to the active formatter.
237
452
  def data
238
453
  formatter.data
239
454
  end