ruport 0.4.23 → 0.4.99

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