ruport 0.10.0 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/LICENSE +55 -9
  2. data/Rakefile +3 -5
  3. data/examples/line_plotter.rb +3 -0
  4. data/examples/pdf_complex_report.rb +0 -1
  5. data/examples/pdf_report_with_common_base.rb +72 -0
  6. data/examples/pdf_styles.rb +16 -0
  7. data/examples/simple_pdf_lines.rb +0 -1
  8. data/lib/ruport.rb +5 -66
  9. data/lib/ruport/acts_as_reportable.rb +122 -51
  10. data/lib/ruport/data/grouping.rb +30 -13
  11. data/lib/ruport/data/record.rb +26 -25
  12. data/lib/ruport/data/table.rb +91 -34
  13. data/lib/ruport/formatter.rb +86 -11
  14. data/lib/ruport/formatter/csv.rb +29 -2
  15. data/lib/ruport/formatter/html.rb +23 -1
  16. data/lib/ruport/formatter/pdf.rb +123 -32
  17. data/lib/ruport/formatter/text.rb +62 -6
  18. data/lib/ruport/query.rb +75 -39
  19. data/lib/ruport/renderer.rb +250 -35
  20. data/lib/ruport/renderer/grouping.rb +2 -2
  21. data/test/html_formatter_test.rb +4 -1
  22. data/test/pdf_formatter_test.rb +30 -7
  23. data/test/query_test.rb +12 -0
  24. data/test/renderer_test.rb +33 -2
  25. data/test/table_test.rb +8 -2
  26. data/test/text_formatter_test.rb +11 -1
  27. metadata +53 -107
  28. data/bin/rope +0 -12
  29. data/examples/rope_examples/itunes/README +0 -12
  30. data/examples/rope_examples/itunes/Rakefile +0 -39
  31. data/examples/rope_examples/itunes/config/environment.rb +0 -4
  32. data/examples/rope_examples/itunes/data/mix.txt +0 -1
  33. data/examples/rope_examples/itunes/lib/helpers.rb +0 -0
  34. data/examples/rope_examples/itunes/lib/init.rb +0 -39
  35. data/examples/rope_examples/itunes/lib/reports.rb +0 -1
  36. data/examples/rope_examples/itunes/lib/reports/playlist.rb +0 -17
  37. data/examples/rope_examples/itunes/log/ruport.log +0 -1
  38. data/examples/rope_examples/itunes/test/test_playlist.rb +0 -8
  39. data/examples/rope_examples/itunes/util/build +0 -96
  40. data/examples/rope_examples/itunes/util/sql_exec +0 -5
  41. data/examples/rope_examples/sales_report/README +0 -4
  42. data/examples/rope_examples/sales_report/Rakefile +0 -39
  43. data/examples/rope_examples/sales_report/config/environment.rb +0 -4
  44. data/examples/rope_examples/sales_report/lib/helpers.rb +0 -0
  45. data/examples/rope_examples/sales_report/lib/init.rb +0 -39
  46. data/examples/rope_examples/sales_report/lib/reports.rb +0 -1
  47. data/examples/rope_examples/sales_report/lib/reports/sales.rb +0 -132
  48. data/examples/rope_examples/sales_report/log/ruport.log +0 -1
  49. data/examples/rope_examples/sales_report/output/books.pdf +0 -170
  50. data/examples/rope_examples/sales_report/output/books.txt +0 -11
  51. data/examples/rope_examples/sales_report/test/test_sales.rb +0 -8
  52. data/examples/rope_examples/sales_report/util/build +0 -96
  53. data/examples/rope_examples/sales_report/util/sql_exec +0 -5
  54. data/examples/sample.rb +0 -16
  55. data/lib/ruport/generator.rb +0 -294
  56. data/lib/ruport/report.rb +0 -262
  57. data/setup.rb +0 -1585
  58. data/test/report_test.rb +0 -218
  59. data/test/samples/foo.rtxt +0 -3
@@ -1,14 +1,70 @@
1
- # formatter.rb : Generalized formatting base class for Ruby Reports
1
+ # Ruport : Extensible Reporting System
2
2
  #
3
- # Created by Gregory Brown. Copyright December 2006, All Rights Reserved.
3
+ # formatter.rb provides a generalized base class for creating ruport formatters.
4
+ #
5
+ # Created By Gregory Brown
6
+ # Copyright (C) December 2006, All Rights Reserved.
4
7
  #
