ruport 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. data/LICENSE +55 -9
  2. data/Rakefile +3 -5
  3. data/examples/line_plotter.rb +3 -0
  4. data/examples/pdf_complex_report.rb +0 -1
  5. data/examples/pdf_report_with_common_base.rb +72 -0
  6. data/examples/pdf_styles.rb +16 -0
  7. data/examples/simple_pdf_lines.rb +0 -1
  8. data/lib/ruport.rb +5 -66
  9. data/lib/ruport/acts_as_reportable.rb +122 -51
  10. data/lib/ruport/data/grouping.rb +30 -13
  11. data/lib/ruport/data/record.rb +26 -25
  12. data/lib/ruport/data/table.rb +91 -34
  13. data/lib/ruport/formatter.rb +86 -11
  14. data/lib/ruport/formatter/csv.rb +29 -2
  15. data/lib/ruport/formatter/html.rb +23 -1
  16. data/lib/ruport/formatter/pdf.rb +123 -32
  17. data/lib/ruport/formatter/text.rb +62 -6
  18. data/lib/ruport/query.rb +75 -39
  19. data/lib/ruport/renderer.rb +250 -35
  20. data/lib/ruport/renderer/grouping.rb +2 -2
  21. data/test/html_formatter_test.rb +4 -1
  22. data/test/pdf_formatter_test.rb +30 -7
  23. data/test/query_test.rb +12 -0
  24. data/test/renderer_test.rb +33 -2
  25. data/test/table_test.rb +8 -2
  26. data/test/text_formatter_test.rb +11 -1
  27. metadata +53 -107
  28. data/bin/rope +0 -12
  29. data/examples/rope_examples/itunes/README +0 -12
  30. data/examples/rope_examples/itunes/Rakefile +0 -39
  31. data/examples/rope_examples/itunes/config/environment.rb +0 -4
  32. data/examples/rope_examples/itunes/data/mix.txt +0 -1
  33. data/examples/rope_examples/itunes/lib/helpers.rb +0 -0
  34. data/examples/rope_examples/itunes/lib/init.rb +0 -39
  35. data/examples/rope_examples/itunes/lib/reports.rb +0 -1
  36. data/examples/rope_examples/itunes/lib/reports/playlist.rb +0 -17
  37. data/examples/rope_examples/itunes/log/ruport.log +0 -1
  38. data/examples/rope_examples/itunes/test/test_playlist.rb +0 -8
  39. data/examples/rope_examples/itunes/util/build +0 -96
  40. data/examples/rope_examples/itunes/util/sql_exec +0 -5
  41. data/examples/rope_examples/sales_report/README +0 -4
  42. data/examples/rope_examples/sales_report/Rakefile +0 -39
  43. data/examples/rope_examples/sales_report/config/environment.rb +0 -4
  44. data/examples/rope_examples/sales_report/lib/helpers.rb +0 -0
  45. data/examples/rope_examples/sales_report/lib/init.rb +0 -39
  46. data/examples/rope_examples/sales_report/lib/reports.rb +0 -1
  47. data/examples/rope_examples/sales_report/lib/reports/sales.rb +0 -132
  48. data/examples/rope_examples/sales_report/log/ruport.log +0 -1
  49. data/examples/rope_examples/sales_report/output/books.pdf +0 -170
  50. data/examples/rope_examples/sales_report/output/books.txt +0 -11
  51. data/examples/rope_examples/sales_report/test/test_sales.rb +0 -8
  52. data/examples/rope_examples/sales_report/util/build +0 -96
  53. data/examples/rope_examples/sales_report/util/sql_exec +0 -5
  54. data/examples/sample.rb +0 -16
  55. data/lib/ruport/generator.rb +0 -294
  56. data/lib/ruport/report.rb +0 -262
  57. data/setup.rb +0 -1585
  58. data/test/report_test.rb +0 -218
  59. data/test/samples/foo.rtxt +0 -3
@@ -1,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