ruport 0.6.1 → 0.7.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 (83) hide show
  1. data/AUTHORS +6 -0
  2. data/Rakefile +4 -4
  3. data/TODO +3 -2
  4. data/bin/rope +2 -103
  5. data/examples/pdf_complex_report.rb +53 -0
  6. data/lib/ruport/config.rb +7 -7
  7. data/lib/ruport/data/collection.rb +8 -7
  8. data/lib/ruport/data/groupable.rb +3 -2
  9. data/lib/ruport/data/record.rb +13 -16
  10. data/lib/ruport/data/table.rb +89 -18
  11. data/lib/ruport/format/csv.rb +29 -0
  12. data/lib/ruport/format/html.rb +40 -0
  13. data/lib/ruport/format/latex.rb +50 -0
  14. data/lib/ruport/format/pdf.rb +78 -0
  15. data/lib/ruport/format/plugin.rb +20 -65
  16. data/lib/ruport/format/svg.rb +39 -0
  17. data/lib/ruport/format/text.rb +77 -0
  18. data/lib/ruport/format/xml.rb +32 -0
  19. data/lib/ruport/format.rb +1 -159
  20. data/lib/ruport/generator.rb +158 -0
  21. data/lib/ruport/layout/component.rb +7 -0
  22. data/lib/ruport/layout.rb +1 -0
  23. data/lib/ruport/query.rb +3 -3
  24. data/lib/ruport/renderer/graph.rb +48 -0
  25. data/lib/ruport/renderer/table.rb +132 -0
  26. data/lib/ruport/renderer.rb +193 -0
  27. data/lib/ruport/report/graph.rb +2 -2
  28. data/lib/ruport/report.rb +94 -96
  29. data/lib/ruport/system_extensions.rb +3 -6
  30. data/lib/ruport.rb +6 -4
  31. data/test/samples/dates.csv +1409 -0
  32. data/test/samples/foo.rtxt +3 -0
  33. data/test/test_collection.rb +0 -14
  34. data/test/test_config.rb +6 -6
  35. data/test/test_graph_renderer.rb +97 -0
  36. data/test/test_groupable.rb +1 -0
  37. data/test/test_query.rb +325 -324
  38. data/test/test_record.rb +3 -2
  39. data/test/test_renderer.rb +74 -0
  40. data/test/test_report.rb +29 -26
  41. data/test/test_table.rb +54 -29
  42. data/test/test_table_renderer.rb +93 -0
  43. data/test/test_text_table.rb +61 -0
  44. data/test/unit.log +24 -0
  45. metadata +41 -63
  46. data/CHANGELOG +0 -587
  47. data/examples/basic_grouping.rb +0 -19
  48. data/examples/fieldless_table.rb +0 -13
  49. data/examples/latex_table.rb +0 -17
  50. data/examples/line_graph.rb +0 -22
  51. data/examples/line_graph_report.rb +0 -23
  52. data/examples/line_plotter.rb +0 -46
  53. data/examples/long.txt +0 -24
  54. data/examples/new_plugin.rb +0 -24
  55. data/examples/report.rb +0 -35
  56. data/examples/sample_invoice_report.rb +0 -32
  57. data/examples/simple_mail.rb +0 -15
  58. data/examples/simple_table_interface.rb +0 -20
  59. data/examples/sql_erb.rb +0 -20
  60. data/examples/template.rb +0 -15
  61. data/examples/text_processors.rb +0 -13
  62. data/lib/ruport/format/engine/document.rb +0 -28
  63. data/lib/ruport/format/engine/graph.rb +0 -18
  64. data/lib/ruport/format/engine/invoice.rb +0 -23
  65. data/lib/ruport/format/engine/table.rb +0 -54
  66. data/lib/ruport/format/engine.rb +0 -108
  67. data/lib/ruport/format/plugin/csv_plugin.rb +0 -26
  68. data/lib/ruport/format/plugin/html_plugin.rb +0 -32
  69. data/lib/ruport/format/plugin/latex_plugin.rb +0 -50
  70. data/lib/ruport/format/plugin/pdf_plugin.rb +0 -126
  71. data/lib/ruport/format/plugin/svg_plugin.rb +0 -61
  72. data/lib/ruport/format/plugin/text_plugin.rb +0 -77
  73. data/lib/ruport/meta_tools.rb +0 -66
  74. data/lib/ruport/report/invoice.rb +0 -29
  75. data/test/_test_groupable.rb +0 -0
  76. data/test/test_format.rb +0 -39
  77. data/test/test_format_engine.rb +0 -264
  78. data/test/test_graph.rb +0 -93
  79. data/test/test_invoice.rb +0 -32
  80. data/test/test_latex.rb +0 -20
  81. data/test/test_meta_tools.rb +0 -14
  82. data/test/test_plugin.rb +0 -277
  83. data/test/ts_all.rb +0 -21
