ruport 0.4.23 → 0.4.99

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 (71) hide show
  1. data/AUTHORS +16 -8
  2. data/CHANGELOG +30 -1
  3. data/README +144 -114
  4. data/Rakefile +12 -4
  5. data/TODO +4 -7
  6. data/bin/rope +21 -28
  7. data/examples/line_graph.rb +36 -0
  8. data/examples/sample_invoice_report.rb +1 -1
  9. data/examples/simple_graph.rb +8 -0
  10. data/lib/SVG/Graph/Bar.rb +137 -0
  11. data/lib/SVG/Graph/BarBase.rb +140 -0
  12. data/lib/SVG/Graph/BarHorizontal.rb +136 -0
  13. data/lib/SVG/Graph/Graph.rb +977 -0
  14. data/lib/SVG/Graph/Line.rb +444 -0
  15. data/lib/SVG/Graph/Pie.rb +394 -0
  16. data/lib/SVG/Graph/Plot.rb +494 -0
  17. data/lib/SVG/Graph/Schedule.rb +373 -0
  18. data/lib/SVG/Graph/TimeSeries.rb +241 -0
  19. data/lib/ruport.rb +2 -2
  20. data/lib/ruport/config.rb +47 -3
  21. data/lib/ruport/data/collection.rb +17 -1
  22. data/lib/ruport/data/record.rb +101 -8
  23. data/lib/ruport/data/set.rb +81 -2
  24. data/lib/ruport/data/set.rb.rej +147 -0
  25. data/lib/ruport/data/set.rb~ +73 -0
  26. data/lib/ruport/data/table.rb +127 -2
  27. data/lib/ruport/data/taggable.rb +21 -2
  28. data/lib/ruport/format.rb +36 -44
  29. data/lib/ruport/format/engine.rb +21 -1
  30. data/lib/ruport/format/plugin.rb +64 -1
  31. data/lib/ruport/mailer.rb +70 -36
  32. data/lib/ruport/meta_tools.rb +15 -6
  33. data/lib/ruport/query.rb +1 -1
  34. data/lib/ruport/rails/reportable.rb +23 -1
  35. data/lib/ruport/report.rb +11 -11
  36. data/lib/ruport/report/invoice.rb +16 -0
  37. data/lib/ruport/system_extensions.rb +3 -55
  38. data/test/{tc_database.rb → _test_database.rb} +0 -0
  39. data/test/{tc_config.rb → test_config.rb} +0 -0
  40. data/test/{tc_format.rb → test_format.rb} +1 -0
  41. data/test/{tc_format_engine.rb → test_format_engine.rb} +14 -2
  42. data/test/test_graph.rb +101 -0
  43. data/test/{tc_invoice.rb → test_invoice.rb} +7 -1
  44. data/test/test_mailer.rb +108 -0
  45. data/test/test_meta_tools.rb +14 -0
  46. data/test/{tc_plugin.rb → test_plugin.rb} +12 -1
  47. data/test/{tc_query.rb → test_query.rb} +0 -0
  48. data/test/{tc_record.rb → test_record.rb} +9 -0
  49. data/test/{tc_report.rb → test_report.rb} +2 -1
  50. data/test/{tc_ruport.rb → test_ruport.rb} +0 -0
  51. data/test/test_set.rb +118 -0
  52. data/test/test_set.rb.rej +16 -0
  53. data/test/{tc_set.rb → test_set.rb~} +17 -0
  54. data/test/{tc_sql_split.rb → test_sql_split.rb} +0 -0
  55. data/test/{tc_table.rb → test_table.rb} +15 -0
  56. data/test/{tc_taggable.rb → test_taggable.rb} +0 -0
  57. data/test/unit.log +361 -0
  58. metadata +52 -30
  59. data/examples/bar.pdf +0 -193
  60. data/examples/f.log +0 -5
  61. data/examples/foo.pdf +0 -193
  62. data/lib/ruport/format/document.rb +0 -78
  63. data/lib/ruport/format/open_node.rb +0 -38
  64. data/test/tc_data_row.rb +0 -132
  65. data/test/tc_data_set.rb +0 -386
  66. data/test/tc_document.rb +0 -42
  67. data/test/tc_element.rb +0 -18
  68. data/test/tc_page.rb +0 -42
  69. data/test/tc_section.rb +0 -45
  70. data/test/ts_all.rb +0 -12
  71. data/test/ts_format.rb +0 -7
