ruport 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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