5
- # This is free software, please see LICENSE and COPYING for details.
6
-
7
- module Ruport
8
+ # This is free software distributed under the same terms as Ruby 1.8
9
+ # See LICENSE and COPYING for details.
10
+ module Ruport
11
+ # Formatter is the base class for Ruport's format implementations.
12
+ #
13
+ # Typically, a Formatter will implement one or more output types,
14
+ # and be registered with one or more Renderer classes.
15
+ #
16
+ # This class provides all the necessary base functionality to make
17
+ # use of Ruport's rendering system, including option handling, data
18
+ # access, and basic output wrapping.
19
+ #
20
+ # The following example should provide a general idea of how formatters
21
+ # work, but see the built in formatters for reference implementations.
22
+ #
23
+ # A simple Renderer definition is included to help show the example in
24
+ # context, but you can also build your own custom interface to formatter
25
+ # if you wish.
26
+ #
27
+ # class ReverseRenderer < Ruport::Renderer
28
+ # stage :reversed_header, :reversed_body
29
+ # option :header_text
30
+ # end
31
+ #
32
+ # class ReversedText < Ruport::Formatter
33
+ #
34
+ # # Hooks formatter up to renderer
35
+ # renders :txt, :for => ReverseRenderer
36
+ #
37
+ # # Implements ReverseRenderer's :reversed_header hook
38
+ # # but can be used by any renderer
39
+ # def build_reversed_header
40
+ # output << "#{options.header_text}\n"
41
+ # output << "The reversed text will follow\n"
42
+ # end
43
+ #
44
+ # # Implements ReverseRenderer's :reversed_body hook
45
+ # # but can be used by any renderer
46
+ # def build_reversed_body
47
+ # output << data.reverse << "\n"
48
+ # end
49
+ #
50
+ # end
51
+ #
52
+ # puts ReverseRenderer.render_txt(:data => "apple",
53
+ # :header_text => "Hello Mike, Hello Joe!")
54
+ #
55
+ # -----
56
+ # OUTPUT:
57
+ #
58
+ # Hello Mike, Hello Joe!
59
+ # The reversed text will follow
60
+ # elppa
61
+ #
8
62
  class Formatter
9
-
63
+
64
+ # Provides shortcuts so that you can use Ruport's default rendering
65
+ # capabilities within your custom formatters
66
+ #
10
67
  module RenderingTools
11
-
12
68
  # Iterates through <tt>data</tt> and passes
13
69
  # each row to render_row with the given options
14
70
  def render_data_by_row(options={},&block)
@@ -75,9 +131,15 @@ module Ruport
75
131
  end
76
132
 
77
133
  include RenderingTools
78
-
79
- attr_accessor :data
80
- attr_accessor :format
134
+
135
+ # Set by the <tt>:data</tt> attribute from Renderer#render
136
+ attr_accessor :data
137
+
138
+ # Set automatically by Renderer#render(format) or Renderer#render_format
139
+ attr_accessor :format
140
+
141
+ # Set automatically by Renderer#render as a Renderer::Options option built
142
+ # by the hash provided.
81
143
  attr_writer :options
82
144
 
83
145
  # Registers the formatter with one or more Renderers
@@ -116,7 +178,7 @@ module Ruport
116
178
  @output ||= ""
117
179
  end
118
180
 
119
- # Provides a generic OpenStruct for storing formatter options
181
+ # Provides a Renderer::Options object for storing formatting options
120
182
  def options
121
183
  @options ||= Renderer::Options.new
122
184
  end
@@ -124,6 +186,19 @@ module Ruport
124
186
  # Clears output.
125
187
  def clear_output
126
188
  @output.replace("")
189
+ end
190
+
191
+ # Evaluates the string using ERB and returns the results.
192
+ #
193
+ # If <tt>:binding</tt> is specified, it will evaluate the template
194
+ # in that context.
195
+ def erb(string,options={})
196
+ require "erb"
197
+ if string =~ /\.r\w+$/
198
+ ERB.new(File.read(string)).result(options[:binding]||binding)
199
+ else
200
+ ERB.new(string).result(options[:binding]||binding)
201
+ end
127
202
  end
128
203
 
129
204
  # Provides a shortcut for per format handlers.
@@ -1,6 +1,32 @@
1
+ # Ruport : Extensible Reporting System
2
+ #
3
+ # formatter/csv.rb provides csv formatting for Ruport.
4
+ #
5
+ # Original code dates back to the earliest versions of Ruport in August 2005
6
+ # Extended over time, with much of the existing code being added around
7
+ # December 2006.
8
+ #
9
+ # Copyright (C) 2005-2007 Gregory Brown, 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.
13
+ #
1
14
  module Ruport
