ruport 0.5.0 → 0.5.1

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/CHANGELOG CHANGED
@@ -1,4 +1,10 @@
1
- Tnghe current version of Ruby Reports is 0.5.0
1
+ Tnghe current version of Ruby Reports is 0.5.1
2
+
3
+ changes since 0.5.0
4
+
5
+ - Broke plugins and engines out into their own files
6
+
7
+ - Fixed a bug which prevented TextPlugin from working right in Windows
2
8
 
3
9
  changes since 0.4.99
4
10
 
data/Rakefile CHANGED
@@ -23,7 +23,7 @@ end
23
23
 
24
24
  spec = Gem::Specification.new do |spec|
25
25
  spec.name = LEAN ? "lean-ruport" : "ruport"
26
- spec.version = "0.5.0"
26
+ spec.version = "0.5.1"
27
27
  spec.platform = Gem::Platform::RUBY
28
28
  spec.summary = "A generalized Ruby report generation and templating engine."
29
29
  spec.files = Dir.glob("{examples,lib,test,bin}/**/**/*") +
@@ -12,7 +12,7 @@
12
12
 
13
13
  module Ruport
14
14
 
15
- VERSION = "0.5.0"
15
+ VERSION = "0.5.1"
16
16
 
17
17
  # Ruports logging and error interface.
18
18
  # Can generate warnings or raise fatal errors
@@ -101,114 +101,7 @@ module Ruport
101
101
  end
102
102
 
103
103
  private_class_method :new
104
+ engines = %w[graph invoice table document]
105
+ engines.each { |e| require "lib/ruport/format/engine/#{e}" }
104
106
  end
105
-
106
- class Format::Engine::Graph < Ruport::Format::Engine
107
-
108
- attributes [:width, :height, :style, :title]
109
-
110
- renderer do
111
- super
112
- active_plugin.render_graph
113
- end
114
-
115
- alias_engine Graph, :graph_engine
116
- Ruport::Format.build_interface_for Graph, :graph
117
-
118
- end
119
-
120
- class Format::Engine::Invoice < Ruport::Format::Engine
121
-
122
- # order meta data
123
- attributes [ :customer_info, :company_info,
124
- :comments, :order_info, :title]
125
-
126
- renderer do
127
- super
128
- build_headers
129
- build_body
130
- build_footer
131
- active_plugin.render_invoice
132
- end
133
-
134
- alias_engine Invoice, :invoice_engine
135
- Ruport::Format.build_interface_for Invoice, :invoice
136
-
137
- end
138
-
139
- class Format::Engine::Table < Format::Engine
140
-
141
- renderer do
142
- super
143
- active_plugin.rendered_field_names = ""
144
- build_field_names if (data.respond_to?(:column_names) &&
145
- data.column_names && show_field_names)
146
- a = active_plugin.render_table
147
- end
148
-
149
- class << self
150
-
151
- def rewrite_column(key,&block)
152
- data.each { |r| r[key] = block[r] }
153
- end
154
-
155
- def num_cols
156
- data[0].to_a.length
157
- end
158
-
159
- def prune(limit=data[0].length)
160
- limit.times do |field|
161
- last = ""
162
- data.each_cons(2) { |l,e|
163
- next if field.nonzero? && e[field-1]
164
- last = l[field] if l[field]
165
- e[field] = nil if e[field] == last
166
- }
167
- end
168
- end
169
-
170
- attr_accessor :show_field_names
171
-
172
- private
173
-
174
- def build_field_names
175
- if active_plugin.respond_to?(:build_field_names)
176
- active_plugin.rendered_field_names =
177
- active_plugin.build_field_names
178
- end
179
- end
180
-
181
- end
182
-
183
- alias_engine Table, :table_engine
184
- Format.build_interface_for Table, :table
185
- self.show_field_names = true
186
- end
187
-
188
- class Format::Engine::Document < Format::Engine
189
-
190
- renderer do
191
- super
192
- apply_erb if erb_enabled
193
- apply_red_cloth if red_cloth_enabled
194
- active_plugin.render_document
195
- end
196
-
197
- class << self
198
-
199
- attr_accessor :red_cloth_enabled
200
- attr_accessor :erb_enabled
201
-
202
- def apply_red_cloth
203
- require "redcloth"
204
- active_plugin.data = RedCloth.new(active_plugin.data).to_html
205
- end
206
-
207
- end
208
-
209
- alias_engine Document, :document_engine
210
- Format.build_interface_for Document, :document
211
- end
212
-
213
-
214
107
  end
