ruport 0.8.14 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. data/README +42 -107
  2. data/Rakefile +29 -32
  3. data/examples/centered_pdf_text_box.rb +13 -19
  4. data/examples/example.csv +3 -0
  5. data/examples/line_plotter.rb +15 -15
  6. data/examples/pdf_complex_report.rb +10 -23
  7. data/examples/pdf_table_with_title.rb +12 -12
  8. data/examples/rope_examples/itunes/Rakefile +22 -1
  9. data/examples/rope_examples/itunes/config/environment.rb +4 -0
  10. data/examples/rope_examples/itunes/lib/init.rb +32 -2
  11. data/examples/rope_examples/itunes/util/build +50 -16
  12. data/examples/rope_examples/sales_report/README +1 -1
  13. data/examples/rope_examples/sales_report/Rakefile +22 -1
  14. data/examples/rope_examples/sales_report/config/environment.rb +4 -0
  15. data/examples/rope_examples/sales_report/lib/init.rb +32 -2
  16. data/examples/rope_examples/sales_report/lib/reports/sales.rb +10 -16
  17. data/examples/rope_examples/sales_report/util/build +50 -16
  18. data/examples/row_renderer.rb +39 -0
  19. data/examples/ruport_list/png_embed.rb +61 -0
  20. data/examples/ruport_list/roadmap.png +0 -0
  21. data/examples/sample.rb +16 -0
  22. data/examples/simple_pdf_lines.rb +24 -0
  23. data/lib/ruport.rb +143 -57
  24. data/lib/ruport/acts_as_reportable.rb +246 -0
  25. data/lib/ruport/data.rb +1 -2
  26. data/lib/ruport/data/grouping.rb +311 -0
  27. data/lib/ruport/data/record.rb +113 -84
  28. data/lib/ruport/data/table.rb +275 -174
  29. data/lib/ruport/formatter.rb +149 -0
  30. data/lib/ruport/formatter/csv.rb +87 -0
  31. data/lib/ruport/formatter/html.rb +89 -0
  32. data/lib/ruport/formatter/pdf.rb +357 -0
  33. data/lib/ruport/formatter/text.rb +151 -0
  34. data/lib/ruport/generator.rb +127 -30
  35. data/lib/ruport/query.rb +46 -99
  36. data/lib/ruport/renderer.rb +238 -194
  37. data/lib/ruport/renderer/grouping.rb +67 -0
  38. data/lib/ruport/renderer/table.rb +25 -98
  39. data/lib/ruport/report.rb +45 -96
  40. data/test/acts_as_reportable_test.rb +229 -0
  41. data/test/csv_formatter_test.rb +97 -0
  42. data/test/{_test_database.rb → database_test_.rb} +0 -0
  43. data/test/grouping_test.rb +305 -0
  44. data/test/html_formatter_test.rb +104 -0
  45. data/test/pdf_formatter_test.rb +25 -0
  46. data/test/{test_query.rb → query_test.rb} +32 -121
  47. data/test/{test_record.rb → record_test.rb} +40 -23
  48. data/test/renderer_test.rb +344 -0
  49. data/test/{test_report.rb → report_test.rb} +74 -44
  50. data/test/samples/ticket_count.csv +124 -0
  51. data/test/{test_sql_split.rb → sql_split_test.rb} +0 -0
  52. data/test/{test_table.rb → table_test.rb} +255 -44
  53. data/test/text_formatter_test.rb +144 -0
  54. data/util/bench/data/record/bench_as_vs_to.rb +17 -0
  55. data/util/bench/data/record/bench_constructor.rb +46 -0
  56. data/util/bench/data/record/bench_indexing.rb +65 -0
  57. data/util/bench/data/record/bench_reorder.rb +35 -0
  58. data/util/bench/data/record/bench_to_a.rb +19 -0
  59. data/util/bench/data/table/bench_column_manip.rb +103 -0
  60. data/util/bench/data/table/bench_dup.rb +24 -0
  61. data/util/bench/data/table/bench_init.rb +67 -0
  62. data/util/bench/data/table/bench_manip.rb +125 -0
  63. data/util/bench/formatter/bench_csv.rb +14 -0
  64. data/util/bench/formatter/bench_html.rb +14 -0
  65. data/util/bench/formatter/bench_pdf.rb +14 -0
  66. data/util/bench/formatter/bench_text.rb +14 -0
  67. data/util/bench/samples/tattle.csv +1237 -0
  68. metadata +121 -143
  69. data/TODO +0 -21
  70. data/examples/invoice.rb +0 -142
  71. data/examples/invoice_report.rb +0 -29
  72. data/examples/line_graph.rb +0 -38
  73. data/examples/rope_examples/itunes/config/ruport_config.rb +0 -8
  74. data/examples/rope_examples/sales_report/config/ruport_config.rb +0 -8
  75. data/lib/ruport/attempt.rb +0 -63
  76. data/lib/ruport/config.rb +0 -204
  77. data/lib/ruport/data/groupable.rb +0 -93
  78. data/lib/ruport/data/taggable.rb +0 -80
  79. data/lib/ruport/format.rb +0 -1
  80. data/lib/ruport/format/csv.rb +0 -29
  81. data/lib/ruport/format/html.rb +0 -42
  82. data/lib/ruport/format/latex.rb +0 -47
  83. data/lib/ruport/format/pdf.rb +0 -233
  84. data/lib/ruport/format/plugin.rb +0 -31
  85. data/lib/ruport/format/svg.rb +0 -60
  86. data/lib/ruport/format/text.rb +0 -103
  87. data/lib/ruport/format/xml.rb +0 -32
  88. data/lib/ruport/layout.rb +0 -1
  89. data/lib/ruport/layout/component.rb +0 -7
  90. data/lib/ruport/mailer.rb +0 -99
  91. data/lib/ruport/renderer/graph.rb +0 -46
  92. data/lib/ruport/report/graph.rb +0 -14
  93. data/lib/ruport/system_extensions.rb +0 -71
  94. data/test/test_config.rb +0 -88
  95. data/test/test_format_text.rb +0 -63
  96. data/test/test_graph_renderer.rb +0 -97
  97. data/test/test_groupable.rb +0 -56
  98. data/test/test_mailer.rb +0 -170
  99. data/test/test_renderer.rb +0 -151
  100. data/test/test_ruport.rb +0 -58
  101. data/test/test_table_renderer.rb +0 -141
  102. data/test/test_taggable.rb +0 -52
