ruport 1.2.3 → 1.4.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/Rakefile +2 -4
- data/examples/centered_pdf_text_box.rb +2 -6
- data/examples/pdf_report_with_common_base.rb +2 -5
- data/examples/png_embed.rb +3 -8
- data/examples/simple_templating_example.rb +7 -7
- data/examples/tattle_rubygems_version.rb +0 -3
- data/lib/ruport/data/grouping.rb +11 -10
- data/lib/ruport/data/record.rb +3 -1
- data/lib/ruport/data/table.rb +0 -14
- data/lib/ruport/formatter/csv.rb +10 -15
- data/lib/ruport/formatter/html.rb +4 -6
- data/lib/ruport/formatter/pdf.rb +50 -91
- data/lib/ruport/formatter/template.rb +33 -15
- data/lib/ruport/formatter/text.rb +22 -26
- data/lib/ruport/formatter.rb +27 -11
- data/lib/ruport/renderer/grouping.rb +0 -6
- data/lib/ruport/renderer/table.rb +0 -4
- data/lib/ruport/renderer.rb +64 -78
- data/lib/ruport.rb +7 -4
- data/test/csv_formatter_test.rb +8 -8
- data/test/grouping_test.rb +10 -10
- data/test/helpers.rb +2 -0
- data/test/html_formatter_test.rb +5 -5
- data/test/pdf_formatter_test.rb +23 -14
- data/test/record_test.rb +5 -0
- data/test/renderer_test.rb +103 -47
- data/test/table_test.rb +111 -138
- data/test/template_test.rb +12 -1
- data/test/text_formatter_test.rb +12 -14
- metadata +69 -88
- data/lib/ruport/acts_as_reportable.rb +0 -378
- data/lib/ruport/query/sql_split.rb +0 -33
- data/lib/ruport/query.rb +0 -232
- data/test/acts_as_reportable_test.rb +0 -272
- data/test/query_test.rb +0 -259
- data/test/sql_split_test.rb +0 -20
@@ -46,26 +46,39 @@ class Ruport::Formatter::TemplateNotDefined < StandardError; end
|
|
46
46
|
#
|
47
47
|
# Example:
|
48
48
|
#
|
49
|
-
# Ruport::Formatter::Template.create(:simple) do |
|
50
|
-
#
|
49
|
+
# Ruport::Formatter::Template.create(:simple) do |format|
|
50
|
+
# format.page = {
|
51
51
|
# :size => "LETTER",
|
52
52
|
# :layout => :landscape
|
53
53
|
# }
|
54
54
|
# end
|
55
55
|
#
|
56
|
+
# If you define a template with the name :default, then it will be used by
|
57
|
+
# all formatters unless they either specify a template or explicitly turn off
|
58
|
+
# the templating functionality by using :template => false.
|
59
|
+
#
|
60
|
+
# Example:
|
61
|
+
#
|
62
|
+
# Ruport::Formatter::Template.create(:simple)
|
63
|
+
# Ruport::Formatter::Template.create(:default)
|
64
|
+
#
|
65
|
+
# puts g.to_pdf #=> uses the :default template
|
66
|
+
# puts g.to_pdf(:template => :simple) #=> uses the :simple template
|
67
|
+
# puts g.to_pdf(:template => false) #=> doesn't use a template
|
68
|
+
#
|
56
69
|
# ==== PDF Formatter Options
|
57
70
|
#
|
58
71
|
# Option Key Value
|
59
72
|
#
|
60
|
-
#
|
73
|
+
# page :size Any size supported by the :paper
|
61
74
|
# option to PDF::Writer.new
|
62
75
|
#
|
63
76
|
# :layout :portrait, :landscape
|
64
77
|
#
|
65
|
-
#
|
78
|
+
# text Any available to Corresponding values
|
66
79
|
# PDF::Writer#text
|
67
80
|
#
|
68
|
-
#
|
81
|
+
# table All attributes of Corresponding values
|
69
82
|
# PDF::SimpleTable
|
70
83
|
#
|
71
84
|
# :column_options - All attributes of
|
@@ -78,41 +91,41 @@ class Ruport::Formatter::TemplateNotDefined < StandardError; end
|
|
78
91
|
# - :heading => { All attributes of
|
79
92
|
# PDF::SimpleTable::Column::Heading }
|
80
93
|
#
|
81
|
-
#
|
94
|
+
# column :alignment :left, :right, :center, :full
|
82
95
|
#
|
83
96
|
# :width column width
|
84
97
|
#
|
85
|
-
#
|
98
|
+
# heading :alignment :left, :right, :center, :full
|
86
99
|
#
|
87
100
|
# :bold true or false
|
88
101
|
#
|
89
102
|
# :title heading title (if not set,
|
90
103
|
# defaults to column name)
|
91
104
|
#
|
92
|
-
#
|
105
|
+
# grouping :style :inline, :justified, :separated, :offset
|
93
106
|
#
|
94
107
|
#
|
95
108
|
# ==== Text Formatter Options
|
96
109
|
#
|
97
110
|
# Option Key Value
|
98
111
|
#
|
99
|
-
#
|
112
|
+
# table :show_headings true or false
|
100
113
|
# :width Table width
|
101
114
|
# :ignore_width true or false
|
102
115
|
#
|
103
|
-
#
|
116
|
+
# column :alignment :center
|
104
117
|
# :maximum_width Max column width
|
105
118
|
#
|
106
|
-
#
|
119
|
+
# grouping :show_headings true or false
|
107
120
|
#
|
108
121
|
#
|
109
122
|
# ==== HTML Formatter Options
|
110
123
|
#
|
111
124
|
# Option Key Value
|
112
125
|
#
|
113
|
-
#
|
126
|
+
# table :show_headings true or false
|
114
127
|
#
|
115
|
-
#
|
128
|
+
# grouping :style :inline, :justified
|
116
129
|
# :show_headings true or false
|
117
130
|
#
|
118
131
|
#
|
@@ -120,9 +133,9 @@ class Ruport::Formatter::TemplateNotDefined < StandardError; end
|
|
120
133
|
#
|
121
134
|
# Option Key Value
|
122
135
|
#
|
123
|
-
#
|
136
|
+
# table :show_headings true or false
|
124
137
|
#
|
125
|
-
#
|
138
|
+
# grouping :style :inline, :justified, :raw
|
126
139
|
# :show_headings true or false
|
127
140
|
#
|
128
141
|
# format_options All options Corresponding values
|
@@ -166,4 +179,9 @@ class Ruport::Formatter::Template < Ruport::Renderer::Options
|
|
166
179
|
def self.[](label)
|
167
180
|
templates[label] or raise Ruport::Formatter::TemplateNotDefined
|
168
181
|
end
|
182
|
+
|
183
|
+
# Returns the default template.
|
184
|
+
def self.default
|
185
|
+
templates[:default]
|
186
|
+
end
|
169
187
|
end
|
@@ -45,19 +45,15 @@ module Ruport
|
|
45
45
|
# truncating it. Useful for file output.
|
46
46
|
class Formatter::Text < Formatter
|
47
47
|
|
48
|
-
renders :text, :for => [ Renderer::Row, Renderer::Table,
|
49
|
-
|
48
|
+
renders [:txt, :text], :for => [ Renderer::Row, Renderer::Table,
|
49
|
+
Renderer::Group, Renderer::Grouping ]
|
50
50
|
|
51
|
-
opt_reader :max_col_width, :alignment, :table_width,
|
52
|
-
:show_table_headers, :show_group_headers,
|
53
|
-
:ignore_table_width
|
54
|
-
|
55
51
|
# Hook for setting available options using a template. See the template
|
56
52
|
# documentation for the available options and their format.
|
57
53
|
def apply_template
|
58
|
-
apply_table_format_template(template.
|
59
|
-
apply_column_format_template(template.
|
60
|
-
apply_grouping_format_template(template.
|
54
|
+
apply_table_format_template(template.table)
|
55
|
+
apply_column_format_template(template.column)
|
56
|
+
apply_grouping_format_template(template.grouping)
|
61
57
|
end
|
62
58
|
|
63
59
|
# Checks to ensure the table is not empty and then calls
|
@@ -78,7 +74,7 @@ module Ruport
|
|
78
74
|
return unless should_render_column_names?
|
79
75
|
|
80
76
|
c = data.column_names.enum_for(:each_with_index).map { |f,i|
|
81
|
-
f.to_s.center(max_col_width[i])
|
77
|
+
f.to_s.center(options.max_col_width[i])
|
82
78
|
}
|
83
79
|
|
84
80
|
output << fit_to_width("#{hr}| #{c.join(' | ')} |\n")
|
@@ -96,14 +92,14 @@ module Ruport
|
|
96
92
|
output << fit_to_width(hr)
|
97
93
|
return if data.empty?
|
98
94
|
|
99
|
-
calculate_max_col_widths unless max_col_width
|
95
|
+
calculate_max_col_widths unless options.max_col_width
|
100
96
|
|
101
97
|
render_data_by_row do |rend|
|
102
98
|
rend.options do |o|
|
103
|
-
o.max_col_width = max_col_width
|
104
|
-
o.alignment = alignment
|
105
|
-
o.table_width = table_width
|
106
|
-
o.ignore_table_width = ignore_table_width
|
99
|
+
o.max_col_width = options.max_col_width
|
100
|
+
o.alignment = options.alignment
|
101
|
+
o.table_width = options.table_width
|
102
|
+
o.ignore_table_width = options.ignore_table_width
|
107
103
|
end
|
108
104
|
end
|
109
105
|
|
@@ -119,15 +115,15 @@ module Ruport
|
|
119
115
|
# Uses fit_to_width to truncate the row if necessary.
|
120
116
|
#
|
121
117
|
def build_row
|
122
|
-
max_col_widths_for_row(data) unless max_col_width
|
118
|
+
max_col_widths_for_row(data) unless options.max_col_width
|
123
119
|
|
124
120
|
data.enum_for(:each_with_index).inject(line=[]) { |s,e|
|
125
121
|
field,index = e
|
126
|
-
if alignment.eql? :center
|
127
|
-
line << field.to_s.center(max_col_width[index])
|
122
|
+
if options.alignment.eql? :center
|
123
|
+
line << field.to_s.center(options.max_col_width[index])
|
128
124
|
else
|
129
125
|
align = field.is_a?(Numeric) ? :rjust : :ljust
|
130
|
-
line << field.to_s.send(align, max_col_width[index])
|
126
|
+
line << field.to_s.send(align, options.max_col_width[index])
|
131
127
|
end
|
132
128
|
}
|
133
129
|
output << fit_to_width("| #{line.join(' | ')} |\n")
|
@@ -157,7 +153,7 @@ module Ruport
|
|
157
153
|
# is false/nil. Returns true otherwise.
|
158
154
|
#
|
159
155
|
def should_render_column_names?
|
160
|
-
not data.column_names.empty? || !show_table_headers
|
156
|
+
not data.column_names.empty? || !options.show_table_headers
|
161
157
|
end
|
162
158
|
|
163
159
|
# Generates the horizontal rule by calculating the total table width and
|
@@ -166,7 +162,7 @@ module Ruport
|
|
166
162
|
# "+------------------+"
|
167
163
|
def hr
|
168
164
|
ref = data.column_names.empty? ? data[0].to_a : data.column_names
|
169
|
-
len = max_col_width.inject(ref.length * 3) {|s,e|s+e}
|
165
|
+
len = options.max_col_width.inject(ref.length * 3) {|s,e|s+e}
|
170
166
|
"+" + "-"*(len-1) + "+\n"
|
171
167
|
end
|
172
168
|
|
@@ -174,7 +170,7 @@ module Ruport
|
|
174
170
|
#
|
175
171
|
# Otherwise, uses SystemExtensions to determine terminal width.
|
176
172
|
def width
|
177
|
-
table_width || SystemExtensions.terminal_width
|
173
|
+
options.table_width || SystemExtensions.terminal_width
|
178
174
|
end
|
179
175
|
|
180
176
|
# Truncates a string so that it does not exceed Text#width
|
@@ -191,13 +187,13 @@ module Ruport
|
|
191
187
|
# Determines the text widths for each column.
|
192
188
|
def calculate_max_col_widths
|
193
189
|
# allow override
|
194
|
-
return if max_col_width
|
190
|
+
return if options.max_col_width
|
195
191
|
|
196
192
|
options.max_col_width = []
|
197
193
|
|
198
194
|
unless data.column_names.empty?
|
199
195
|
data.column_names.each_index do |i|
|
200
|
-
max_col_width[i] = data.column_names[i].to_s.length
|
196
|
+
options.max_col_width[i] = data.column_names[i].to_s.length
|
201
197
|
end
|
202
198
|
end
|
203
199
|
|
@@ -209,8 +205,8 @@ module Ruport
|
|
209
205
|
def max_col_widths_for_row(row)
|
210
206
|
options.max_col_width ||= []
|
211
207
|
row.each_with_index do |f,i|
|
212
|
-
if !max_col_width[i] || f.to_s.length > max_col_width[i]
|
213
|
-
max_col_width[i] = f.to_s.length
|
208
|
+
if !options.max_col_width[i] || f.to_s.length > options.max_col_width[i]
|
209
|
+
options.max_col_width[i] = f.to_s.length
|
214
210
|
end
|
215
211
|
end
|
216
212
|
end
|
data/lib/ruport/formatter.rb
CHANGED
@@ -26,7 +26,6 @@ module Ruport
|
|
26
26
|
#
|
27
27
|
# class ReverseRenderer < Ruport::Renderer
|
28
28
|
# stage :reversed_header, :reversed_body
|
29
|
-
# option :header_text
|
30
29
|
# end
|
31
30
|
#
|
32
31
|
# class ReversedText < Ruport::Formatter
|
@@ -159,16 +158,26 @@ module Ruport
|
|
159
158
|
formats << format unless formats.include?(format)
|
160
159
|
end
|
161
160
|
end
|
162
|
-
end
|
161
|
+
end
|
163
162
|
|
164
|
-
# Allows
|
163
|
+
# Allows you to implement stages in your formatter using the
|
164
|
+
# following syntax:
|
165
|
+
#
|
166
|
+
# class ReversedText < Ruport::Formatter
|
167
|
+
# renders :txt, :for => ReverseRenderer
|
168
|
+
#
|
169
|
+
# build :reversed_header do
|
170
|
+
# output << "#{options.header_text}\n"
|
171
|
+
# output << "The reversed text will follow\n"
|
172
|
+
# end
|
165
173
|
#
|
166
|
-
#
|
167
|
-
#
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
174
|
+
# build :reversed_body do
|
175
|
+
# output << data.reverse << "\n"
|
176
|
+
# end
|
177
|
+
# end
|
178
|
+
#
|
179
|
+
def self.build(stage,&block)
|
180
|
+
define_method "build_#{stage}", &block
|
172
181
|
end
|
173
182
|
|
174
183
|
# Gives a list of formats registered for this formatter.
|
@@ -178,7 +187,7 @@ module Ruport
|
|
178
187
|
|
179
188
|
# Returns the template currently set for this formatter.
|
180
189
|
def template
|
181
|
-
Template[options.template]
|
190
|
+
Template[options.template] rescue nil || Template[:default]
|
182
191
|
end
|
183
192
|
|
184
193
|
# Stores a string used for outputting formatted data.
|
@@ -202,13 +211,20 @@ module Ruport
|
|
202
211
|
File.open(filename,"w") {|f| f << output }
|
203
212
|
end
|
204
213
|
|
214
|
+
# Use to define that your formatter should save in binary format
|
215
|
+
def self.save_as_binary_file
|
216
|
+
define_method :save_output do |filename|
|
217
|
+
File.open(filename,"wb") {|f| f << output }
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
205
221
|
# Evaluates the string using ERB and returns the results.
|
206
222
|
#
|
207
223
|
# If <tt>:binding</tt> is specified, it will evaluate the template
|
208
224
|
# in that context.
|
209
225
|
def erb(string,options={})
|
210
226
|
require "erb"
|
211
|
-
if string =~
|
227
|
+
if string =~ /(\.r\w+)|(\.erb)$/
|
212
228
|
ERB.new(File.read(string)).result(options[:binding]||binding)
|
213
229
|
else
|
214
230
|
ERB.new(string).result(options[:binding]||binding)
|
@@ -30,9 +30,6 @@ module Ruport
|
|
30
30
|
# * build_group_footer
|
31
31
|
#
|
32
32
|
class Renderer::Group < Renderer
|
33
|
-
|
34
|
-
option :show_table_headers
|
35
|
-
|
36
33
|
options { |o| o.show_table_headers = true }
|
37
34
|
|
38
35
|
stage :group_header, :group_body, :group_footer
|
@@ -61,9 +58,6 @@ module Ruport
|
|
61
58
|
# * finalize_grouping
|
62
59
|
#
|
63
60
|
class Renderer::Grouping < Renderer
|
64
|
-
|
65
|
-
option :show_group_headers, :style
|
66
|
-
|
67
61
|
options do |o|
|
68
62
|
o.show_group_headers = true
|
69
63
|
o.style = :inline
|
@@ -18,7 +18,6 @@ module Ruport
|
|
18
18
|
# * build_row
|
19
19
|
#
|
20
20
|
class Renderer::Row < Renderer
|
21
|
-
option :format_options
|
22
21
|
stage :row
|
23
22
|
end
|
24
23
|
|
@@ -44,9 +43,6 @@ module Ruport
|
|
44
43
|
# * finalize_table
|
45
44
|
#
|
46
45
|
class Renderer::Table < Renderer
|
47
|
-
|
48
|
-
option :show_table_headers, :format_options
|
49
|
-
|
50
46
|
options { |o| o.show_table_headers = true }
|
51
47
|
|
52
48
|
prepare :table
|
data/lib/ruport/renderer.rb
CHANGED
@@ -25,7 +25,10 @@ class Ruport::Renderer
|
|
25
25
|
|
26
26
|
# Structure for holding renderer options.
|
27
27
|
# Simplified version of HashWithIndifferentAccess
|
28
|
-
class Options < OpenStruct
|
28
|
+
class Options < OpenStruct
|
29
|
+
|
30
|
+
private :id
|
31
|
+
|
29
32
|
# Returns a Hash object. Use this if you need methods other than []
|
30
33
|
def to_hash
|
31
34
|
@table
|
@@ -172,49 +175,16 @@ class Ruport::Renderer
|
|
172
175
|
respond_to?(:renderable_data) ? renderable_data(format) : self
|
173
176
|
yield(rend) if block_given?
|
174
177
|
end
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
|
179
|
-
module AutoRunner #:nodoc:
|
180
|
-
# Called automatically when the report is rendered. Uses the
|
181
|
-
# data collected from the earlier methods.
|
182
|
-
def _run_
|
183
|
-
|
184
|
-
# ensure all the required options have been set
|
185
|
-
unless self.class.required_options.nil?
|
186
|
-
self.class.required_options.each do |opt|
|
187
|
-
if options.__send__(opt).nil?
|
188
|
-
raise RequiredOptionNotSet, "Required option #{opt} not set"
|
189
|
-
end
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
if formatter.respond_to?(:apply_template) && options.template
|
194
|
-
formatter.apply_template
|
195
|
-
end
|
196
|
-
|
197
|
-
prepare self.class.first_stage if self.class.first_stage
|
198
|
-
|
199
|
-
if formatter.respond_to?(:layout) && options.layout != false
|
200
|
-
formatter.layout do execute_stages end
|
201
|
-
else
|
202
|
-
execute_stages
|
203
|
-
end
|
204
|
-
|
205
|
-
finalize self.class.final_stage if self.class.final_stage
|
206
|
-
end
|
178
|
+
end
|
207
179
|
|
208
|
-
def
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
maybe("build_#{stage}")
|
213
|
-
end
|
214
|
-
end
|
180
|
+
def save_as(file,options={})
|
181
|
+
file =~ /.*\.(.*)/
|
182
|
+
format = $1
|
183
|
+
as(format.to_sym, options.merge(:file => file))
|
215
184
|
end
|
216
185
|
end
|
217
186
|
|
187
|
+
|
218
188
|
class << self
|
219
189
|
|
220
190
|
attr_accessor :first_stage,:final_stage,:required_options,:stages #:nodoc:
|
@@ -311,28 +281,6 @@ class Ruport::Renderer
|
|
311
281
|
}
|
312
282
|
end
|
313
283
|
|
314
|
-
# Defines attribute writers for the Renderer::Options object shared
|
315
|
-
# between Renderer and Formatter.
|
316
|
-
#
|
317
|
-
# usage:
|
318
|
-
#
|
319
|
-
# class MyRenderer < Ruport::Renderer
|
320
|
-
# option :font_size, :font_style
|
321
|
-
# # other details omitted
|
322
|
-
# end
|
323
|
-
def option(*opts)
|
324
|
-
opts.each do |opt|
|
325
|
-
o = opt
|
326
|
-
unless instance_methods(false).include?(o.to_s)
|
327
|
-
define_method(o) {
|
328
|
-
options.send(o.to_s)
|
329
|
-
}
|
330
|
-
end
|
331
|
-
opt = "#{opt}="
|
332
|
-
define_method(opt) {|t| options.send(opt, t) }
|
333
|
-
end
|
334
|
-
end
|
335
|
-
|
336
284
|
# Defines attribute writers for the Renderer::Options object shared
|
337
285
|
# between Renderer and Formatter. Will throw an error if the user does
|
338
286
|
# not provide values for these options upon rendering.
|
@@ -347,10 +295,15 @@ class Ruport::Renderer
|
|
347
295
|
self.required_options ||= []
|
348
296
|
opts.each do |opt|
|
349
297
|
self.required_options << opt
|
350
|
-
|
298
|
+
|
299
|
+
o = opt
|
300
|
+
unless instance_methods(false).include?(o.to_s)
|
301
|
+
define_method(o) { options.send(o.to_s) }
|
302
|
+
end
|
303
|
+
opt = "#{opt}="
|
304
|
+
define_method(opt) {|t| options.send(opt, t) }
|
351
305
|
end
|
352
306
|
end
|
353
|
-
|
354
307
|
|
355
308
|
# Lists the formatters that are currently registered on a renderer,
|
356
309
|
# as a hash keyed by format name.
|
@@ -372,15 +325,10 @@ class Ruport::Renderer
|
|
372
325
|
# * If the renderer contains a module Helpers, mix it in to the instance.
|
373
326
|
# * If a block is given, yield the Renderer instance.
|
374
327
|
# * If a setup() method is defined on the Renderer, call it.
|
375
|
-
# *
|
376
|
-
# include Renderer::AutoRunner (you usually won't need a run() method).
|
377
|
-
# * Call _run_ if it exists (this is provided by default, by AutoRunner).
|
328
|
+
# * Call the run() method.
|
378
329
|
# * If the :file option is set to a file name, appends output to the file.
|
379
330
|
# * Return the results of formatter.output
|
380
331
|
#
|
381
|
-
# Note that the only time you will need a run() method is if you can't
|
382
|
-
# do what you need to via a helpers module or via setup()
|
383
|
-
#
|
384
332
|
# Please see the examples/ directory for custom renderer examples, because
|
385
333
|
# this is not nearly as complicated as it sounds in most cases.
|
386
334
|
def render(*args)
|
@@ -388,12 +336,7 @@ class Ruport::Renderer
|
|
388
336
|
yield(r) if block_given?
|
389
337
|
r.setup if r.respond_to? :setup
|
390
338
|
}
|
391
|
-
|
392
|
-
rend.run
|
393
|
-
else
|
394
|
-
include AutoRunner
|
395
|
-
end
|
396
|
-
rend._run_ if rend.respond_to? :_run_
|
339
|
+
rend.run
|
397
340
|
rend.formatter.save_output(rend.options.file) if rend.options.file
|
398
341
|
return rend.formatter.output
|
399
342
|
end
|
@@ -411,6 +354,8 @@ class Ruport::Renderer
|
|
411
354
|
return @options
|
412
355
|
end
|
413
356
|
|
357
|
+
private
|
358
|
+
|
414
359
|
# Creates a new instance of the renderer and sets it to use the specified
|
415
360
|
# formatter (by name). If a block is given, the renderer instance is
|
416
361
|
# yielded.
|
@@ -435,8 +380,6 @@ class Ruport::Renderer
|
|
435
380
|
return rend
|
436
381
|
end
|
437
382
|
|
438
|
-
private
|
439
|
-
|
440
383
|
# Allows you to register a format with the renderer.
|
441
384
|
#
|
442
385
|
# Example:
|
@@ -474,6 +417,12 @@ class Ruport::Renderer
|
|
474
417
|
formatter.options
|
475
418
|
end
|
476
419
|
|
420
|
+
# Call the _run_ method. You can override this method in your custom
|
421
|
+
# renderer if you need to define other actions.
|
422
|
+
def run
|
423
|
+
_run_
|
424
|
+
end
|
425
|
+
|
477
426
|
# If an IO object is given, Formatter#output will use it instead of
|
478
427
|
# the default String. For Ruport's core renderers, we technically
|
479
428
|
# can use any object that supports the << method, but it's meant
|
@@ -504,6 +453,43 @@ class Ruport::Renderer
|
|
504
453
|
|
505
454
|
private
|
506
455
|
|
456
|
+
# Called automatically when the report is rendered. Uses the
|
457
|
+
# data collected from the earlier methods.
|
458
|
+
def _run_
|
459
|
+
# ensure all the required options have been set
|
460
|
+
unless self.class.required_options.nil?
|
461
|
+
self.class.required_options.each do |opt|
|
462
|
+
if options.__send__(opt).nil?
|
463
|
+
raise RequiredOptionNotSet, "Required option #{opt} not set"
|
464
|
+
end
|
465
|
+
end
|
466
|
+
end
|
467
|
+
|
468
|
+
if formatter.respond_to?(:apply_template) && options.template != false
|
469
|
+
formatter.apply_template if options.template ||
|
470
|
+
Ruport::Formatter::Template.default
|
471
|
+
end
|
472
|
+
|
473
|
+
prepare self.class.first_stage if self.class.first_stage
|
474
|
+
|
475
|
+
if formatter.respond_to?(:layout) && options.layout != false
|
476
|
+
formatter.layout do execute_stages end
|
477
|
+
else
|
478
|
+
execute_stages
|
479
|
+
end
|
480
|
+
|
481
|
+
finalize self.class.final_stage if self.class.final_stage
|
482
|
+
end
|
483
|
+
|
484
|
+
def execute_stages
|
485
|
+
# call each stage to build the report
|
486
|
+
unless self.class.stages.nil?
|
487
|
+
self.class.stages.each do |stage|
|
488
|
+
maybe("build_#{stage}")
|
489
|
+
end
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
507
493
|
def prepare(name)
|
508
494
|
maybe "prepare_#{name}"
|
509
495
|
end
|
data/lib/ruport.rb
CHANGED
@@ -12,7 +12,7 @@
|
|
12
12
|
|
13
13
|
module Ruport #:nodoc:#
|
14
14
|
|
15
|
-
VERSION = "1.
|
15
|
+
VERSION = "1.4.0"
|
16
16
|
|
17
17
|
class FormatterError < RuntimeError #:nodoc:
|
18
18
|
end
|
@@ -105,8 +105,11 @@ require "enumerator"
|
|
105
105
|
require "ruport/renderer"
|
106
106
|
require "ruport/data"
|
107
107
|
require "ruport/formatter"
|
108
|
-
require "ruport/query"
|
109
108
|
|
110
|
-
|
111
|
-
|
109
|
+
begin
|
110
|
+
if Object.const_defined? :ActiveRecord
|
111
|
+
require "ruport/acts_as_reportable"
|
112
|
+
end
|
113
|
+
rescue LoadError
|
114
|
+
nil
|
112
115
|
end
|
data/test/csv_formatter_test.rb
CHANGED
@@ -11,32 +11,32 @@ end
|
|
11
11
|
class TestRenderCSVTable < Test::Unit::TestCase
|
12
12
|
|
13
13
|
def setup
|
14
|
-
Ruport::Formatter::Template.create(:simple) do |
|
15
|
-
|
14
|
+
Ruport::Formatter::Template.create(:simple) do |format|
|
15
|
+
format.table = {
|
16
16
|
:show_headings => false
|
17
17
|
}
|
18
|
-
|
18
|
+
format.grouping = {
|
19
19
|
:style => :justified,
|
20
20
|
:show_headings => false
|
21
21
|
}
|
22
|
-
|
22
|
+
format.format_options = { :col_sep => ":" }
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
26
|
def test_render_csv_table
|
27
27
|
actual = Ruport::Renderer::Table.render_csv do |r|
|
28
|
-
r.data = [[1,2,3],[4,5,6]]
|
28
|
+
r.data = Table([], :data => [[1,2,3],[4,5,6]])
|
29
29
|
end
|
30
30
|
assert_equal("1,2,3\n4,5,6\n",actual)
|
31
31
|
|
32
32
|
actual = Ruport::Renderer::Table.render_csv do |r|
|
33
|
-
r.data = [[1,2,3],[4,5,6]]
|
33
|
+
r.data = Table(%w[a b c], :data => [[1,2,3],[4,5,6]])
|
34
34
|
end
|
35
35
|
assert_equal("a,b,c\n1,2,3\n4,5,6\n",actual)
|
36
36
|
end
|
37
37
|
|
38
38
|
def test_format_options
|
39
|
-
a = [[1,2,3],[4,5,6]]
|
39
|
+
a = Table(%w[a b c], :data => [[1,2,3],[4,5,6]])
|
40
40
|
assert_equal "a\tb\tc\n1\t2\t3\n4\t5\t6\n",
|
41
41
|
a.as(:csv,:format_options => { :col_sep => "\t" })
|
42
42
|
end
|
@@ -44,7 +44,7 @@ class TestRenderCSVTable < Test::Unit::TestCase
|
|
44
44
|
def test_table_headers
|
45
45
|
actual = Ruport::Renderer::Table.
|
46
46
|
render_csv(:show_table_headers => false,
|
47
|
-
:data => [[1,2,3],[4,5,6]]
|
47
|
+
:data => Table(%w[a b c], :data => [[1,2,3],[4,5,6]]))
|
48
48
|
assert_equal("1,2,3\n4,5,6\n",actual)
|
49
49
|
end
|
50
50
|
|