@@ -0,0 +1,28 @@
1
+ module Ruport
2
+ class Format::Engine
3
+ class Document < Format::Engine
4
+ renderer do
5
+ super
6
+ apply_erb if erb_enabled
7
+ apply_red_cloth if red_cloth_enabled
8
+ active_plugin.render_document
9
+ end
10
+
11
+ class << self
12
+
13
+ attr_accessor :red_cloth_enabled
14
+ attr_accessor :erb_enabled
15
+
16
+ def apply_red_cloth
17
+ require "redcloth"
18
+ active_plugin.data = RedCloth.new(active_plugin.data).to_html
19
+ end
20
+
21
+ end
22
+
23
+ alias_engine Document, :document_engine
24
+ Format.build_interface_for Document, :document
25
+ end
26
+ end
27
+ end
28
+
@@ -0,0 +1,18 @@
1
+ module Ruport
2
+ class Format::Engine
3
+ class Graph < Format::Engine
4
+
5
+ attributes [:width, :height, :style, :title]
6
+
7
+ renderer do
8
+ super
9
+ active_plugin.render_graph
10
+ end
11
+
12
+ alias_engine Graph, :graph_engine
13
+ Ruport::Format.build_interface_for Graph, :graph
14
+
15
+ end
16
+ end
17
+ end
18
+
@@ -0,0 +1,23 @@
1
+ module Ruport
2
+ class Format::Engine
3
+ class Format::Engine::Invoice < Ruport::Format::Engine
4
+
5
+ # order meta data
6
+ attributes [ :customer_info, :company_info,
7
+ :comments, :order_info, :title]
8
+
9
+ renderer do
10
+ super
11
+ build_headers
12
+ build_body
13
+ build_footer
14
+ active_plugin.render_invoice
15
+ end
16
+
17
+ alias_engine Invoice, :invoice_engine
18
+ Ruport::Format.build_interface_for Invoice, :invoice
19
+
20
+ end
21
+ end
22
+ end
23
+
@@ -0,0 +1,53 @@
1
+ module Ruport
2
+ class Format::Engine
3
+ class Table < Format::Engine
4
+
5
+ renderer do
6
+ super
7
+ active_plugin.rendered_field_names = ""
8
+ build_field_names if (data.respond_to?(:column_names) &&
9
+ data.column_names && show_field_names)
10
+ a = active_plugin.render_table
11
+ end
12
+
13
+ class << self
14
+
15
+ def rewrite_column(key,&block)
16
+ data.each { |r| r[key] = block[r] }
17
+ end
18
+
19
+ def num_cols
20
+ data[0].to_a.length
21
+ end
22
+
23
+ def prune(limit=data[0].length)
24
+ limit.times do |field|
25
+ last = ""
26
+ data.each_cons(2) { |l,e|
27
+ next if field.nonzero? && e[field-1]
28
+ last = l[field] if l[field]
29
+ e[field] = nil if e[field] == last
30
+ }
31
+ end
32
+ end
33
+
34
+ attr_accessor :show_field_names
35
+
36
+ private
37
+
38
+ def build_field_names
39
+ if active_plugin.respond_to?(:build_field_names)
40
+ active_plugin.rendered_field_names =
41
+ active_plugin.build_field_names
42
+ end
43
+ end
44
+
45
+ end
46
+
47
+ alias_engine Table, :table_engine
48
+ Format.build_interface_for Table, :table
49
+ self.show_field_names = true
50
+ end
51
+ end
52
+ end
53
+
@@ -2,10 +2,13 @@ class InvalidGraphDataError < RuntimeError; end
2
2
  class InvalidGraphOptionError < RuntimeError; end
3
3
 
4
4
  require 'bigdecimal'
5
+ require 'tempfile'
6
+
7
+ class RenderingError < RuntimeError; end
5
8
 
6
9
  module Ruport
7
10
  class Format::Plugin
8
-
11
+
9
12
  class << self
10
13
 
11
14
  attr_accessor :data
@@ -62,292 +65,9 @@ module Ruport
62
65
  attr_accessor :rendered_field_names
63
66
  attr_accessor :pre, :post
64
67
  attr_accessor :header, :footer