@@ -0,0 +1,36 @@
1
+ $: << File.dirname(__FILE__) + "/../lib/"
2
+ require "ruport"
3
+
4
+ # Start with a Ruport::Table object. This could easily come from
5
+ # activerecord or any of the other ways to build a Table. See the ruport
6
+ # recipes book for some ideas
7
+ data = [[14.2, 14.4, 14.56, 14.87, 15.23, 15.58, 15.79]].to_table(%w[45000 35000 20000 15000 5000 400 17])
8
+
9
+ # initialize the graph with our table object
10
+ graph = Ruport::Format.graph_object :plugin => :svg, :data => data
11
+
12
+ # The SVG:Graph library accepts a wide range of options to style the resulting graph.
13
+ # These are set using a simple hash. The ones used below are approximately 1/3 of the available
14
+ # options.
15
+ options = {
16
+ :graph_style => :line,
17
+ :height => 500,
18
+ :width => 600,
19
+ :graph_title => "Global Average Temperature vs. Number of Pirates",
20
+ :show_graph_title => true,
21
+ :x_title => "Number of Pirates (approx.)",
22
+ :show_x_title => true,
23
+ :y_title => "Global Average Temperature (C)",
24
+ :show_y_title => true,
25
+ :key => false,
26
+ :min_scale_value => 13,
27
+ :scale_integers => true,
28
+ :no_css => true
29
+ }
30
+
31
+ # apply the options to the graph
32
+ graph.options = options
33
+
34
+ # render the graph and print it to stdout. To save the output to a file, try:
35
+ # ruby line_graph.rb > pirates.svg
36
+ puts graph.render
@@ -18,7 +18,7 @@ class SampleInvoiceReport < Ruport::Report
18
18
  i.data = [["Rock Collection","$25.00"],
19
19
  ["Endless Sand Supply","$500.00"],
20
20
  ["Fire Filled Pit","$800.00"]].to_table %w[item price]
21
- i.comments = "Be sure to visit our website at www.iheartruport.com"
21
+ i.comments = "Your Total: $1325.00 -- Thank you for your purchase!"
22
22
  i.title = "Invoice for Gregory"
23
23
  #i.active_plugin.paper = "A4"
24
24
  end