2
15
 
3
- # This formatter implements the CSV format for tabular data output.
16
+ # This formatter implements the CSV format for Ruport's Row, Table, Group
17
+ # and Grouping renderers. It is a light wrapper around James Edward Gray II's
18
+ # FasterCSV.
19
+ #
20
+ # === Rendering Options
21
+ #
22
+ # <tt>:style</tt> Used for grouping (:inline,:justified,:raw)
23
+ #
24
+ # <tt>:format_options</tt> A hash of FasterCSV options
25
+ #
26
+ # <tt>:show_table_headers</tt> True by default
27
+ #
28
+ # <tt>:show_group_headers</tt> True by default
29
+ #
4
30
  class Formatter::CSV < Formatter
5
31
 
6
32
  renders :csv, :for => [ Renderer::Row, Renderer::Table,
@@ -55,7 +81,8 @@ module Ruport
55
81
  output << "#{data.grouped_by}," << grouping_columns
56
82
  end
57
83
  end
58
-
84
+
85
+ # determines the proper style to use and renders the Grouping.
59
86
  def build_grouping_body
60
87
  case style
61
88
  when :inline
@@ -1,5 +1,25 @@
1
+ # Ruport : Extensible Reporting System
2
+ #
3
+ # formatter/html.rb provides html formatting for Ruport.
4
+ #
5
+ # Created by Gregory Brown, late 2005. Updated numerous times as needed to
6
+ # fit new formatting systems.
7
+ #
8
+ # Copyright (C) 2005-2007 Gregory Brown, All Rights Reserved.
9
+ #
10
+ # This is free software distributed under the same terms as Ruby 1.8
11
+ # See LICENSE and COPYING for details.
12
+ #
1
13
  module Ruport
2
- # Produces HTML output for tabular data.
14
+ # This class produces HTML output for Ruport's Row,Table,Group, and Grouping
15
+ # renderers. It can be used as a subclass, as it has some helper methods
16
+ # that might be useful for custom output
17
+ #
18
+ # === Rendering Options
19
+ #
20
+ # <tt>:show_table_headers</tt> True by default
21
+ #
22
+ # <tt>:show_group_headers</tt> True by default
3
23
  #
4
24
  class Formatter::HTML < Formatter
5
25
 
@@ -21,6 +41,8 @@ module Ruport
21
41
  end
22
42
  end
23
43
 
44
+ # Uses the Row renderer to build up the table body.
45
+ # Replaces nil and empty strings with "&nbsp;"
24
46
  def build_table_body
25
47
  render_data_by_row do |rend|
26
48
  r = rend.data
@@ -1,19 +1,43 @@
1
+ # Ruport : Extensible Reporting System
2
+ #
3
+ # formatter/pdf.rb provides text formatting for Ruport.
4
+ #
5
+ # Created by Gregory Brown, February 2006
6
+ # Extended by James Healy, Fall 2006
7
+ # Copyright (C) 2006-2007 Gregory Brown / James Healy, All Rights Reserved.
8
+ #
9
+ # Initially inspired by some ideas and code from Simon Claret,
10
+ # with many improvements from James Healy and Michael Milner over time.
11
+ #
12
+ # This is free software distributed under the same terms as Ruby 1.8
13
+ # See LICENSE and COPYING for details.
14
+ #
1
15
  module Ruport
2
16
 
3
- # PDF generation formatter
17
+ # This class provides PDF output for Ruport's Table, Group, and Grouping
18
+ # renderers. It wraps Austin Ziegler's PDF::Writer to provide a higher
19
+ # level interface and provides a number of helpers designed to make
20
+ # generating PDF reports much easier. You will typically want to build
21
+ # subclasses of this formatter to customize it as needed.
4
22
  #
5
- # options:
23
+ # Many methods forward options to PDF::Writer, so you may wish to consult
24
+ # its API docs.
25
+ #
26
+ # === Rendering Options
6
27
  # General:
7
28
  # * paper_size #=> "LETTER"
8
29
  # * paper_orientation #=> :portrait
9
30
  #
10
31
  # Text:
11
- # * text_format
32
+ # * text_format (sets options to be passed to add_text by default)
12
33
  #
13
34
  # Table:
14
35
  # * table_format (a hash that can take any of the options available
15
36
  # to PDF::SimpleTable)
16
- # * table_format[:maximum_width] #=> 500
37
+ # * table_format[:maximum_width] #=> 500
38
+ #
39
+ # Grouping:
40
+ # * style (:inline,:justified,:separated,:offset)
17
41
  #
18
42
  class Formatter::PDF < Formatter
19
43
 
@@ -21,9 +45,7 @@ module Ruport
21
45
  Renderer::Group, Renderer::Grouping ]