65
- end
66
-
67
-
68
- class CSVPlugin < Format::Plugin
69
-
70
- helper(:init_plugin) { |eng| require "fastercsv" }
71
-
72
- format_field_names do
73
- FasterCSV.generate { |csv| csv << data.column_names }
74
- end
75
-
76
- renderer :table do
77
- rendered_field_names +
78
- FasterCSV.generate { |csv| data.each { |r| csv << r } }
79
- end
80
-
81
- plugin_name :csv
82
- register_on :table_engine
83
- end
84
-
85
- class SVGPlugin < Format::Plugin
86
-
87
- helper(:init_plugin) { |eng|
88
- # check the supplied data can be used for graphing
89
- data.each { |r|
90
- if data.column_names.size != r.data.size
91
- raise InvalidGraphDataError, "Column names and data do not match"
92
- end
93
- r.data.each { |c|
94
- begin
95
- c = BigDecimal.new(c) unless c.kind_of?(Float) ||
96
- c.kind_of?(Fixnum) || c.kind_of?(BigDecimal)
97
- rescue
98
- raise InvalidGraphDataError, "Unable to convert #{c.to_s} into a number"
99
- end
100
- }
101
- }
102
-
103
- raise InvalidGraphOptionError, 'You must provide a width before rendering a graph' if eng.width.nil?
104
- raise InvalidGraphOptionError, 'You must provide a height before rendering a graph' if eng.height.nil?
105
- raise InvalidGraphOptionError, 'You must provide a style before rendering a graph' if eng.style.nil?
106
- if eng.style != :area && eng.style != :bar &&
107
- eng.style != :line &&
108
- eng.style != :smiles &&
109
- eng.style != :stacked
110
- raise InvalidGraphOptionError, 'Invalid graph style'
111
- end
112
-
113
- require 'scruffy'
114
- @graph = Scruffy::Graph.new
115
- @graph.title = eng.title unless eng.title.nil?
116
- @graph.theme = Scruffy::Themes::Mephisto.new
117
- @graph.point_markers = @data.column_names
118
- @graph_style = eng.style
119
- @graph_width = eng.width
120
- @graph_height = eng.height
121
- }
122
-
123
- renderer :graph do
124
-
125
- data.each_with_index { |r,i|
126
- @graph.add(@graph_style,
127
- r.tags[0] || 'series ' + (i+1).to_s,
128
- r.data)
129
- }
130
-
131
- # return the rendered graph
132
- @graph.render(:size => [@graph_width, @graph_height])
133
- end
134
-
135
- plugin_name :svg
136
- register_on :graph_engine
137
- end
138
-
139
- class TextPlugin < Format::Plugin
140
- rendering_options :erb_enabled => true, :red_cloth_enabled => false
141
-
142
- renderer :document
143
-
144
- renderer :table do
145
- require "ruport/system_extensions"
146
-
147
- th = "#{rendered_field_names}#{hr}"
148
-
149
- data.each { |r|
150
- r.each_with_index { |f,i|
151
- r[i] = f.to_s.center(max_col_width(i))
152
- }
153
- }
154
-
155
- a = data.inject(th){ |s,r|
156
- s + "| #{r.to_a.join(' | ')} |\n"
157
- } << hr
158
-
159
- width = self.right_margin || SystemExtensions.terminal_width
160
-
161
- a.to_a.each { |r|
162
- r.gsub!(/\A.{#{width+1},}/) { |m| m[0,width-2] + ">>" }
163
- }.join
164
- end
165
-
166
- format_field_names do
167
- data.column_names.each_with_index { |f,i|
168
- data.column_names[i] = f.to_s.center(max_col_width(i))
169
- }
170
- "#{hr}| #{data.column_names.to_a.join(' | ')} |\n"
171
- end
172
-
173
- action :max_col_width do |index|
174
- f = data.column_names if data.respond_to? :column_names
175
- d = Data::Table.new :column_names => f, :data => data
176
-
177
- cw = d.map { |r| r[index].to_s.length }.max
178
-
179
- return cw unless d.column_names
180
-
181
- nw = (index.kind_of?(Integer) ? d.column_names[index] : index ).to_s.length
182
-
183
- [cw,nw].max
184
- end
185
-
186
- action :table_width do
187
- f = data.column_names if data.respond_to? :column_names
188
- d = Data::Table.new:column_names => f, :data => data
189
-
190
- f = d[0].attributes || (0...d[0].length)
191
-
192
- f.inject(0) { |s,e| s + max_col_width(e) }
193
- end
194
-
195
- action :hr do
196
- len = data[0].to_a.length * 3 + table_width + 1
197
- "+" + "-"*(len-2) + "+\n"
198
- end
199
-
200
- attribute :right_margin
201
- plugin_name :text
202
- register_on :table_engine
203
- register_on :document_engine
204
- end
205
-
206
- class PDFPlugin < Format::Plugin
207
- attribute :pdf
208
- attribute :paper
209
-
210
- helper(:init_plugin) {
211
- require "pdf/writer"
212
- require "pdf/simpletable"
213
- self.pdf = PDF::Writer.new( :paper => paper || "LETTER" )
214
- }
215
-
216
- renderer :table do
217
- pre[pdf] if pre
218
- PDF::SimpleTable.new do |table|
219
- table.maximum_width = 500
220
- table.orientation = :center
221
- table.data = data
222
- m = "Sorry, cant build PDFs from array like things (yet)"
223
- raise m if self.rendered_field_names.empty?
224
- table.column_order = self.rendered_field_names
225
- table.render_on(pdf)
226
- end
227
- post[pdf] if post
228
- pdf.render
229
- end
230
-
231
- format_field_names { data.column_names }
232
-
233
- renderer(:invoice) { pdf.render }
234
-
235
- # Company Information in top lefthand corner
236
- helper(:build_company_header, :engine => :invoice_engine) { |eng|
237
- @tod = pdf.y
238
- text_box(eng.company_info)
239
- }
240
-
241
- helper(:build_headers, :engine => :invoice_engine) { |eng|
242
- build_company_header_helper(eng)
243
- build_customer_header_helper(eng)
244
- build_title_helper(eng)
245
- build_order_header_helper(eng)
246
- }
247
-
248
- helper(:build_order_header, :engine => :invoice_engine) { |eng|
249
- if eng.order_info
250
- text_box(eng.order_info, :position => 350)
251
- end
252
- }
253
-
254
- helper(:build_title, :engine => :invoice_engine) { |eng|
255
- pdf.y = @tod
256
- if eng.title
257
- pdf.text eng.title, :left => 350, :font_size => 14
258
- pdf.y -= 10
259
- end
260
- }
261
-
262
- helper(:build_footer, :engine => :invoice_engine) { |eng|
263
- # footer
264
- pdf.open_object do |footer|
265
- pdf.save_state
266
- pdf.stroke_color! Color::RGB::Black
267
- pdf.stroke_style! PDF::Writer::StrokeStyle::DEFAULT
268
- if eng.comments
269
- pdf.y -= 20
270
- text_box eng.comments, :position => 110, :width => 400,
271
- :font_size => 14
272
- end
273
- pdf.add_text_wrap( 50, 20, 200, "Printed at " +
274
- Time.now.strftime("%H:%M %d/%m/%Y"), 8)
275
-
276
- pdf.restore_state
277
- pdf.close_object
278
- pdf.add_object(footer, :all_pages)
279
- end
280
- pdf.stop_page_numbering(true, :current)
281
- }
282
-
283
- helper(:build_body, :engine => :invoice_engine) do
284
- pdf.start_page_numbering(500, 20, 8, :right)
285
-
286
- # order contents
287
- pdf.y = 620
288
-
289
- PDF::SimpleTable.new do |table|
290
- table.width = 450
291
- table.orientation = :center
292
- table.data = data
293
- table.show_lines = :outer
294
- table.column_order = data.column_names
295
- table.render_on(pdf)
296
- table.font_size = 12
297
- end
298
- end
299
-
300
- # Order details
301
- helper(:build_customer_header, :engine => :invoice_engine) { |eng|
302
- pdf.y -= 10
303
- text_box(eng.customer_info)
304
- }
305
-
306
- def self.text_box(content,options={})
307
- PDF::SimpleTable.new do |table|
308
- table.data = content.to_a.inject([]) do |s,line|
309
- s << { "value" => line }
310
- end
311
- table.column_order = "value"
312
- table.show_headings = false
313
- table.show_lines = :outer
314
- table.shade_rows = :none
315
- table.width = options[:width] || 200
316
- table.orientation = options[:orientation] || :right
317
- table.position = options[:position] || :left
318
- table.font_size = options[:font_size] || 10
319
- table.render_on(pdf)
320
- end
321
- end
322
-
323
- plugin_name :pdf
324
- register_on :table_engine
325
- register_on :invoice_engine
326
- end
327
-
328
- class HTMLPlugin < Format::Plugin
329
-
330
- rendering_options :red_cloth_enabled => true, :erb_enabled => true
331
-
332
- renderer :document
333
-
334
- renderer :table do
335
- rc = data.inject(rendered_field_names) { |s,r|
336
- row = r.map { |e| e.to_s.empty? ? "&nbsp;" : e }
337
- s + "|#{row.to_a.join('|')}|\n"
338
- }
339
- Format.document :data => rc, :plugin => :html
340
- end
341
-
342
- format_field_names do
343
- s = "|_." + data.column_names.join(" |_.") + "|\n"
344
- end
345
-
346
- plugin_name :html
347
- register_on :table_engine
348
- register_on :document_engine
349
68
 
69
+ plugins = %w[text csv pdf svg html]
70
+ plugins.each { |p| require "ruport/format/plugin/#{p}_plugin" }
350
71
  end
351
-
352
- end
72
+ end
353
73
  end
@@ -0,0 +1,22 @@
1
+ module Ruport
2
+ class Format::Plugin
3
+ class CSVPlugin < Format::Plugin
4
+
5
+ helper(:init_plugin) { |eng| require "fastercsv" }
6
+
7
+ format_field_names do
8
+ FasterCSV.generate { |csv| csv << data.column_names }
9
+ end
10
+
11
+ renderer :table do
12
+ rendered_field_names +
13
+ FasterCSV.generate { |csv| data.each { |r| csv << r } }
14
+ end
15
+
16
+ plugin_name :csv
17
+ register_on :table_engine
18
+ end
19
+ end
20
+ end
21
+
22
+
@@ -0,0 +1,27 @@
1
+ module Ruport
2
+ class Format::Plugin
3
+ class HTMLPlugin < Format::Plugin
4
+
5
+ rendering_options :red_cloth_enabled => true, :erb_enabled => true
6
+
7
+ renderer :document
8
+
9
+ renderer :table do
10
+ rc = data.inject(rendered_field_names) { |s,r|
11
+ row = r.map { |e| e.to_s.empty? ? "&nbsp;" : e }
12
+ s + "|#{row.to_a.join('|')}|\n"
13
+ }
14
+ Format.document :data => rc, :plugin => :html
15
+ end
16
+
17
+ format_field_names do
18
+ s = "|_." + data.column_names.join(" |_.") + "|\n"
19
+ end
20
+
21
+ plugin_name :html
22
+ register_on :table_engine
23
+ register_on :document_engine
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,126 @@
1
+ module Ruport
2
+ class Format::Plugin
3
+ class PDFPlugin < Format::Plugin
4
+ attribute :pdf
5
+ attribute :paper
6
+
7
+ helper(:init_plugin) {
8
+ require "pdf/writer"
9
+ require "pdf/simpletable"
10
+ self.pdf = PDF::Writer.new( :paper => paper || "LETTER" )
11
+ }
12
+
13
+ renderer :table do
14
+ pre[pdf] if pre
15
+ PDF::SimpleTable.new do |table|
16
+ table.maximum_width = 500
17
+ table.orientation = :center
18
+ table.data = data
19
+ m = "Sorry, cant build PDFs from array like things (yet)"
20
+ raise m if self.rendered_field_names.empty?
21
+ table.column_order = self.rendered_field_names
22
+ table.render_on(pdf)
23
+ end
24
+ post[pdf] if post
25
+ pdf.render
26
+ end
27
+
28
+ format_field_names { data.column_names }
29
+
30
+ renderer(:invoice) { pdf.render }
31
+
32
+ # Company Information in top lefthand corner
33
+ helper(:build_company_header, :engine => :invoice_engine) { |eng|
34
+ @tod = pdf.y
35
+ text_box(eng.company_info)
36
+ }
37
+
38
+ helper(:build_headers, :engine => :invoice_engine) { |eng|
39
+ build_company_header_helper(eng)
40
+ build_customer_header_helper(eng)
41
+ build_title_helper(eng)
42
+ build_order_header_helper(eng)
43
+ }
44
+
45
+ helper(:build_order_header, :engine => :invoice_engine) { |eng|
46
+ if eng.order_info
47
+ text_box(eng.order_info, :position => 350)
48
+ end
49
+ }
50
+
51
+ helper(:build_title, :engine => :invoice_engine) { |eng|
52
+ pdf.y = @tod
53
+ if eng.title
54
+ pdf.text eng.title, :left => 350, :font_size => 14
55
+ pdf.y -= 10
56
+ end
57
+ }
58
+
59
+ helper(:build_footer, :engine => :invoice_engine) { |eng|
60
+ # footer
61
+ pdf.open_object do |footer|
62
+ pdf.save_state
63
+ pdf.stroke_color! Color::RGB::Black
64
+ pdf.stroke_style! PDF::Writer::StrokeStyle::DEFAULT
65
+ if eng.comments
66
+ pdf.y -= 20
67
+ text_box eng.comments, :position => 110, :width => 400,
68
+ :font_size => 14
69
+ end
70
+ pdf.add_text_wrap( 50, 20, 200, "Printed at " +
71
+ Time.now.strftime("%H:%M %d/%m/%Y"), 8)
72
+
73
+ pdf.restore_state
74
+ pdf.close_object
75
+ pdf.add_object(footer, :all_pages)
76
+ end
77
+ pdf.stop_page_numbering(true, :current)
78
+ }
79
+
80
+ helper(:build_body, :engine => :invoice_engine) do
81
+ pdf.start_page_numbering(500, 20, 8, :right)
82
+
83
+ # order contents
84
+ pdf.y = 620
85
+
86
+ PDF::SimpleTable.new do |table|
87
+ table.width = 450
88
+ table.orientation = :center
89
+ table.data = data
90
+ table.show_lines = :outer
91
+ table.column_order = data.column_names
92
+ table.render_on(pdf)
93
+ table.font_size = 12
94
+ end
95
+ end
96
+
97
+ # Order details
98
+ helper(:build_customer_header, :engine => :invoice_engine) { |eng|
99
+ pdf.y -= 10
100
+ text_box(eng.customer_info)
101
+ }
102
+
103
+ def self.text_box(content,options={})
104
+ PDF::SimpleTable.new do |table|
105
+ table.data = content.to_a.inject([]) do |s,line|
106
+ s << { "value" => line }
107
+ end
108
+ table.column_order = "value"
109
+ table.show_headings = false
110
+ table.show_lines = :outer
111
+ table.shade_rows = :none
112
+ table.width = options[:width] || 200
113
+ table.orientation = options[:orientation] || :right
114
+ table.position = options[:position] || :left
115
+ table.font_size = options[:font_size] || 10
116
+ table.render_on(pdf)
117
+ end
118
+ end
119
+
120
+ plugin_name :pdf
121
+ register_on :table_engine
122
+ register_on :invoice_engine
123
+ end
124
+ end
125
+ end
126
+
@@ -0,0 +1,61 @@
1
+ module Ruport
2
+ class Format::Plugin
3
+ class SVGPlugin < Format::Plugin
4
+ helper(:init_plugin) { |eng|
5
+ # check the supplied data can be used for graphing
6
+ data.each { |r|
7
+ if data.column_names.size != r.data.size
8
+ raise InvalidGraphDataError,
9
+ "Column names and data do not match"
10
+ end
11
+ r.data.each { |c|
12
+ begin
13
+ c = BigDecimal.new(c) unless c.kind_of?(Float) ||
14
+ c.kind_of?(Fixnum) || c.kind_of?(BigDecimal)
15
+ rescue
16
+ raise InvalidGraphDataError,
17
+ "Unable to convert #{c.to_s} into a number"
18
+ end
19
+ }
20
+ }
21
+
22
+ raise InvalidGraphOptionError,
23
+ 'You must provide a width before rendering a graph' if eng.width.nil?
24
+ raise InvalidGraphOptionError,
25
+ 'You must provide a height before rendering a graph' if eng.height.nil?
26
+ raise InvalidGraphOptionError,
27
+ 'You must provide a style before rendering a graph' if eng.style.nil?
28
+ if eng.style != :area && eng.style != :bar &&
29
+ eng.style != :line &&
30
+ eng.style != :smiles &&
31
+ eng.style != :stacked
32
+ raise InvalidGraphOptionError, 'Invalid graph style'
33
+ end
34
+
35
+ require 'scruffy'
36
+ @graph = Scruffy::Graph.new
37
+ @graph.title = eng.title unless eng.title.nil?
38
+ @graph.theme = Scruffy::Themes::Mephisto.new
39
+ @graph.point_markers = @data.column_names
40
+ @graph_style = eng.style
41
+ @graph_width = eng.width
42
+ @graph_height = eng.height
43
+ }
44
+
45
+ renderer :graph do
46
+
47
+ data.each_with_index { |r,i|
48
+ @graph.add(@graph_style,
49
+ r.tags[0] || 'series ' + (i+1).to_s,
50
+ r.data)
51
+ }
52
+
53
+ # return the rendered graph
54
+ @graph.render(:size => [@graph_width, @graph_height])
55
+ end
56
+
57
+ plugin_name :svg
58
+ register_on :graph_engine
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,71 @@
1
+ module Ruport
2
+ class Format::Plugin
3
+ class TextPlugin < Format::Plugin
4
+ rendering_options :erb_enabled => true, :red_cloth_enabled => false
5
+
6
+ renderer :document
7
+
8
+ renderer :table do
9
+ require "ruport/system_extensions"
10
+
11
+ th = "#{rendered_field_names}#{hr}"
12
+
13
+ data.each { |r|
14
+ r.each_with_index { |f,i|
15
+ r[i] = f.to_s.center(max_col_width(i))
16
+ }
17
+ }
18
+
19
+ a = data.inject(th){ |s,r|
20
+ s + "| #{r.to_a.join(' | ')} |\n"
21
+ } << hr
22
+
23
+ width = self.right_margin || SystemExtensions.terminal_width
24
+
25
+ a.to_a.each { |r|
26
+ r.gsub!(/\A.{#{width+1},}/) { |m| m[0,width-2] + ">>" }
27
+ }.join
28
+ end
29
+
30
+ format_field_names do
31
+ data.column_names.each_with_index { |f,i|
32
+ data.column_names[i] = f.to_s.center(max_col_width(i))
33
+ }
34
+ "#{hr}| #{data.column_names.to_a.join(' | ')} |\n"
35
+ end
36
+
37
+ action :max_col_width do |index|
38
+ f = data.column_names if data.respond_to? :column_names
39
+ d = Data::Table.new :column_names => f, :data => data
40
+
41
+ cw = d.map { |r| r[index].to_s.length }.max
42
+
43
+ return cw unless d.column_names
44
+
45
+ nw = (index.kind_of?(Integer) ? d.column_names[index] : index ).to_s.length
46
+
47
+ [cw,nw].max
48
+ end
49
+
50
+ action :table_width do
51
+ f = data.column_names if data.respond_to? :column_names
52
+ d = Data::Table.new:column_names => f, :data => data
53
+
54
+ f = d[0].attributes || (0...d[0].length)
55
+
56
+ f.inject(0) { |s,e| s + max_col_width(e) }
57
+ end
58
+
59
+ action :hr do
60
+ len = data[0].to_a.length * 3 + table_width + 1
61
+ "+" + "-"*(len-2) + "+\n"
62
+ end
63
+
64
+ attribute :right_margin
65
+ plugin_name :text
66
+ register_on :table_engine
67
+ register_on :document_engine
68
+ end
69
+ end
70
+ end
71
+
@@ -58,16 +58,16 @@ module Ruport
58
58
  # A Unix savvy method to fetch the console columns, and rows.
59
59
  def terminal_size
60
60
  `stty size`.split.map { |x| x.to_i }.reverse
61
- end
61
+ end
62
+ end
62
63
 
63
- def terminal_width
64
- terminal_size.first
65
- end
64
+ def terminal_width
65
+ terminal_size.first
66
+ end
66
67
 
67
- def terminal_height
68
- terminal_size.last
69
- end
70
-
68
+ def terminal_height
69
+ terminal_size.last
71
70
  end
71
+
72
72
  end
73
73
  end
@@ -0,0 +1,32 @@
1
+ ***************
2
+ *** 60,74 ****
3
+ `stty size`.split.map { |x| x.to_i }.reverse
4
+ end
5
+
6
+ - end
7
+ -
8
+ - def terminal_width
9
+ - terminal_size.first
10
+ - end
11
+ -
12
+ - def terminal_height
13
+ - terminal_size.last
14
+ - end
15
+
16
+ end
17
+ end
18
+ --- 60,73 ----
19
+ `stty size`.split.map { |x| x.to_i }.reverse
20
+ end
21
+
22
+ + def terminal_width
23
+ + terminal_size.first
24
+ + end
25
+
26
+ + def terminal_height
27
+ + terminal_size.last
28
+ + end
29
+ +
30
+ + end
31
+ end
32
+ end
@@ -36,4 +36,9 @@ class TestCollection < Test::Unit::TestCase
36
36
  assert_equal @ghost_collection.to_csv, @ghost_collection.as(:csv)
37
37
  end
38
38
 
39
+ def test_invalid_plugin_throws_an_error
40
+ assert_raise(InvalidPluginError) { @ghost_collection.to_papyrus_scroll }
41
+ assert_raise(InvalidPluginError) { @ghost_collection.as(:stone_tablet)}
42
+ end
43
+
39
44
  end
@@ -4718,3 +4718,15 @@ F, [2006-08-28T14:56:51.239122 #2797] FATAL -- : no block given!
4718
4718
  F, [2006-08-28T15:03:28.339719 #2839] FATAL -- : Missing host for mailer bar
4719
4719
  F, [2006-08-28T15:03:28.340989 #2839] FATAL -- : Missing DSN for source foo!
4720
4720
  F, [2006-08-28T15:03:29.731996 #2839] FATAL -- : no block given!
4721
+ F, [2006-08-30T16:45:01.507510 #2290] FATAL -- : Missing host for mailer bar
4722
+ F, [2006-08-30T16:45:01.509091 #2290] FATAL -- : Missing DSN for source foo!
4723
+ F, [2006-08-30T16:45:02.931966 #2290] FATAL -- : no block given!
4724
+ F, [2006-08-31T18:50:43.741551 #2594] FATAL -- : Missing host for mailer bar
4725
+ F, [2006-08-31T18:50:43.823591 #2594] FATAL -- : Missing DSN for source foo!
4726
+ F, [2006-08-31T18:50:45.287417 #2594] FATAL -- : no block given!
4727
+ F, [2006-09-02T14:35:05.490338 #2499] FATAL -- : Missing host for mailer bar
4728
+ F, [2006-09-02T14:35:05.524813 #2499] FATAL -- : Missing DSN for source foo!
4729
+ F, [2006-09-02T14:35:07.162616 #2499] FATAL -- : no block given!
4730
+ F, [2006-09-02T14:41:36.925689 #2530] FATAL -- : Missing host for mailer bar
4731
+ F, [2006-09-02T14:41:36.927265 #2530] FATAL -- : Missing DSN for source foo!
4732
+ F, [2006-09-02T14:41:38.446094 #2530] FATAL -- : no block given!
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
3
3
  specification_version: 1
4
4
  name: ruport
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.5.0
7
- date: 2006-08-28 00:00:00 -04:00
6
+ version: 0.5.1
7
+ date: 2006-09-02 00:00:00 -04:00
8
8
  summary: A generalized Ruby report generation and templating engine.
9
9
  require_paths:
10
10
  - lib
@@ -47,6 +47,7 @@ files:
47
47
  - lib/ruport/rails
48
48
  - lib/ruport/data
49
49
  - lib/ruport/report
50
+ - lib/ruport/system_extensions.rb.rej
50
51
  - lib/ruport/system_extensions.rb
51
52
  - lib/ruport/config.rb
52
53
  - lib/ruport/query.rb
@@ -59,6 +60,17 @@ files:
59
60
  - lib/ruport/query/sql_split.rb
60
61
  - lib/ruport/format/plugin.rb
61
62
  - lib/ruport/format/engine.rb
63
+ - lib/ruport/format/engine
64
+ - lib/ruport/format/plugin
65
+ - lib/ruport/format/engine/document.rb
66
+ - lib/ruport/format/engine/graph.rb
67
+ - lib/ruport/format/engine/invoice.rb
68
+ - lib/ruport/format/engine/table.rb
69
+ - lib/ruport/format/plugin/csv_plugin.rb
70
+ - lib/ruport/format/plugin/html_plugin.rb
71
+ - lib/ruport/format/plugin/pdf_plugin.rb
72
+ - lib/ruport/format/plugin/svg_plugin.rb
73
+ - lib/ruport/format/plugin/text_plugin.rb
62
74
  - lib/ruport/rails/reportable.rb
63
75
  - lib/ruport/data/taggable.rb
64
76
  - lib/ruport/data/table.rb