ruport 1.0.2 → 1.2.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.
- data/AUTHORS +3 -0
- data/README +11 -5
- data/Rakefile +2 -2
- data/examples/btree/commaleon/commaleon.rb +1 -1
- data/examples/simple_templating_example.rb +34 -0
- data/examples/tattle_rubygems_version.rb +6 -5
- data/examples/trac_ticket_status.rb +2 -2
- data/lib/ruport.rb +5 -4
- data/lib/ruport/acts_as_reportable.rb +63 -37
- data/lib/ruport/data.rb +1 -0
- data/lib/ruport/data/feeder.rb +111 -0
- data/lib/ruport/data/grouping.rb +84 -22
- data/lib/ruport/data/record.rb +1 -1
- data/lib/ruport/data/table.rb +127 -87
- data/lib/ruport/formatter.rb +22 -9
- data/lib/ruport/formatter/csv.rb +27 -3
- data/lib/ruport/formatter/html.rb +26 -6
- data/lib/ruport/formatter/pdf.rb +169 -36
- data/lib/ruport/formatter/template.rb +167 -0
- data/lib/ruport/formatter/text.rb +47 -15
- data/lib/ruport/query.rb +1 -1
- data/lib/ruport/renderer.rb +46 -56
- data/test/acts_as_reportable_test.rb +20 -20
- data/test/csv_formatter_test.rb +26 -1
- data/test/data_feeder_test.rb +88 -0
- data/test/grouping_test.rb +90 -4
- data/test/html_formatter_test.rb +25 -2
- data/test/pdf_formatter_test.rb +69 -3
- data/test/query_test.rb +3 -2
- data/test/record_test.rb +2 -1
- data/test/renderer_test.rb +49 -3
- data/test/sql_split_test.rb +4 -2
- data/test/table_test.rb +159 -65
- data/test/template_test.rb +37 -0
- data/test/text_formatter_test.rb +33 -1
- metadata +9 -4
- data/lib/ruport/renderer.rb.orig +0 -542
- data/test/renderer_test.rb.orig +0 -512
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "helpers")
|
3
|
+
|
4
|
+
class TemplateTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@template_class = Ruport::Formatter::Template.dup
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_template_should_exist
|
11
|
+
@template_class.create(:foo)
|
12
|
+
assert_instance_of @template_class,
|
13
|
+
@template_class[:foo]
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_template_creation_yields_an_options_object
|
17
|
+
@template_class.create(:foo) do |template|
|
18
|
+
template.page_format = { :layout => :landscape,
|
19
|
+
:paper_size => :letter }
|
20
|
+
end
|
21
|
+
assert_equal :landscape, @template_class[:foo].page_format[:layout]
|
22
|
+
assert_equal :letter, @template_class[:foo].page_format[:paper_size]
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_create_derived_template
|
26
|
+
Ruport::Formatter::Template.create(:foo) do |template|
|
27
|
+
template.page_format = { :layout => :landscape,
|
28
|
+
:paper_size => :letter }
|
29
|
+
end
|
30
|
+
Ruport::Formatter::Template.create(:bar, :base => :foo)
|
31
|
+
assert_equal :landscape,
|
32
|
+
Ruport::Formatter::Template[:bar].page_format[:layout]
|
33
|
+
assert_equal :letter,
|
34
|
+
Ruport::Formatter::Template[:bar].page_format[:paper_size]
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
data/test/text_formatter_test.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
#!/usr/bin/env ruby -w
|
2
|
+
require File.join(File.expand_path(File.dirname(__FILE__)), "helpers")
|
2
3
|
|
3
4
|
class TestRenderTextTable < Test::Unit::TestCase
|
4
5
|
|
@@ -60,6 +61,37 @@ class TestRenderTextTable < Test::Unit::TestCase
|
|
60
61
|
"+-----------+\n"
|
61
62
|
assert_equal expected, a
|
62
63
|
end
|
64
|
+
|
65
|
+
def test_render_with_template
|
66
|
+
Ruport::Formatter::Template.create(:simple) do |t|
|
67
|
+
t.table_format = {
|
68
|
+
:show_headings => false,
|
69
|
+
:width => 50,
|
70
|
+
:ignore_width => true
|
71
|
+
}
|
72
|
+
t.column_format = {
|
73
|
+
:maximum_width => 5,
|
74
|
+
:alignment => :center
|
75
|
+
}
|
76
|
+
t.grouping_format = {
|
77
|
+
:show_headings => false
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
formatter = Ruport::Formatter::Text.new
|
82
|
+
formatter.options = Ruport::Renderer::Options.new
|
83
|
+
formatter.options.template = :simple
|
84
|
+
formatter.apply_template
|
85
|
+
|
86
|
+
assert_equal false, formatter.options.show_table_headers
|
87
|
+
assert_equal 50, formatter.options.table_width
|
88
|
+
assert_equal true, formatter.options.ignore_table_width
|
89
|
+
|
90
|
+
assert_equal 5, formatter.options.max_col_width
|
91
|
+
assert_equal :center, formatter.options.alignment
|
92
|
+
|
93
|
+
assert_equal false, formatter.options.show_group_headers
|
94
|
+
end
|
63
95
|
|
64
96
|
# -- BUG TRAPS ------------------------------
|
65
97
|
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
|
|
3
3
|
specification_version: 1
|
4
4
|
name: ruport
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.0
|
7
|
-
date: 2007-08-
|
6
|
+
version: 1.2.0
|
7
|
+
date: 2007-08-28 00:00:00 -04:00
|
8
8
|
summary: A generalized Ruby report generation and templating engine.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -40,6 +40,7 @@ files:
|
|
40
40
|
- examples/row_renderer.rb
|
41
41
|
- examples/RWEmerson.jpg
|
42
42
|
- examples/simple_pdf_lines.rb
|
43
|
+
- examples/simple_templating_example.rb
|
43
44
|
- examples/tattle_ruby_version.rb
|
44
45
|
- examples/tattle_rubygems_version.rb
|
45
46
|
- examples/trac_ticket_status.rb
|
@@ -62,19 +63,21 @@ files:
|
|
62
63
|
- lib/ruport/query.rb
|
63
64
|
- lib/ruport/renderer
|
64
65
|
- lib/ruport/renderer.rb
|
65
|
-
- lib/ruport/
|
66
|
+
- lib/ruport/data/feeder.rb
|
66
67
|
- lib/ruport/data/grouping.rb
|
67
68
|
- lib/ruport/data/record.rb
|
68
69
|
- lib/ruport/data/table.rb
|
69
70
|
- lib/ruport/formatter/csv.rb
|
70
71
|
- lib/ruport/formatter/html.rb
|
71
72
|
- lib/ruport/formatter/pdf.rb
|
73
|
+
- lib/ruport/formatter/template.rb
|
72
74
|
- lib/ruport/formatter/text.rb
|
73
75
|
- lib/ruport/query/sql_split.rb
|
74
76
|
- lib/ruport/renderer/grouping.rb
|
75
77
|
- lib/ruport/renderer/table.rb
|
76
78
|
- test/acts_as_reportable_test.rb
|
77
79
|
- test/csv_formatter_test.rb
|
80
|
+
- test/data_feeder_test.rb
|
78
81
|
- test/grouping_test.rb
|
79
82
|
- test/helpers.rb
|
80
83
|
- test/html_formatter_test.rb
|
@@ -82,10 +85,10 @@ files:
|
|
82
85
|
- test/query_test.rb
|
83
86
|
- test/record_test.rb
|
84
87
|
- test/renderer_test.rb
|
85
|
-
- test/renderer_test.rb.orig
|
86
88
|
- test/samples
|
87
89
|
- test/sql_split_test.rb
|
88
90
|
- test/table_test.rb
|
91
|
+
- test/template_test.rb
|
89
92
|
- test/text_formatter_test.rb
|
90
93
|
- test/samples/addressbook.csv
|
91
94
|
- test/samples/data.csv
|
@@ -123,6 +126,7 @@ files:
|
|
123
126
|
test_files:
|
124
127
|
- test/acts_as_reportable_test.rb
|
125
128
|
- test/csv_formatter_test.rb
|
129
|
+
- test/data_feeder_test.rb
|
126
130
|
- test/grouping_test.rb
|
127
131
|
- test/html_formatter_test.rb
|
128
132
|
- test/pdf_formatter_test.rb
|
@@ -131,6 +135,7 @@ test_files:
|
|
131
135
|
- test/renderer_test.rb
|
132
136
|
- test/sql_split_test.rb
|
133
137
|
- test/table_test.rb
|
138
|
+
- test/template_test.rb
|
134
139
|
- test/text_formatter_test.rb
|
135
140
|
rdoc_options:
|
136
141
|
- --title
|
data/lib/ruport/renderer.rb.orig
DELETED
@@ -1,542 +0,0 @@
|
|
1
|
-
# renderer.rb : General purpose formatted data renderer for Ruby Reports
|
2
|
-
#
|
3
|
-
# Copyright December 2006, Gregory Brown. All Rights Reserved.
|
4
|
-
#
|
5
|
-
# This is free software. Please see the LICENSE and COPYING files for details.
|
6
|
-
|
7
|
-
|
8
|
-
# This class implements the core renderer for Ruport's formatting system. It is
|
9
|
-
# designed to implement the low level tools necessary to build report renderers
|
10
|
-
# for different kinds of tasks. See Renderer::Table for a tabular data
|
11
|
-
# renderer.
|
12
|
-
#
|
13
|
-
class Ruport::Renderer
|
14
|
-
|
15
|
-
class RequiredOptionNotSet < RuntimeError #:nodoc:
|
16
|
-
end
|
17
|
-
class UnknownFormatError < RuntimeError #:nodoc:
|
18
|
-
end
|
19
|
-
class StageAlreadyDefinedError < RuntimeError #:nodoc:
|
20
|
-
end
|
21
|
-
class RendererNotSetError < RuntimeError #:nodoc:
|
22
|
-
end
|
23
|
-
|
24
|
-
require "ostruct"
|
25
|
-
|
26
|
-
# Structure for holding renderer options.
|
27
|
-
# Simplified version of HashWithIndifferentAccess
|
28
|
-
class Options < OpenStruct
|
29
|
-
# returns a Hash object. Use this if you need methods other than []
|
30
|
-
def to_hash
|
31
|
-
@table
|
32
|
-
end
|
33
|
-
# indifferent lookup of an attribute, e.g.
|
34
|
-
#
|
35
|
-
# options[:foo] == options["foo"]
|
36
|
-
def [](key)
|
37
|
-
send(key)
|
38
|
-
end
|
39
|
-
|
40
|
-
# Sets an attribute, with indifferent access.
|
41
|
-
#
|
42
|
-
# options[:foo] = "bar"
|
43
|
-
#
|
44
|
-
# options[:foo] == options["foo"] #=> true
|
45
|
-
# options["foo"] == options.foo #=> true
|
46
|
-
# options.foo #=> "bar"
|
47
|
-
def []=(key,value)
|
48
|
-
send("#{key}=",value)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
# This module provides hooks into Ruport's formatting system.
|
53
|
-
# It is used to implement the as() method for all of Ruport's datastructures,
|
54
|
-
# as well as the renders_with and renders_as_* helpers.
|
55
|
-
#
|
56
|
-
# You can actually use this with any data structure, it will look for a
|
57
|
-
# renderable_data method to pass to the <tt>renderer</tt> you specify,
|
58
|
-
# but if that is not defined, it will pass <tt>self</tt>
|
59
|
-
#
|
60
|
-
# Examples:
|
61
|
-
#
|
62
|
-
# # Render Arrays with Ruport's Row Renderer
|
63
|
-
# class Array
|
64
|
-
# include Ruport::Renderer::Hooks
|
65
|
-
# renders_as_row
|
66
|
-
# end
|
67
|
-
#
|
68
|
-
# # >> [1,2,3].as(:csv)
|
69
|
-
# # => "1,2,3\n"
|
70
|
-
#
|
71
|
-
# # Render Hashes with Ruport's Row Renderer
|
72
|
-
# class Hash
|
73
|
-
# include Ruport::Renderer::Hooks
|
74
|
-
# renders_as_row
|
75
|
-
# attr_accessor :column_order
|
76
|
-
# def renderable_data
|
77
|
-
# column_order.map { |c| self[c] }
|
78
|
-
# end
|
79
|
-
# end
|
80
|
-
#
|
81
|
-
# # >> a = { :a => 1, :b => 2, :c => 3 }
|
82
|
-
# # >> a.column_order = [:b,:a,:c]
|
83
|
-
# # >> a.as(:csv)
|
84
|
-
# # => "2,1,3\n"
|
85
|
-
module Hooks
|
86
|
-
module ClassMethods
|
87
|
-
|
88
|
-
# Tells the class which renderer as() will forward to.
|
89
|
-
#
|
90
|
-
# usage:
|
91
|
-
#
|
92
|
-
# class MyStructure
|
93
|
-
# include Renderer::Hooks
|
94
|
-
# renders_with CustomRenderer
|
95
|
-
# end
|
96
|
-
#
|
97
|
-
# You can also specify default rendering options, which will be used
|
98
|
-
# if they are not overriden by the options passed to as()
|
99
|
-
#
|
100
|
-
# class MyStructure
|
101
|
-
# include Renderer::Hooks
|
102
|
-
# renders_with CustomRenderer, :font_size => 14
|
103
|
-
# end
|
104
|
-
def renders_with(renderer,opts={})
|
105
|
-
@renderer = renderer.name
|
106
|
-
@rendering_options=opts
|
107
|
-
end
|
108
|
-
|
109
|
-
# The default rendering options for a class, stored as a hash.
|
110
|
-
def rendering_options
|
111
|
-
@rendering_options
|
112
|
-
end
|
113
|
-
|
114
|
-
# Shortcut for renders_with(Ruport::Renderer::Table), you
|
115
|
-
# may wish to override this if you build a custom table renderer.
|
116
|
-
def renders_as_table(options={})
|
117
|
-
renders_with Ruport::Renderer::Table,options
|
118
|
-
end
|
119
|
-
|
120
|
-
# Shortcut for renders_with(Ruport::Renderer::Row), you
|
121
|
-
# may wish to override this if you build a custom row renderer.
|
122
|
-
def renders_as_row(options={})
|
123
|
-
renders_with Ruport::Renderer::Row, options
|
124
|
-
end
|
125
|
-
|
126
|
-
# Shortcut for renders_with(Ruport::Renderer::Group), you
|
127
|
-
# may wish to override this if you build a custom group renderer.
|
128
|
-
def renders_as_group(options={})
|
129
|
-
renders_with Ruport::Renderer::Group,options
|
130
|
-
end
|
131
|
-
|
132
|
-
# Shortcut for renders_with(Ruport::Renderer::Grouping), you
|
133
|
-
# may wish to override this if you build a custom grouping renderer.
|
134
|
-
def renders_as_grouping(options={})
|
135
|
-
renders_with Ruport::Renderer::Grouping,options
|
136
|
-
end
|
137
|
-
|
138
|
-
# The class of the renderer object for the base class.
|
139
|
-
#
|
140
|
-
# Example
|
141
|
-
#
|
142
|
-
# >> Ruport::Data::Table.renderer
|
143
|
-
# => Ruport::Renderer::Table
|
144
|
-
def renderer
|
145
|
-
return unless @renderer
|
146
|
-
@renderer.split("::").inject(Class) { |c,el| c.const_get(el) }
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
def self.included(base) #:nodoc:
|
151
|
-
base.extend(ClassMethods)
|
152
|
-
end
|
153
|
-
|
154
|
-
# Uses the Renderer specified by renders_with to generate formatted
|
155
|
-
# output. Passes the return value of the <tt>renderable_data</tt> method if
|
156
|
-
# the method is defined, otherwise passes <tt>self</tt> as :data
|
157
|
-
#
|
158
|
-
# The remaining options are converted to a Renderer::Options object and
|
159
|
-
# accessible in both the renderer and formatter.
|
160
|
-
#
|
161
|
-
# Example:
|
162
|
-
#
|
163
|
-
# table.as(:csv, :show_table_headers => false)
|
164
|
-
def as(format,options={})
|
165
|
-
raise RendererNotSetError unless self.class.renderer
|
166
|
-
unless self.class.renderer.formats.include?(format)
|
167
|
-
raise UnknownFormatError
|
168
|
-
end
|
169
|
-
self.class.renderer.render(format,
|
170
|
-
self.class.rendering_options.merge(options)) do |rend|
|
171
|
-
rend.data = respond_to?(:renderable_data) ? renderable_data : self
|
172
|
-
yield(rend) if block_given?
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
|
178
|
-
module AutoRunner #:nodoc:
|
179
|
-
# called automagically when the report is rendered. Uses the
|
180
|
-
# data collected from the earlier methods.
|
181
|
-
def _run_
|
182
|
-
|
183
|
-
# ensure all the required options have been set
|
184
|
-
unless self.class.required_options.nil?
|
185
|
-
self.class.required_options.each do |opt|
|
186
|
-
if options.__send__(opt).nil?
|
187
|
-
raise RequiredOptionNotSet, "Required option #{opt} not set"
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
prepare self.class.first_stage if self.class.first_stage
|
193
|
-
|
194
|
-
if formatter.respond_to?(:layout)
|
195
|
-
formatter.layout do execute_stages end
|
196
|
-
else
|
197
|
-
execute_stages
|
198
|
-
end
|
199
|
-
|
200
|
-
finalize self.class.final_stage if self.class.final_stage
|
201
|
-
|
202
|
-
end
|
203
|
-
|
204
|
-
def execute_stages
|
205
|
-
# call each stage to build the report
|
206
|
-
unless self.class.stages.nil?
|
207
|
-
self.class.stages.each do |stage|
|
208
|
-
self.send(:build,stage)
|
209
|
-
end
|
210
|
-
end
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
214
|
-
class << self
|
215
|
-
|
216
|
-
attr_accessor :first_stage,:final_stage,:required_options,:stages #:nodoc:
|
217
|
-
|
218
|
-
# Registers a hook to look for in the Formatter object when the render()
|
219
|
-
# method is called.
|
220
|
-
#
|
221
|
-
# Usage:
|
222
|
-
#
|
223
|
-
# class MyRenderer < Ruport::Renderer
|
224
|
-
# # other details omitted...
|
225
|
-
# finalize :apple
|
226
|
-
# end
|
227
|
-
#
|
228
|
-
# class MyFormatter < Ruport::Formatter
|
229
|
-
# renders :example, :for => MyRenderer
|
230
|
-
#
|
231
|
-
# # other details omitted...
|
232
|
-
#
|
233
|
-
# def finalize_apple
|
234
|
-
# # this method will be called when MyRenderer tries to render
|
235
|
-
# # the :example format
|
236
|
-
# end
|
237
|
-
# end
|
238
|
-
#
|
239
|
-
# If a formatter does not implement this hook, it is simply ignored.
|
240
|
-
def finalize(stage)
|
241
|
-
if final_stage
|
242
|
-
raise StageAlreadyDefinedError, 'final stage already defined'
|
243
|
-
end
|
244
|
-
self.final_stage = stage
|
245
|
-
end
|
246
|
-
|
247
|
-
# Registers a hook to look for in the Formatter object when the render()
|
248
|
-
# method is called.
|
249
|
-
#
|
250
|
-
# Usage:
|
251
|
-
#
|
252
|
-
# class MyRenderer < Ruport::Renderer
|
253
|
-
# # other details omitted...
|
254
|
-
# prepare :apple
|
255
|
-
# end
|
256
|
-
#
|
257
|
-
# class MyFormatter < Ruport::Formatter
|
258
|
-
# renders :example, :for => MyRenderer
|
259
|
-
#
|
260
|
-
# def prepare_apple
|
261
|
-
# # this method will be called when MyRenderer tries to render
|
262
|
-
# # the :example format
|
263
|
-
# end
|
264
|
-
#
|
265
|
-
# # other details omitted...
|
266
|
-
# end
|
267
|
-
#
|
268
|
-
# If a formatter does not implement this hook, it is simply ignored.
|
269
|
-
def prepare(stage)
|
270
|
-
if first_stage
|
271
|
-
raise StageAlreadyDefinedError, "prepare stage already defined"
|
272
|
-
end
|
273
|
-
self.first_stage = stage
|
274
|
-
end
|
275
|
-
|
276
|
-
# Registers hooks to look for in the Formatter object when the render()
|
277
|
-
# method is called.
|
278
|
-
#
|
279
|
-
# Usage:
|
280
|
-
#
|
281
|
-
# class MyRenderer < Ruport::Renderer
|
282
|
-
# # other details omitted...
|
283
|
-
# stage :apple,:banana
|
284
|
-
# end
|
285
|
-
#
|
286
|
-
# class MyFormatter < Ruport::Formatter
|
287
|
-
# renders :example, :for => MyRenderer
|
288
|
-
#
|
289
|
-
# def build_apple
|
290
|
-
# # this method will be called when MyRenderer tries to render
|
291
|
-
# # the :example format
|
292
|
-
# end
|
293
|
-
#
|
294
|
-
# def build_banana
|
295
|
-
# # this method will be called when MyRenderer tries to render
|
296
|
-
# # the :example format
|
297
|
-
# end
|
298
|
-
#
|
299
|
-
# # other details omitted...
|
300
|
-
# end
|
301
|
-
#
|
302
|
-
# If a formatter does not implement these hooks, they are simply ignored.
|
303
|
-
def stage(*stage_list)
|
304
|
-
self.stages ||= []
|
305
|
-
stage_list.each { |stage|
|
306
|
-
self.stages << stage.to_s
|
307
|
-
}
|
308
|
-
end
|
309
|
-
|
310
|
-
# Defines attribute writers for the Renderer::Options object shared
|
311
|
-
# between Renderer and Formatter
|
312
|
-
#
|
313
|
-
# usage:
|
314
|
-
#
|
315
|
-
# class MyRenderer < Ruport::Renderer
|
316
|
-
# option :font_size, :font_style
|
317
|
-
# # other details omitted
|
318
|
-
# end
|
319
|
-
def option(*opts)
|
320
|
-
opts.each do |opt|
|
321
|
-
o = opt
|
322
|
-
unless instance_methods(false).include?(o.to_s)
|
323
|
-
define_method(o) {
|
324
|
-
options.send(o.to_s)
|
325
|
-
}
|
326
|
-
end
|
327
|
-
opt = "#{opt}="
|
328
|
-
define_method(opt) {|t| options.send(opt, t) }
|
329
|
-
end
|
330
|
-
end
|
331
|
-
|
332
|
-
# Defines attribute writers for the Renderer::Options object shared
|
333
|
-
# between Renderer and Formatter. Will throw an error if the user does
|
334
|
-
# not provide values for these options upon rendering.
|
335
|
-
#
|
336
|
-
# usage:
|
337
|
-
#
|
338
|
-
# class MyRenderer < Ruport::Renderer
|
339
|
-
# required_option :employee_name, :address
|
340
|
-
# # other details omitted
|
341
|
-
# end
|
342
|
-
def required_option(*opts)
|
343
|
-
self.required_options ||= []
|
344
|
-
opts.each do |opt|
|
345
|
-
self.required_options << opt
|
346
|
-
option opt
|
347
|
-
end
|
348
|
-
end
|
349
|
-
|
350
|
-
|
351
|
-
# Lists the formatters that are currently registered on a renderer,
|
352
|
-
# as a hash keyed by format name.
|
353
|
-
#
|
354
|
-
# Example:
|
355
|
-
#
|
356
|
-
# >> Ruport::Renderer::Table.formats
|
357
|
-
# => {:html=>Ruport::Formatter::HTML,
|
358
|
-
# ?> :csv=>Ruport::Formatter::CSV,
|
359
|
-
# ?> :text=>Ruport::Formatter::Text,
|
360
|
-
# ?> :pdf=>Ruport::Formatter::PDF}
|
361
|
-
def formats
|
362
|
-
@formats ||= {}
|
363
|
-
end
|
364
|
-
|
365
|
-
# Builds up a renderer object, looks up the appropriate formatter,
|
366
|
-
# sets the data and options, and then does the following process:
|
367
|
-
#
|
368
|
-
# * If the renderer contains a module Helpers, mix it in to the instance.
|
369
|
-
# * If a block is given, yield the Renderer instance
|
370
|
-
# * If a setup() method is defined on the Renderer, call it
|
371
|
-
# * If the renderer has defined a run() method, call it, otherwise,
|
372
|
-
# include Renderer::AutoRunner. (you usually won't need a run() method )
|
373
|
-
# * call _run_ if it exists (This is provided by default, by AutoRunner)
|
374
|
-
# * return the results of formatter.output
|
375
|
-
#
|
376
|
-
# Note that the only time you will need a run() method is if you can't
|
377
|
-
# do what you need to via a helpers module or via setup()
|
378
|
-
#
|
379
|
-
# Please see the examples/ directory for custom renderer examples, because
|
380
|
-
# this is not nearly as complicated as it sounds in most cases.
|
381
|
-
def render(*args)
|
382
|
-
rend = build(*args) { |r|
|
383
|
-
yield(r) if block_given?
|
384
|
-
r.setup if r.respond_to? :setup
|
385
|
-
}
|
386
|
-
if rend.respond_to? :run
|
387
|
-
rend.run
|
388
|
-
else
|
389
|
-
include AutoRunner
|
390
|
-
end
|
391
|
-
rend._run_ if rend.respond_to? :_run_
|
392
|
-
return rend.formatter.output
|
393
|
-
end
|
394
|
-
|
395
|
-
# Allows you to set class_wide default options
|
396
|
-
#
|
397
|
-
# Example:
|
398
|
-
#
|
399
|
-
# options { |o| o.style = :justified }
|
400
|
-
#
|
401
|
-
def options
|
402
|
-
@options ||= Ruport::Renderer::Options.new
|
403
|
-
yield(@options) if block_given?
|
404
|
-
|
405
|
-
return @options
|
406
|
-
end
|
407
|
-
|
408
|
-
# Creates a new instance of the renderer and sets it to use the specified
|
409
|
-
# formatter (by name). If a block is given, the renderer instance is
|
410
|
-
# yielded.
|
411
|
-
#
|
412
|
-
# Returns the renderer instance.
|
413
|
-
#
|
414
|
-
def build(*args)
|
415
|
-
rend = self.new
|
416
|
-
|
417
|
-
rend.send(:use_formatter,args[0])
|
418
|
-
rend.send(:options=, options.dup)
|
419
|
-
if rend.class.const_defined? :Helpers
|
420
|
-
rend.formatter.extend(rend.class.const_get(:Helpers))
|
421
|
-
end
|
422
|
-
if args[1].kind_of?(Hash)
|
423
|
-
d = args[1].delete(:data)
|
424
|
-
rend.data = d if d
|
425
|
-
args[1].each {|k,v| rend.options.send("#{k}=",v) }
|
426
|
-
end
|
427
|
-
|
428
|
-
yield(rend) if block_given?
|
429
|
-
return rend
|
430
|
-
end
|
431
|
-
|
432
|
-
private
|
433
|
-
|
434
|
-
# Allows you to register a format with the renderer.
|
435
|
-
#
|
436
|
-
# example:
|
437
|
-
#
|
438
|
-
# class MyFormatter < Ruport::Formatter
|
439
|
-
# # formatter code ...
|
440
|
-
# SomeRenderer.add_format self, :my_formatter
|
441
|
-
# end
|
442
|
-
#
|
443
|
-
def add_format(format,name=nil)
|
444
|
-
formats[name] = format
|
445
|
-
end
|
446
|
-
|
447
|
-
end
|
448
|
-
|
449
|
-
# The name of format being used
|
450
|
-
attr_accessor :format
|
451
|
-
|
452
|
-
# The formatter object being used
|
453
|
-
attr_writer :formatter
|
454
|
-
|
455
|
-
# The +data+ that has been passed to the active formatter.
|
456
|
-
def data
|
457
|
-
formatter.data
|
458
|
-
end
|
459
|
-
|
460
|
-
# Sets +data+ attribute on the active formatter.
|
461
|
-
def data=(val)
|
462
|
-
formatter.data = val.dup
|
463
|
-
end
|
464
|
-
|
465
|
-
# Renderer::Options object which is shared with the current formatter.
|
466
|
-
def options
|
467
|
-
yield(formatter.options) if block_given?
|
468
|
-
formatter.options
|
469
|
-
end
|
470
|
-
|
471
|
-
# If an IO object is given, Formatter#output will use it instead of
|
472
|
-
# the default String. For Ruport's core renderers, we technically
|
473
|
-
# can use any object that supports the << method, but it's meant
|
474
|
-
# for IO objects such as File or STDOUT
|
475
|
-
#
|
476
|
-
def io=(obj)
|
477
|
-
options.io=obj
|
478
|
-
end
|
479
|
-
|
480
|
-
# When no block is given, returns active formatter.
|
481
|
-
#
|
482
|
-
# When a block is given with a block variable, sets the block variable to the
|
483
|
-
# formatter.
|
484
|
-
#
|
485
|
-
# When a block is given without block variables, instance_evals the block
|
486
|
-
# within the context of the formatter.
|
487
|
-
#
|
488
|
-
def formatter(&block)
|
489
|
-
if block.nil?
|
490
|
-
return @formatter
|
491
|
-
elsif block.arity > 0
|
492
|
-
yield(@formatter)
|
493
|
-
else
|
494
|
-
@formatter.instance_eval(&block)
|
495
|
-
end
|
496
|
-
return @formatter
|
497
|
-
end
|
498
|
-
|
499
|
-
# Provides a shortcut to render() to allow
|
500
|
-
# render(:csv) to become render_csv
|
501
|
-
#
|
502
|
-
def self.method_missing(id,*args,&block)
|
503
|
-
id.to_s =~ /^render_(.*)/
|
504
|
-
unless args[0].kind_of? Hash
|
505
|
-
args = [ (args[1] || {}).merge(:data => args[0]) ]
|
506
|
-
end
|
507
|
-
$1 ? render($1.to_sym,*args,&block) : super
|
508
|
-
end
|
509
|
-
|
510
|
-
private
|
511
|
-
|
512
|
-
def prepare(name)
|
513
|
-
maybe "prepare_#{name}"
|
514
|
-
end
|
515
|
-
|
516
|
-
def build(names,prefix=nil)
|
517
|
-
return maybe("build_#{names}") if prefix.nil?
|
518
|
-
names.each { |n| maybe "build_#{prefix}_#{n}" }
|
519
|
-
end
|
520
|
-
|
521
|
-
def finalize(name)
|
522
|
-
maybe "finalize_#{name}"
|
523
|
-
end
|
524
|
-
|
525
|
-
def maybe(something)
|
526
|
-
formatter.send something if formatter.respond_to? something
|
527
|
-
end
|
528
|
-
|
529
|
-
def options=(o)
|
530
|
-
formatter.options = o
|
531
|
-
end
|
532
|
-
|
533
|
-
# selects a formatter for use by format name
|
534
|
-
def use_formatter(format)
|
535
|
-
self.formatter = self.class.formats[format].new
|
536
|
-
self.formatter.format = format
|
537
|
-
end
|
538
|
-
|
539
|
-
end
|
540
|
-
|
541
|
-
require "ruport/renderer/table"
|
542
|
-
require "ruport/renderer/grouping"
|