@@ -1,80 +0,0 @@
1
- # The Ruport Data Collections.
2
- # Authors: Gregory Brown / Dudley Flanders
3
- #
4
- # This is Free Software. For details, see LICENSE and COPYING
5
- # Copyright 2006 by respective content owners, all rights reserved.
6
- module Ruport::Data
7
-
8
- require 'set'
9
- #
10
- # === Overview
11
- #
12
- # This module provides a simple mechanism for tagging arbitrary objects.
13
- # It provides the necessary methods to set and retrieve tags which can
14
- # consist of any Ruby object.
15
- #
16
- module Taggable
17
-
18
- #
19
- # Adds a tag to the object.
20
- #
21
- # Example:
22
- #
23
- # taggable_obj.tag :spiffy
24
- #
25
- def tag(tag_name)
26
- tags << tag_name
27
- end
28
-
29
- #
30
- # Removes a tag from the object.
31
- #
32
- # Example:
33
- #
34
- # taggable_obj.delete_tag :not_so_spiffy
35
- #
36
- def delete_tag(tag_name)
37
- tags.delete tag_name
38
- end
39
-
40
- #
41
- # Checks to see if a tag is present.
42
- #
43
- # Example:
44
- #
45
- # taggable_obj.has_tag? :spiffy #=> true
46
- #
47
- def has_tag?(tag_name)
48
- tags.include? tag_name
49
- end
50
-
51
- #
52
- # Returns an Set of the object's tags.
53
- #
54
- # Example:
55
- #
56
- # taggable_obj.tags #=> #<Set: {:spiffy, :kind_of_spiffy}>
57
- #
58
- def tags
59
- @ruport_tags ||= Set.new
60
- end
61
-
62
- #
63
- # Sets the tags.
64
- #
65
- # Example:
66
- #
67
- # taggable_obj.tags = [:really_dang_spiffy, :the_most_spiffy]
68
- #
69
- def tags=(tags_list)
70
- case tags_list
71
- when Array
72
- @ruport_tags = Set.new(tags_list)
73
- else
74
- @ruport_tags = tags_list
75
- end
76
- end
77
-
78
- end
79
-
80
- end
data/lib/ruport/format.rb DELETED
@@ -1 +0,0 @@
1
- require "ruport/format/plugin"
@@ -1,29 +0,0 @@
1
- module Ruport::Format
2
-
3
- # This plugin implements the CSV format for tabular data output.
4
- # See also: Renderer::Table
5
- class CSV < Plugin
6
-
7
- # Generates table header by turning column_names into a CSV row.
8
- # Uses build_csv_row to generate the actual formatted output
9
- #
10
- # This method does not do anything if layout.show_table_headers is false or
11
- # the Data::Table has no column names.
12
- def build_table_header
13
- unless data.column_names.empty? || !layout.show_table_headers
14
- build_csv_row(data.column_names)
15
- end
16
- end
17
-
18
- # Calls build_csv_row for each row in the Data::Table
19
- def build_table_body
20
- data.each { |r| build_csv_row(r) }
21
- end
22
-
23
- # Produces CSV output for a data row.
24
- def build_csv_row(row)
25
- require "fastercsv"
26
- output << FasterCSV.generate { |csv| csv << row }
27
- end
28
- end
29
- end
@@ -1,42 +0,0 @@
1
- module Ruport::Format
2
- # Produces HTML output for tabular data.
3
- #
4
- # See also Renderer::Table
5
- class HTML < Plugin
6
-
7
- # Generates table headers based on the column names of your Data::Table.
8
- #
9
- # This method does not do anything if layout.show_table_headers is false or
10
- # the Data::Table has no column names.
11
- def build_table_header
12
- output << "\t<table>\n"
13
- unless data.column_names.empty? || !layout.show_table_headers
14
- output << "\t\t<tr>\n\t\t\t<th>" +
15
- data.column_names.join("</th>\n\t\t\t<th>") +
16
- "</th>\n\t\t</tr>\n"
17
- end
18
- end
19
-
20
- # Generates the <tr> and <td> tags for each row, calling to_s on each
21
- # element of the Record. If the Record has been tagged, the tags will be
22
- # converted into class attributes in the HTML output.
23
- #
24
- def build_table_body
25
- output << data.inject("") do |s,r|
26
- row = r.map { |e| e.to_s.empty? ? "&nbsp;" : e }
27
- #classstr = r.tags.inject("") {|cs,c| cs + " class='#{c}'" }
28
- classstr =
29
- r.tags.length > 0 ? " class='#{r.tags.to_a.join(' ')}'" : ""
30
- s + "\t\t<tr#{classstr}>\n\t\t\t<td#{classstr}>" +
31
- row.to_a.join("</td>\n\t\t\t<td#{classstr}>") +
32
- "</td>\n\t\t</tr>\n"
33
- end
34
- end
35
-
36
- # Simply closes the table tag.
37
- def build_table_footer
38
- output << "\t</table>"
39
- end
40
-
41
- end
42
- end
@@ -1,47 +0,0 @@
1
- module Ruport::Format
2
- class Latex < Plugin #:nodoc:
3
-
4
- attr_accessor :caption
5
-
6
- def build_table_header
7
- output << "\\documentclass[11pt]{article}\n" <<
8
- "\\RequirePackage{lscape,longtable}\n" <<
9
- "\\begin{document}\n" <<
10
- "\\begin{longtable}[c]{ "
11
-
12
- data.column_names.each do
13
- output << " p{2cm} "
14
- end
15
- output << " }\n"
16
- output << "\\hline\n"
17
-
18
- output << "\\textsc{#{data.column_names[0]}}"
19
- data.column_names[1..-1].each do |t|
20
- output << " & "
21
- output << "\\textsc{#{t}}"
22
- end
23
-
24
- output << "\\\\\n"
25
- output << "\\hline\n"
26
- output << "\\endhead\n"
27
- output << "\\endfoot\n"
28
- output << "\\hline\n"
29
- end
30
-
31
- def build_table_body
32
- data.each do |r|
33
- output << r.to_a.join(" & ") + "\\\\\n"
34
- output << "\\hline\n"
35
- end
36
- if caption
37
- output << "\\caption[#{caption}]{#{caption}}\n"
38
- end
39
- output << "\\end{longtable}\n"
40
- end
41
-
42
- def build_table_footer
43
- output << "\\end{document}\n"
44
- end
45
-
46
- end
47
- end
@@ -1,233 +0,0 @@
1
- module Ruport::Format
2
-
3
- # PDF generation plugin
4
- #
5
- # layout options:
6
- # General:
7
- # * paper_size #=> "LETTER"
8
- # * orientation #=> :center
9
- #
10
- # Table:
11
- # * table_width
12
- # * max_table_width #=> 500
13
- #
14
- class PDF < Plugin
15
- attr_writer :pdf_writer
16
- attr_accessor :table_header_proc
17
- attr_accessor :table_footer_proc
18
-
19
- # Does the necessary PDF::Writer requires
20
- def initialize
21
- require "pdf/writer"
22
- require "pdf/simpletable"
23
- end
24
-
25
- # Returns the current PDF::Writer object or creates a new one if it has not
26
- # been set yet.
27
- #
28
- def pdf_writer
29
- @pdf_writer ||=
30
- ::PDF::Writer.new( :paper => layout.paper_size || "LETTER" )
31
- end
32
-
33
- # If table_header_proc is defined, it will be executed and the PDF::Writer
34
- # object will be yielded.
35
- #
36
- # This should be overridden by subclasses, or used as a shortcut for your
37
- # own plugin implementations
38
- #
39
- # This method is automatically called by the table renderer
40
- #
41
- def build_table_header
42
- table_header_proc[pdf_writer] if table_header_proc
43
- end
44
-
45
- # Calls the draw_table method
46
- #
47
- # This method is automatically called by the table renderer
48
- #
49
- def build_table_body
50
- draw_table
51
- end
52
-
53
- # If table_footer_proc is defined, it will be executed and the PDF::Writer
54
- # object will be yielded.
55
- #
56
- # This should be overridden by subclasses, or used as a shortcut for your
57
- # own plugin implementations
58
- #
59
- # This method is automatically called by the table renderer
60
- #
61
- def build_table_footer
62
- table_footer_proc[pdf_writer] if table_footer_proc
63
- end
64
-
65
- # Appends the results of PDF::Writer#render to output for your
66
- # <tt>pdf_writer</tt> object.
67
- #
68
- def finalize_table
69
- output << pdf_writer.render
70
- end
71
-
72
- # Call PDF::Writer#text with the given arguments
73
- def add_text(*args)
74
- pdf_writer.text(*args)
75
- end
76
-
77
- # - if the image is bigger than the box, it will be scaled down until it fits
78
- # - if the image is smaller than the box it's won't be resized
79
- #
80
- # arguments:
81
- # - x: left bound of box
82
- # - y: bottom bound of box
83
- # - width: width of box
84
- # - height: height of box
85
- def center_image_in_box(path, x, y, width, height)
86
- info = ::PDF::Writer::Graphics::ImageInfo.new(File.read(path))
87
-
88
- # if the image is larger than the requested box, prepare to
89
- # scale it down
90
- fits = !(info.width > width || info.height > height)
91
-
92
- # setup initial sizes for the image. These will be reduced as necesary
93
- img_width = info.width
94
- img_height = info.height
95
- img_ratio = info.height.to_f / info.width.to_f
96
-
97
- # reduce the size of the image until it fits into the requested box
98
- until fits
99
- img_width -= 1
100
- img_height = img_width * img_ratio
101
- fits = true if img_width < width && img_height < height
102
- end
103
-
104
- # if the width of the image is less than the requested box, calculate
105
- # the white space buffer
106
- if img_width < width
107
- white_space = width - img_width
108
- x = x + (white_space / 2)
109
- end
110
-
111
- # if the height of the image is less than the requested box, calculate
112
- # the white space buffer
113
- if img_height < height
114
- white_space = height - img_height
115
- y = y + (white_space / 2)
116
- end
117
-
118
- pdf_writer.add_image_from_file(path, x, y, img_width, img_height)
119
- end
120
-
121
- # Draws some text on the canvas, surrounded by a box with rounded corners
122
- #
123
- def rounded_text_box(text)
124
- opts = OpenStruct.new
125
- yield(opts)
126
-
127
- # resize the text automatically to ensure it isn't wider than the box
128
- loop do
129
- sz = pdf_writer.text_width( text, opts.font_size )
130
- opts.x + sz > opts.x + opts.width or break
131
- opts.font_size -= 1
132
- end
133
-
134
- # save the drawing state (colors, etc) so we can restore it later
135
- pdf_writer.save_state
136
-
137
- # draw our box
138
- pdf_writer.fill_color(opts.fill_color || Color::RGB::White)
139
- pdf_writer.stroke_color(opts.stroke_color || Color::RGB::Black)
140
- pdf_writer.rounded_rectangle( opts.x, opts.y,
141
- opts.width, opts.height,
142
- opts.radius).fill_stroke
143
-
144
- # if a heading for this box has been specified
145
- if opts.heading
146
- pdf_writer.line( opts.x, opts.y - 20,
147
- opts.x + opts.width, opts.y - 20).stroke
148
- pdf_writer.fill_color(Color::RGB::Black)
149
- move_cursor_to(opts.y - 3)
150
- add_text("<b>#{opts.heading}</b>",
151
- :absolute_left => opts.x, :absolute_right => opts.x + opts.width,
152
- :justification => :center, :font_size => opts.font_size)
153
- end
154
-
155
- # restore the original colors
156
- pdf_writer.restore_state
157
-
158
- # move our y cursor into position, write the text, then move the cursor
159
- # to be just below the box
160
- pdf_writer.y = opts.heading ? opts.y - 20 : opts.y
161
-
162
- add_text( text, :absolute_left => opts.x,
163
- :absolute_right => opts.x + opts.width,
164
- :justification => opts.justification || :center,
165
- :font_size => opts.font_size )
166
-
167
- pdf_writer.y = opts.y - opts.height
168
- end
169
-
170
- # adds an image to every page. The color and size won't be modified,
171
- # but it will be centered.
172
- #
173
- def watermark(imgpath)
174
- x = pdf_writer.absolute_left_margin
175
- y = pdf_writer.absolute_bottom_margin
176
- width = pdf_writer.absolute_right_margin - x
177
- height = pdf_writer.absolute_top_margin - y
178
-
179
- pdf_writer.open_object do |wm|
180
- pdf_writer.save_state
181
- center_image_in_box(imgpath, x, y, width, height)
182
- pdf_writer.restore_state
183
- pdf_writer.close_object
184
- pdf_writer.add_object(wm, :all_pages)
185
- end
186
- end
187
-
188
- # moves the PDF::Writer cursor by dy points
189
- # NOTE: In PDF::Writer, 0 is at the bottom of the page.
190
- def move_cursor(dy)
191
- pdf_writer.y += dy
192
- end
193
-
194
- # moves the PDF::Writer cursor to the y position specified
195
- def move_cursor_to(y)
196
- pdf_writer.y = y
197
- end
198
-
199
- # moves the cursor down by dy, executes the block, and moves the cursor
200
- # again.
201
- #
202
- # Example:
203
- #
204
- # # Add a padding of 5 to a text element
205
- #
206
- # pad(5) { add_text "hello" }
207
- #
208
- def pad(dy,&block)
209
- move_cursor -dy
210
- block.call
211
- move_cursor -dy
212
- end
213
-
214
- # Used by Renderer::Table to draw a SimpleTable.
215
- # table_width, max_table_width and orientation can all be set via the
216
- # <tt>layout</tt> object
217
- #
218
- def draw_table
219
- m = "Sorry, cant build PDFs from array like things (yet)"
220
- raise m if data.column_names.empty?
221
- ::PDF::SimpleTable.new do |table|
222
- table.maximum_width = layout.max_table_width || 500
223
- table.width = layout.table_width if layout.table_width
224
- table.orientation = layout.orientation || :center
225
- table.data = data
226
- table.column_order = data.column_names
227
- table.render_on(pdf_writer)
228
- end
229
- end
230
-
231
-
232
- end
233
- end
@@ -1,31 +0,0 @@
1
- # format/plugin.rb : Generalized formatting plugin base class for Ruby Reports
2
- #
3
- # Created by Gregory Brown. Copyright December 2006, All Rights Reserved.
4
- #
5
- # This is free software, please see LICENSE and COPYING for details.
6
-
7
- module Ruport
8
- module Format
9
- class Plugin
10
-
11
- attr_accessor :layout
12
- attr_accessor :data
13
-
14
- # Stores a string used for outputting formatted data.
15
- def output
16
- @output ||= ""
17
- end
18
-
19
- # Provides a generic OpenStruct for storing plugin options
20
- def options
21
- @options ||= OpenStruct.new
22
- end
23
-
24
- # clears output. Useful if you are building your own interface to
25
- # plugins.
26
- def clear_output
27
- @output.replace("")
28
- end
29
- end
30
- end
31
- end