@@ -1,46 +0,0 @@
1
- #this demonstrates how to create a complete engine / plugin setup.
2
- require "ruport"
3
-
4
- include Ruport
5
-
6
- class LinePlotter < Format::Engine
7
-
8
- Line = Struct.new(:x1,:y1,:x2,:y2)
9
-
10
- renderer do
11
- active_plugin.data = get_lines
12
- active_plugin.render_plot
13
- end
14
-
15
- def self.get_lines
16
- data.map { |r| Line.new(r[0][0],r[0][1],r[1][0],r[1][1]) }
17
- end
18
-
19
- alias_engine LinePlotter, :line_plotting_engine
20
- Format.build_interface_for LinePlotter, :plot
21
- end
22
-
23
- class SVG < Format::Plugin
24
-
25
- renderer :plot do
26
- h = '<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg">'+
27
- '<g stroke="black" stroke-width="1">'
28
-
29
- data.inject(h) { |s,r|
30
- s << "<line x1=\"#{r.x1}\" y1=\"#{r.y1}\"" <<
31
- " x2=\"#{r.x2}\" y2=\"#{r.y2}\" />"
32
- } << "</g></svg>"
33
- end
34
-
35
- plugin_name :svg
36
- register_on :line_plotting_engine
37
- end
38
-
39
- lines = [ [ [0,0], [0,100] ],
40
- [ [0,100], [100,100] ],
41
- [ [100,100], [100,0] ],
42
- [ [100,0], [0,0] ] ]
43
-
44
- a = Format.plot :plugin => :svg,
45
- :data => lines
46
- puts a
data/examples/long.txt DELETED
@@ -1,24 +0,0 @@
1
- TWO roads diverged in a yellow wood,
2
- And sorry I could not travel both
3
- And be one traveler, long I stood
4
- And looked down one as far as I could
5
- To where it bent in the undergrowth; 5
6
-
7
- Then took the other, as just as fair,
8
- And having perhaps the better claim,
9
- Because it was grassy and wanted wear;
10
- Though as for that the passing there
11
- Had worn them really about the same, 10
12
-
13
- And both that morning equally lay
14
- In leaves no step had trodden black.
15
- Oh, I kept the first for another day!
16
- Yet knowing how way leads on to way,
17
- I doubted if I should ever come back. 15
18
-
19
- I shall be telling this with a sigh
20
- Somewhere ages and ages hence:
21
- Two roads diverged in a wood, and I�
22
- I took the one less traveled by,
23
- And that has made all the difference. 20
24
-
@@ -1,24 +0,0 @@
1
- require "rubygems"
2
- require "ruport"
3
-
4
- # this shows how you can alter an existing plugin's rendering.
5
-
6
- include Ruport
7
-
8
- class Text < Ruport::Format::Plugin
9
- renderer :table do
10
- data.inject(rendered_field_names) { |s,r|
11
- s << r.to_a.join("()") << "\n"
12
- }
13
- end
14
-
15
- format_field_names do
16
- data.column_names.join("---") << "\n"
17
- end
18
-
19
- plugin_name :text
20
- register_on :table_engine
21
- end
22
-
23
- puts Format.table({ :data => [[1,2],[3,4]].to_table(:column_names =>%w[a b]),
24
- :plugin => :text })
data/examples/report.rb DELETED
@@ -1,35 +0,0 @@
1
- require "ruport"
2
- require "fileutils"
3
- class MyReport < Ruport::Report
4
- prepare do
5
- log_file "f.log"
6
- log "preparing report", :status => :info
7
- source :default,
8
- :dsn => "dbi:mysql:foo",
9
- :user => "root"
10
- mailer :default,
11
- :host => "mail.adelphia.net",
12
- :address => "gregory.t.brown@gmail.com"
13
- end
14
-
15
- generate do
16
- log "generated csv from query", :status => :info
17
- query "select * from bar", :as => :csv
18
- end
19
-
20
- cleanup do
21
- log "removing foo.csv", :status => :info
22
- FileUtils.rm("foo.csv")
23
- end
24
- end
25
-
26
- MyReport.run { |res|
27
- res.write "foo.csv";
28
- res.send_to("greg7224@gmail.com") do |mail|
29
- mail.subject = "Sample report"
30
- mail.attach "foo.csv"
31
- mail.text = <<-EOS
32
- this is a sample of sending an emailed report from within Ruport.
33
- EOS
34
- end
35
- }
@@ -1,32 +0,0 @@
1
- require "rubygems" rescue LoadError nil
2
- require "ruport"
3
-
4
- class SampleInvoiceReport < Ruport::Report
5
-
6
- include Invoice
7
-
8
- #optional
9
- prepare { self.file = "foo.pdf" }
10
-
11
- #mandatory
12
- generate {
13
- render_invoice do |i|
14
- i.company_info = "Foo Inc.\n42 Rock Street\nNew Haven, CT"
15
- i.customer_info = "Gregory Brown\ngregory.t.brown@gmail.com"
16
- i.order_info = "Order ID: 18180\nCustomer ID: 6291\n" +
17
- "Order Date: #{Date.today}"
18
- i.data = [["Rock Collection","$25.00"],
19
- ["Endless Sand Supply","$500.00"],
20
- ["Fire Filled Pit","$800.00"]].to_table %w[item price]
21
- i.comments = "Your Total: $1325.00 -- Thank you for your purchase!"
22
- i.title = "Invoice for Gregory"
23
- #i.active_plugin.paper = "A4"
24
- end
25
- }
26
-
27
- #optional
28
- cleanup { }
29
-
30
- end
31
-
32
- SampleInvoiceReport.run { |res| res.write }
@@ -1,15 +0,0 @@
1
- require "ruport"
2
-
3
- Ruport.configure do |conf|
4
- conf.mailer :default,
5
- :host => "mail.adelphia.net", :address => "gregory.t.brown@gmail.com"
6
- end
7
-
8
- mailer = Ruport::Mailer.new
9
-
10
- mailer.attach "README"
11
-
12
- mailer.deliver :to => "gregory.t.brown@gmail.com",
13
- :from => "gregory.t.brown@gmail.com",
14
- :subject => "Hey there",
15
- :text => "This is what you asked for"
@@ -1,20 +0,0 @@
1
- require "ruport"
2
- class SimpleTableShortcut < Ruport::Report
3
-
4
- prepare do
5
- log_file "foo.log"
6
- @table = table(%w[a b c]) do |t|
7
- t << [1,2,3]
8
- t << { "a" => 1, "c" => 9, "b" => 2 }
9
- end
10
- end
11
-
12
- generate do
13
- @table.to_csv
14
- end
15
-
16
- end
17
-
18
- SimpleTableShortcut.run(:tries => 3, :interval => 5) { |r|
19
- puts r.results
20
- }
data/examples/sql_erb.rb DELETED
@@ -1,20 +0,0 @@
1
- require "ruport"
2
- require "rubygems"
3
-
4
- class Foo < Ruport::Report
5
-
6
- SQL = "select * from <%= helper %>"
7
-
8
- prepare do
9
- source :default, :dsn => "dbi:mysql:foo", :user => "root"
10
- end
11
-
12
- generate do
13
- query(SQL)
14
- end
15
-
16
- def helper; "bar" end
17
-
18
- end
19
-
20
- Foo.run { |r| puts r.results }
data/examples/template.rb DELETED
@@ -1,15 +0,0 @@
1
- require "ruport"
2
-
3
- TEMPLATE = <<-EOS
4
-
5
- My HTML Table:
6
- <%= query "select * from bar", :as => :html %>
7
-
8
- EOS
9
-
10
- class MyReport < Ruport::Report
11
- prepare { source :default, :dsn => "dbi:mysql:foo", :user => "root" }
12
- generate { eval_template TEMPLATE }
13
- end
14
-
15
- MyReport.run { |r| puts r.results }
@@ -1,13 +0,0 @@
1
- require "ruport"
2
-
3
- class MyReport < Ruport::Report
4
- prepare {
5
- self.results = "Foo Bar Baz"
6
- text_processor(:replace_foo) { |r| r.gsub(/Foo/,"Ruport") }
7
- text_processor(:replace_bar) { |r| r.gsub(/Bar/,"Is") }
8
- text_processor(:replace_baz) { |r| r.gsub(/Baz/, "Cool!") }
9
- }
10
- generate {
11
- process_text results, :filters => [:replace_foo,:replace_bar,:replace_baz]
12
- }
13
- end
@@ -1,28 +0,0 @@
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
-
@@ -1,18 +0,0 @@
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
-
@@ -1,23 +0,0 @@
1
- module Ruport
2
- class Format::Engine
3
- class 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
-
@@ -1,54 +0,0 @@
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.empty? &&
10
- data.column_names && show_field_names)
11
- a = active_plugin.render_table
12
- end
13
-
14
- class << self
15
-
16
- def rewrite_column(key,&block)
17
- data.each { |r| r[key] = block[r] }
18
- end
19
-
20
- def num_cols
21
- data[0].to_a.length
22
- end
23
-
24
- def prune(limit=data[0].length)
25
- limit.times do |field|
26
- last = ""
27
- data.each_cons(2) { |l,e|
28
- next if field.nonzero? && e[field-1]
29
- last = l[field] if l[field]
30
- e[field] = nil if e[field] == last
31
- }
32
- end
33
- end
34
-
35
- attr_accessor :show_field_names
36
-
37
- private
38
-
39
- def build_field_names
40
- if active_plugin.respond_to?(:build_field_names)
41
- active_plugin.rendered_field_names =
42
- active_plugin.build_field_names
43
- end
44
- end
45
-
46
- end
47
-
48
- alias_engine Table, :table_engine
49
- Format.build_interface_for Table, :table
50
- self.show_field_names = true
51
- end
52
- end
53
- end
54
-
@@ -1,108 +0,0 @@
1
- class InvalidPluginError < RuntimeError; end
2
-
3
- module Ruport
4
- class Format::Engine
5
- require "forwardable"
6
- require "enumerator"
7
- class << self
8
-
9
- include Enumerable
10
- include MetaTools
11
- extend Forwardable
12
-
13
- attr_accessor :engine_classes
14
- attr_reader :plugin
15
- attr_reader :data
16
- attr_accessor :class_binding
17
- attr_reader :options
18
-
19
- def_delegator :@data, :each
20
- private :attribute, :attributes, :singleton_class, :action
21
-
22
- def renderer(&block)
23
- block = lambda { data } unless block_given?
24
- singleton_class.send(:define_method, :render,&block)
25
- end
26
-
27
- def alias_engine(klass,name)
28
- singleton_class.send(:define_method,:engine_name) { name }
29
- Format::Engine.engine_classes ||= {}
30
- Format::Engine.engine_classes[name] = klass
31
- end
32
-
33
- def data=(stuff)
34
- return unless stuff
35
- @data = stuff
36
- active_plugin.data = stuff.dup if active_plugin
37
- end
38
-
39
- def options=(opts)
40
- @options = opts
41
- active_plugin.options = options if active_plugin
42
- end
43
-
44
- def active_plugin
45
- return yield(@format_plugins[:current]) if block_given?
46
- @format_plugins[:current]
47
- end
48
-
49
- def plugin=(p)
50
- if @format_plugins[p].nil?
51
- raise(InvalidPluginError,
52
- 'The requested plugin and engine combination is invalid')
53
- end
54
-
55
- @plugin = p
56
- @format_plugins[:current] = @format_plugins[p].dup
57
- @format_plugins[:current].data = self.data.dup if self.data
58
- end
59
-
60
- def apply_erb
61
- active_plugin.data =
62
- ERB.new(active_plugin.data).result(class_binding || binding)
63
- end
64
-
65
- def render
66
- raise "No plugin specified" unless plugin
67
- active_plugin.data = data.dup if data
68
- if active_plugin.respond_to? :init_plugin_helper
69
- active_plugin.init_plugin_helper(self)
70
- end
71
- end
72
-
73
- def flush_data
74
- self.data = nil
75
- end
76
-
77
- def accept_format_plugin(klass)
78
- format_plugins[klass.plugin_name] = klass
79
- end
80
-
81
- private
82
-
83
- def format_plugins
84
- @format_plugins ||= {}
85
- end
86
-
87
- def plugin_names
88
- format_plugins.keys
89
- end
90
-
91
- def plugins
92
- format_plugins.values
93
- end
94
-
95
- def method_missing(id,*args)
96
- active_plugin.extend active_plugin.helpers[engine_name]
97
- super unless active_plugin.respond_to?("#{id}_helper")
98
- return active_plugin.send("#{id}_helper",self)
99
- end
100
-
101
- end
102
-
103
- private_class_method :new
104
- end
105
- end
106
-
107
- engines = %w[graph invoice table document]
108
- engines.each { |e| require "ruport/format/engine/#{e}" }
@@ -1,26 +0,0 @@
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
- if data.column_names.empty?
9
- ""
10
- else
11
- FasterCSV.generate { |csv| csv << data.column_names }
12
- end
13
- end
14
-
15
- renderer :table do
16
- rendered_field_names +
17
- FasterCSV.generate { |csv| data.each { |r| csv << r } }
18
- end
19
-
20
- plugin_name :csv
21
- register_on :table_engine
22
- end
23
- end
24
- end
25
-
26
-
@@ -1,32 +0,0 @@
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
- data.inject("\t<table>\n" + rendered_field_names) do |s,r|
11
- row = r.map { |e| e.to_s.empty? ? "&nbsp;" : e }
12
- classstr = defined?(r.tags) ?
13
- r.tags.inject("") {|cs,c| cs + " class='#{c}'" } : ""
14
- s + "\t\t<tr#{classstr}>\n\t\t\t<td#{classstr}>" +
15
- row.to_a.join("</td>\n\t\t\t<td#{classstr}>") +
16
- "</td>\n\t\t</tr>\n"
17
- end + "\t</table>"
18
- end
19
-
20
- format_field_names do
21
- "\t\t<tr>\n\t\t\t<th>" +
22
- data.column_names.join("</th>\n\t\t\t<th>") +
23
- "</th>\n\t\t</tr>\n"
24
- end
25
-
26
- plugin_name :html
27
- register_on :table_engine
28
- register_on :document_engine
29
-
30
- end
31
- end
32
- end
@@ -1,50 +0,0 @@
1
- module Ruport
2
- class Format::Plugin
3
- class LatexPlugin < Format::Plugin
4
-
5
- helper(:init_plugin) { |eng|
6
- @report_header = "\\documentclass[11pt]{article}\n"
7
- @report_header << "\\RequirePackage{lscape,longtable}\n"
8
- @report_header << "\\begin{document}\n"
9
-
10
- @report_footer = "\\end{document}\n"
11
- }
12
-
13
- renderer :table do
14
- self.options = {} if self.options.nil?
15
-
16
- @body = "\\begin{longtable}[c]{ "
17
- @data.column_names.each do
18
- @body << " p{2cm} "
19
- end
20
- @body << " }\n"
21
- @body << "\\hline\n"
22
- counter = 0
23
- @data.column_names.each do |t|
24
- @body << " & " unless counter == 0
25
- @body << "\\textsc{#{t}}"
26
- counter += 1
27
- end
28
- @body << "\\\\\n"
29
- @body << "\\hline\n"
30
- @body << "\\endhead\n"
31
- @body << "\\endfoot\n"
32
- @body << "\\hline\n"
33
- @data.each do |r|
34
- @body << r.data.join(" & ") + "\\\\\n"
35
- @body << "\\hline\n"
36
- end
37
- unless options[:caption].nil?
38
- @body << "\\caption[#{options[:caption]}]{#{options[:caption]}}\n"
39
- end
40
- @body << "\\end{longtable}\n"
41
-
42
- @report_header + @body + @report_footer
43
- end
44
-
45
- plugin_name :latex
46
- register_on :table_engine
47
-
48
- end
49
- end
50
- end