@@ -0,0 +1,8 @@
1
+ require "ruport"
2
+ data = [[1,4,7,9]].to_table(%w[a b c d])
3
+ data[0].tag "snickelfritz"
4
+ graph = Ruport::Format.graph_object :plugin => :svg,
5
+ :data => data
6
+ graph.options = {:graph_style => :line, :graph_title => "Worms on Steriods", :show_graph_title => true }
7
+ puts graph.render
8
+
@@ -0,0 +1,137 @@
1
+ require 'rexml/document'
2
+ require 'SVG/Graph/Graph'
3
+ require 'SVG/Graph/BarBase'
4
+
5
+ module SVG
6
+ module Graph
7
+ # === Create presentation quality SVG bar graphs easily
8
+ #
9
+ # = Synopsis
10
+ #
11
+ # require 'SVG/Graph/Bar'
12
+ #
13
+ # fields = %w(Jan Feb Mar);
14
+ # data_sales_02 = [12, 45, 21]
15
+ #
16
+ # graph = SVG::Graph::Bar.new(
17
+ # :height => 500,
18
+ # :width => 300,
19
+ # :fields => fields
20
+ # )
21
+ #
22
+ # graph.add_data(
23
+ # :data => data_sales_02,
24
+ # :title => 'Sales 2002'
25
+ # )
26
+ #
27
+ # print "Content-type: image/svg+xml\r\n\r\n"
28
+ # print graph.burn
29
+ #
30
+ # = Description
31
+ #
32
+ # This object aims to allow you to easily create high quality
33
+ # SVG[http://www.w3c.org/tr/svg bar graphs. You can either use the default
34
+ # style sheet or supply your own. Either way there are many options which
35
+ # can be configured to give you control over how the graph is generated -
36
+ # with or without a key, data elements at each point, title, subtitle etc.
37
+ #
38
+ # = Notes
39
+ #
40
+ # The default stylesheet handles upto 12 data sets, if you
41
+ # use more you must create your own stylesheet and add the
42
+ # additional settings for the extra data sets. You will know
43
+ # if you go over 12 data sets as they will have no style and
44
+ # be in black.
45
+ #
46
+ # = Examples
47
+ #
48
+ # * http://germane-software.com/repositories/public/SVG/test/test.rb
49
+ #
50
+ # = See also
51
+ #
52
+ # * SVG::Graph::Graph
53
+ # * SVG::Graph::BarHorizontal
54
+ # * SVG::Graph::Line
55
+ # * SVG::Graph::Pie
56
+ # * SVG::Graph::Plot
57
+ # * SVG::Graph::TimeSeries
58
+ class Bar < BarBase
59
+ include REXML
60
+
61
+ # See Graph::initialize and BarBase::set_defaults
62
+ def set_defaults
63
+ super
64
+ self.top_align = self.top_font = 1
65
+ end
66
+
67
+ protected
68
+
69
+ def get_x_labels
70
+ @config[:fields]
71
+ end
72
+
73
+ def get_y_labels
74
+ maxvalue = max_value
75
+ minvalue = min_value
76
+ range = maxvalue - minvalue
77
+
78
+ top_pad = range == 0 ? 10 : range / 20.0
79
+ scale_range = (maxvalue + top_pad) - minvalue
80
+
81
+ scale_division = scale_divisions || (scale_range / 10.0)
82
+
83
+ if scale_integers
84
+ scale_division = scale_division < 1 ? 1 : scale_division.round
85
+ end
86
+
87
+ rv = []
88
+ maxvalue = maxvalue%scale_division == 0 ?
89
+ maxvalue : maxvalue + scale_division
90
+ minvalue.step( maxvalue, scale_division ) {|v| rv << v}
91
+ return rv
92
+ end
93
+
94
+ def x_label_offset( width )
95
+ width / 2.0
96
+ end
97
+
98
+ def draw_data
99
+ fieldwidth = field_width
100
+ maxvalue = max_value
101
+ minvalue = min_value
102
+
103
+ fieldheight = (@graph_height.to_f - font_size*2*top_font) /
104
+ (get_y_labels.max - get_y_labels.min)
105
+ bargap = bar_gap ? (fieldwidth < 10 ? fieldwidth / 2 : 10) : 0
106
+
107
+ subbar_width = fieldwidth - bargap
108
+ subbar_width /= @data.length if stack == :side
109
+ x_mod = (@graph_width-bargap)/2 - (stack==:side ? subbar_width/2 : 0)
110
+ # Y1
111
+ p2 = @graph_height
112
+ # to X2
113
+ field_count = 0
114
+ @config[:fields].each_index { |i|
115
+ dataset_count = 0
116
+ for dataset in @data
117
+ # X1
118
+ p1 = (fieldwidth * field_count)
119
+ # to Y2
120
+ p3 = @graph_height - ((dataset[:data][i] - minvalue) * fieldheight)
121
+ p1 += subbar_width * dataset_count if stack == :side
122
+ @graph.add_element( "path", {
123
+ "class" => "fill#{dataset_count+1}",
124
+ "d" => "M#{p1} #{p2} V#{p3} h#{subbar_width} V#{p2} Z"
125
+ })
126
+ make_datapoint_text(
127
+ p1 + subbar_width/2.0,
128
+ p3 - 6,
129
+ dataset[:data][i].to_s)
130
+ dataset_count += 1
131
+ end
132
+ field_count += 1
133
+ }
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,140 @@
1
+ require 'rexml/document'
2
+ require 'SVG/Graph/Graph'
3
+
4
+ module SVG
5
+ module Graph
6
+ # = Synopsis
7
+ #
8
+ # A superclass for bar-style graphs. Do not attempt to instantiate
9
+ # directly; use one of the subclasses instead.
10
+ #
11
+ # = Author
12
+ #
13
+ # Sean E. Russell <serATgermaneHYPHENsoftwareDOTcom>
14
+ #
15
+ # Copyright 2004 Sean E. Russell
16
+ # This software is available under the Ruby license[LICENSE.txt]
17
+ #
18
+ class BarBase < SVG::Graph::Graph
19
+ # Ensures that :fields are provided in the configuration.
20
+ def initialize config
21
+ raise "fields was not supplied or is empty" unless config[:fields] &&
22
+ config[:fields].kind_of?(Array) &&
23
+ config[:fields].length > 0
24
+ super
25
+ end
26
+
27
+ # In addition to the defaults set in Graph::initialize, sets
28
+ # [bar_gap] true
29
+ # [stack] :overlap
30
+ def set_defaults
31
+ init_with( :bar_gap => true, :stack => :overlap )
32
+ end
33
+
34
+ # Whether to have a gap between the bars or not, default
35
+ # is true, set to false if you don't want gaps.
36
+ attr_accessor :bar_gap
37
+ # How to stack data sets. :overlap overlaps bars with
38
+ # transparent colors, :top stacks bars on top of one another,
39
+ # :side stacks the bars side-by-side. Defaults to :overlap.
40
+ attr_accessor :stack
41
+
42
+
43
+ protected
44
+
45
+ def max_value
46
+ return @data.collect{|x| x[:data].max}.max
47
+ end
48
+
49
+ def min_value
50
+ min = 0
51
+
52
+ if (min_scale_value.nil? == false) then
53
+ min = min_scale_value
54
+ else
55
+ min = @data.collect{|x| x[:data].min}.min
56
+ end
57
+
58
+ return min
59
+ end
60
+
61
+ def get_css
62
+ return <<EOL
63
+ /* default fill styles for multiple datasets (probably only use a single dataset on this graph though) */
64
+ .key1,.fill1{
65
+ fill: #ff0000;
66
+ fill-opacity: 0.5;
67
+ stroke: none;
68
+ stroke-width: 0.5px;
69
+ }
70
+ .key2,.fill2{
71
+ fill: #0000ff;
72
+ fill-opacity: 0.5;
73
+ stroke: none;
74
+ stroke-width: 1px;
75
+ }
76
+ .key3,.fill3{
77
+ fill: #00ff00;
78
+ fill-opacity: 0.5;
79
+ stroke: none;
80
+ stroke-width: 1px;
81
+ }
82
+ .key4,.fill4{
83
+ fill: #ffcc00;
84
+ fill-opacity: 0.5;
85
+ stroke: none;
86
+ stroke-width: 1px;
87
+ }
88
+ .key5,.fill5{
89
+ fill: #00ccff;
90
+ fill-opacity: 0.5;
91
+ stroke: none;
92
+ stroke-width: 1px;
93
+ }
94
+ .key6,.fill6{
95
+ fill: #ff00ff;
96
+ fill-opacity: 0.5;
97
+ stroke: none;
98
+ stroke-width: 1px;
99
+ }
100
+ .key7,.fill7{
101
+ fill: #00ffff;
102
+ fill-opacity: 0.5;
103
+ stroke: none;
104
+ stroke-width: 1px;
105
+ }
106
+ .key8,.fill8{
107
+ fill: #ffff00;
108
+ fill-opacity: 0.5;
109
+ stroke: none;
110
+ stroke-width: 1px;
111
+ }
112
+ .key9,.fill9{
113
+ fill: #cc6666;
114
+ fill-opacity: 0.5;
115
+ stroke: none;
116
+ stroke-width: 1px;
117
+ }
118
+ .key10,.fill10{
119
+ fill: #663399;
120
+ fill-opacity: 0.5;
121
+ stroke: none;
122
+ stroke-width: 1px;
123
+ }
124
+ .key11,.fill11{
125
+ fill: #339900;
126
+ fill-opacity: 0.5;
127
+ stroke: none;
128
+ stroke-width: 1px;
129
+ }
130
+ .key12,.fill12{
131
+ fill: #9966FF;
132
+ fill-opacity: 0.5;
133
+ stroke: none;
134
+ stroke-width: 1px;
135
+ }
136
+ EOL
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,136 @@
1
+ require 'rexml/document'
2
+ require 'SVG/Graph/BarBase'
3
+
4
+ module SVG
5
+ module Graph
6
+ # === Create presentation quality SVG horitonzal bar graphs easily
7
+ #
8
+ # = Synopsis
9
+ #
10
+ # require 'SVG/Graph/BarHorizontal'
11
+ #
12
+ # fields = %w(Jan Feb Mar)
13
+ # data_sales_02 = [12, 45, 21]
14
+ #
15
+ # graph = SVG::Graph::BarHorizontal.new({
16
+ # :height => 500,
17
+ # :width => 300,
18
+ # :fields => fields,
19
+ # })
20
+ #
21
+ # graph.add_data({
22
+ # :data => data_sales_02,
23
+ # :title => 'Sales 2002',
24
+ # })
25
+ #
26
+ # print "Content-type: image/svg+xml\r\n\r\n"
27
+ # print graph.burn
28
+ #
29
+ # = Description
30
+ #
31
+ # This object aims to allow you to easily create high quality
32
+ # SVG horitonzal bar graphs. You can either use the default style sheet
33
+ # or supply your own. Either way there are many options which can
34
+ # be configured to give you control over how the graph is
35
+ # generated - with or without a key, data elements at each point,
36
+ # title, subtitle etc.
37
+ #
38
+ # = Examples
39
+ #
40
+ # * http://germane-software.com/repositories/public/SVG/test/test.rb
41
+ #
42
+ # = See also
43
+ #
44
+ # * SVG::Graph::Graph
45
+ # * SVG::Graph::Bar
46
+ # * SVG::Graph::Line
47
+ # * SVG::Graph::Pie
48
+ # * SVG::Graph::Plot
49
+ # * SVG::Graph::TimeSeries
50
+ #
51
+ # == Author
52
+ #
53
+ # Sean E. Russell <serATgermaneHYPHENsoftwareDOTcom>
54
+ #
55
+ # Copyright 2004 Sean E. Russell
56
+ # This software is available under the Ruby license[LICENSE.txt]
57
+ #
58
+ class BarHorizontal < BarBase
59
+ # In addition to the defaults set in BarBase::set_defaults, sets
60
+ # [rotate_y_labels] true
61
+ # [show_x_guidelines] true
62
+ # [show_y_guidelines] false
63
+ def set_defaults
64
+ super
65
+ init_with(
66
+ :rotate_y_labels => true,
67
+ :show_x_guidelines => true,
68
+ :show_y_guidelines => false
69
+ )
70
+ self.right_align = self.right_font = 1
71
+ end
72
+
73
+ protected
74
+
75
+ def get_x_labels
76
+ maxvalue = max_value
77
+ minvalue = min_value
78
+ range = maxvalue - minvalue
79
+ top_pad = range == 0 ? 10 : range / 20.0
80
+ scale_range = (maxvalue + top_pad) - minvalue
81
+
82
+ scale_division = scale_divisions || (scale_range / 10.0)
83
+
84
+ if scale_integers
85
+ scale_division = scale_division < 1 ? 1 : scale_division.round
86
+ end
87
+
88
+ rv = []
89
+ maxvalue = maxvalue%scale_division == 0 ?
90
+ maxvalue : maxvalue + scale_division
91
+ minvalue.step( maxvalue, scale_division ) {|v| rv << v}
92
+ return rv
93
+ end
94
+
95
+ def get_y_labels
96
+ @config[:fields]
97
+ end
98
+
99
+ def y_label_offset( height )
100
+ height / -2.0
101
+ end
102
+
103
+ def draw_data
104
+ minvalue = min_value
105
+ fieldheight = field_height
106
+ fieldwidth = (@graph_width.to_f - font_size*2*right_font ) /
107
+ (get_x_labels.max - get_x_labels.min )
108
+ bargap = bar_gap ? (fieldheight < 10 ? fieldheight / 2 : 10) : 0
109
+
110
+ subbar_height = fieldheight - bargap
111
+ subbar_height /= @data.length if stack == :side
112
+
113
+ field_count = 1
114
+ y_mod = (subbar_height / 2) + (font_size / 2)
115
+ @config[:fields].each_index { |i|
116
+ dataset_count = 0
117
+ for dataset in @data
118
+ y = @graph_height - (fieldheight * field_count)
119
+ y += (subbar_height * dataset_count) if stack == :side
120
+ x = (dataset[:data][i] - minvalue) * fieldwidth
121
+
122
+ @graph.add_element( "path", {
123
+ "d" => "M0 #{y} H#{x} v#{subbar_height} H0 Z",
124
+ "class" => "fill#{dataset_count+1}"
125
+ })
126
+ make_datapoint_text(
127
+ x+5, y+y_mod, dataset[:data][i], "text-anchor: start; "
128
+ )
129
+ dataset_count += 1
130
+ end
131
+ field_count += 1
132
+ }
133
+ end
134
+ end
135
+ end
136
+ end