22
46
 
23
47
  attr_writer :pdf_writer
24
- attr_accessor :table_header_proc
25
- attr_accessor :table_footer_proc
26
-
48
+
27
49
  opt_reader :show_table_headers,
28
50
  :style,
29
51
  :table_format,
@@ -40,7 +62,7 @@ module Ruport
40
62
 
41
63
  # Returns the current PDF::Writer object or creates a new one if it has not
42
64
  # been set yet.
43
- #
65
+ #
44
66
  def pdf_writer
45
67
  @pdf_writer ||= options.formatter ||
46
68
  ::PDF::Writer.new( :paper => paper_size || "LETTER",
@@ -60,15 +82,19 @@ module Ruport
60
82
  def finalize_table
61
83
  render_pdf unless options.skip_finalize_table
62
84
  end
63
-
85
+
86
+ # Generates a header with the group name for Renderer::Group
64
87
  def build_group_header
65
88
  pad(10) { add_text data.name.to_s, :justification => :center }
66
89
  end
67
-
90
+
91
+ # Renders the group as a table for Renderer::Group
68
92
  def build_group_body
69
93
  render_table data, options.to_hash.merge(:formatter => pdf_writer)
70
94
  end
71
-
95
+
96
+ # Determines which style to use and renders the main body for
97
+ # Renderer::Grouping
72
98
  def build_grouping_body
73
99
  case style
74
100
  when :inline
@@ -82,12 +108,21 @@ module Ruport
82
108
  raise NotImplementedError, "Unknown style"
83
109
  end
84
110
  end
85
-
111
+
112
+ # calls <tt>render_pdf</tt>
86
113
  def finalize_grouping
87
114
  render_pdf
88
115
  end
89
116
 
90
- # Call PDF::Writer#text with the given arguments
117
+ # Call PDF::Writer#text with the given arguments, using <tt>text_format</tt>
118
+ # defaults, if they are defined.
119
+ #
120
+ # Example:
121
+ #
122
+ # options.text_format { :font_size => 14 }
123
+ #
124
+ # add_text("Hello Joe") #renders at 14pt
125
+ # add_text("Hello Mike",:font_size => 16) # renders at 16pt
91
126
  def add_text(text, format_opts={})
92
127
  format_opts = text_format.merge(format_opts) if text_format
93
128
  pdf_writer.text(text, format_opts)
@@ -125,7 +160,22 @@ module Ruport
125
160
  pdf_writer.add_image_from_file(path, x, y, img_width, img_height)
126
161
  end
127
162
 
128
- # Draws some text on the canvas, surrounded by a box with rounded corners
163
+ # Draws some text on the canvas, surrounded by a box with rounded corner
164
+ #
165
+ # Yields an OpenStruct which options can be defined on.
166
+ #
167
+ # Example:
168
+ #
169
+ # rounded_text_box(options.text) do |o|
170
+ # o.radius = 5
171
+ # o.width = options.width || 400
172
+ # o.height = options.height || 130
173
+ # o.font_size = options.font_size || 12
174
+ # o.heading = options.heading
175
+ #
176
+ # o.x = pdf_writer.absolute_x_middle - o.width/2
177
+ # o.y = 300
178
+ # end
129
179
  #
130
180
  def rounded_text_box(text)
131
181
  opts = OpenStruct.new
@@ -167,34 +217,60 @@ module Ruport
167
217
  pdf_writer.add_object(wm, :all_pages)
168
218
  end
169
219
  end
170
-
220
+
221
+ # adds n to pdf_writer.y, moving the vertical drawing position in the
222
+ # document
171
223
  def move_cursor(n)
172
224
  pdf_writer.y += n
173
225
  end
174
-
226
+
227
+ # moves the cursor to a specific y coordinate in the document
175
228
  def move_cursor_to(n)
176
229
  pdf_writer.y = n
177
230
  end
178
-
231
+
232
+ # puts a specified amount of whitespace above and below the code
233
+ # in your block. For example, if you want to surround the top and
234
+ # bottom of a line of text with 5 pixels of whitespace:
235
+ #
236
+ # pad(5) { add_text "This will be padded" }
179
237
  def pad(y,&block)
180
238
  move_cursor(-y)
181
239
  block.call
182
240
  move_cursor(-y)
183
241
  end
184
-
242
+
243
+ # Adds a specified amount of whitespace above the code in your block.
244
+ # For example, if you want to add a 10 pixel buffer to the top of a
245
+ # line of text:
246
+ #
247
+ # pad_top(10) { add_text "This will be padded on top" }
185
248
  def pad_top(y,&block)
186
249
  move_cursor(-y)
187
250
  block.call
188
251
  end
189
-
252
+
253
+ # Adds a specified amount of whitespace below the code in your block.
254
+ # For example, if you want to add a 10 pixel buffer to the bottom of a
255
+ # line of text:
256
+ #
257
+ # pad_bottom(10) { add_text "This will be padded on top" }
190
258
  def pad_bottom(y,&block)
191
259
  block.call
192
260
  move_cursor(-y)
193
261
  end
194
-
262
+
263
+ # Draws a PDF::SimpleTable using the given data (usually a Data::Table)
264
+ # Takes all the options you can set on a PDF::SimpleTable object,
265
+ # see the PDF::Writer API docs for details, or check our quick reference
266
+ # at:
267
+ #
268
+ # http://stonecode.svnrepository.com/ruport/trac.cgi/wiki/PdfWriterQuickRef
195
269
  def draw_table(table_data, format_opts={})
196
- m = "Sorry, cant build PDFs from array like things (yet)"
197
- raise m if table_data.column_names.empty?
270
+ m = "PDF Formatter requires column_names to be defined"
271
+ raise FormatterError, m if table_data.column_names.empty?
272
+
273
+ table_data.rename_columns { |c| c.to_s }
198
274
 
199
275
  format_opts = table_format.merge(format_opts) if table_format
200
276
 
@@ -210,38 +286,53 @@ module Ruport
210
286
  table.render_on(pdf_writer)
211
287
  end
212
288
  end
213
-
289
+
290
+ # This module provides tools to simplify some common drawing operations
291
+ # it is included by default in the PDF formatter
292
+ #
214
293
  module DrawingHelpers
215
-
294
+
295
+ # draws a horizontal line from x1 to x2
216
296
  def horizontal_line(x1,x2)
217
297
  pdf_writer.line(x1,cursor,x2,cursor)
218
298
  pdf_writer.stroke
219
299
  end
220
-
300
+
301
+ # draws a vertical line at x from y1 to y2
221
302
  def vertical_line_at(x,y1,y2)
222
303
  pdf_writer.line(x,y1,x,y2)
304
+ pdf_writer.stroke
223
305
  end
224
-
306
+
307
+ # Alias for PDF::Writer#absolute_left_margin
225
308
  def left_boundary
226
309
  pdf_writer.absolute_left_margin
227
310
  end
228
-
311
+
312
+ # Alias for PDF::Writer#absolute_right_margin
229
313
  def right_boundary
230
314
  pdf_writer.absolute_right_margin
231
315
  end
232
-
316
+
317
+ # Alias for PDF::Writer#absolute_top_margin
233
318
  def top_boundary
234
319
  pdf_writer.absolute_top_margin
235
320
  end
236
-
321
+
322
+ # Alias for PDF::Writer#absolute_bottom_margin
237
323
  def bottom_boundary
238
324
  pdf_writer.absolute_bottom_margin
239
325
  end
240
-
326
+
327
+ # Alias for PDF::Writer#y
241
328
  def cursor
242
329
  pdf_writer.y
243
330
  end
244
-
331
+
332
+ # Draws text at an absolute location, defined by
333
+ # :y, :x1|:left, :x2|:right
334
+ #
335
+ # All usual options to add_text are also supported
245
336
  def draw_text(text,text_opts)
246
337
  move_cursor_to(text_opts[:y]) if text_opts[:y]
247
338
  add_text(text,
@@ -288,7 +379,7 @@ module Ruport
288
379
  data.each do |name,group|
289
380
  group_column = { data.grouped_by => "<b>#{name}</b>\n" }
290
381
  group.each_with_index do |rec,i|
291
- i == 0 ? table << group_column.merge(rec.to_h) : table << rec
382
+ i == 0 ? table << group_column.merge(rec.to_hash) : table << rec
292
383
  end
293
384
  table << Array.new(grouping_columns.length,' ') if style == :separated
294
385
  end