ruport 0.4.17 → 0.4.19
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +22 -2
- data/Rakefile +4 -1
- data/lib/ruport.rb +17 -7
- data/lib/ruport/config.rb +39 -44
- data/lib/ruport/data/record.rb +7 -8
- data/lib/ruport/data/table.rb +39 -5
- data/lib/ruport/data_set.rb +13 -14
- data/lib/ruport/format.rb +10 -10
- data/lib/ruport/format/engine.rb +19 -16
- data/lib/ruport/format/open_node.rb +4 -4
- data/lib/ruport/format/plugin.rb +20 -17
- data/lib/ruport/meta_tools.rb +27 -4
- data/lib/ruport/query.rb +5 -5
- data/lib/ruport/rails/reportable.rb +7 -0
- data/lib/ruport/report.rb +16 -4
- data/test/tc_config.rb +0 -13
- data/test/tc_data_set.rb +3 -0
- data/test/tc_format.rb +1 -0
- data/test/tc_format_engine.rb +1 -0
- data/test/tc_plugin.rb +9 -0
- data/test/tc_ruport.rb +1 -1
- data/test/tc_table.rb +52 -0
- data/test/unit.log +1331 -0
- metadata +2 -2
data/lib/ruport/format/engine.rb
CHANGED
@@ -1,29 +1,30 @@
|
|
1
1
|
module Ruport
|
2
2
|
class Format::Engine
|
3
3
|
require "forwardable"
|
4
|
+
require "enumerator"
|
4
5
|
class << self
|
5
6
|
|
6
7
|
include Enumerable
|
7
8
|
include MetaTools
|
8
9
|
extend Forwardable
|
9
10
|
|
10
|
-
attr_accessor :
|
11
|
+
attr_accessor :engine_classes
|
11
12
|
attr_reader :plugin
|
12
13
|
attr_reader :data
|
13
|
-
attr_accessor :
|
14
|
+
attr_accessor :class_binding
|
14
15
|
attr_reader :options
|
15
16
|
|
16
17
|
def_delegator :@data, :each
|
17
|
-
private :attribute, :attributes, :
|
18
|
+
private :attribute, :attributes, :singleton_class, :action
|
18
19
|
|
19
20
|
def renderer(&block)
|
20
21
|
block = lambda { data } unless block_given?
|
21
|
-
|
22
|
+
singleton_class.send(:define_method, :render,&block)
|
22
23
|
end
|
23
24
|
|
24
25
|
def alias_engine(klass,name)
|
25
|
-
Format::Engine.
|
26
|
-
Format::Engine.
|
26
|
+
Format::Engine.engine_classes ||= {}
|
27
|
+
Format::Engine.engine_classes[name] = klass
|
27
28
|
end
|
28
29
|
|
29
30
|
def data=(data)
|
@@ -49,7 +50,7 @@ module Ruport
|
|
49
50
|
|
50
51
|
def apply_erb
|
51
52
|
active_plugin.data =
|
52
|
-
ERB.new(active_plugin.data).result(
|
53
|
+
ERB.new(active_plugin.data).result(class_binding || binding)
|
53
54
|
end
|
54
55
|
|
55
56
|
def render
|
@@ -57,7 +58,7 @@ module Ruport
|
|
57
58
|
raise "No data provided" unless data
|
58
59
|
active_plugin.data = data.dup
|
59
60
|
if active_plugin.respond_to? :init_plugin_helper
|
60
|
-
|
61
|
+
active_plugin.init_plugin_helper(self)
|
61
62
|
end
|
62
63
|
end
|
63
64
|
|
@@ -66,7 +67,7 @@ module Ruport
|
|
66
67
|
end
|
67
68
|
|
68
69
|
def accept_format_plugin(klass)
|
69
|
-
format_plugins[klass.
|
70
|
+
format_plugins[klass.plugin_name] = klass
|
70
71
|
end
|
71
72
|
|
72
73
|
private
|
@@ -83,12 +84,14 @@ module Ruport
|
|
83
84
|
format_plugins.values
|
84
85
|
end
|
85
86
|
|
86
|
-
def method_missing(id)
|
87
|
+
def method_missing(id,*args)
|
87
88
|
super unless active_plugin.respond_to?("#{id}_helper")
|
88
89
|
return active_plugin.send("#{id}_helper",self)
|
89
90
|
end
|
90
91
|
|
91
92
|
end
|
93
|
+
|
94
|
+
private_class_method :new
|
92
95
|
end
|
93
96
|
|
94
97
|
class Format::Engine::Table < Format::Engine
|
@@ -99,7 +102,7 @@ module Ruport
|
|
99
102
|
build_field_names if (data.respond_to?(:column_names) &&
|
100
103
|
data.column_names && show_field_names)
|
101
104
|
a = active_plugin.render_table
|
102
|
-
|
105
|
+
end
|
103
106
|
|
104
107
|
class << self
|
105
108
|
|
@@ -112,12 +115,12 @@ module Ruport
|
|
112
115
|
end
|
113
116
|
|
114
117
|
def prune(limit=data[0].length)
|
115
|
-
|
118
|
+
limit.times do |field|
|
116
119
|
last = ""
|
117
|
-
data.
|
118
|
-
next if
|
119
|
-
last =
|
120
|
-
|
120
|
+
data.each_cons(2) { |l,e|
|
121
|
+
next if field.nonzero? && e[field-1]
|
122
|
+
last = l[field] if l[field]
|
123
|
+
e[field] = nil if e[field] == last
|
121
124
|
}
|
122
125
|
end
|
123
126
|
end
|
@@ -11,12 +11,12 @@ module Ruport
|
|
11
11
|
@my_name = my_name
|
12
12
|
super(options)
|
13
13
|
self.name = name
|
14
|
-
|
15
|
-
|
14
|
+
send(@my_children_name) ||
|
15
|
+
send("#{@my_children_name}=".to_sym,{})
|
16
16
|
end
|
17
17
|
|
18
|
-
|
19
|
-
|
18
|
+
def each(&p)
|
19
|
+
send(@my_children_name).values.each(&p)
|
20
20
|
end
|
21
21
|
|
22
22
|
def add_child(klass,name,options={})
|
data/lib/ruport/format/plugin.rb
CHANGED
@@ -9,33 +9,33 @@ module Ruport
|
|
9
9
|
include MetaTools
|
10
10
|
|
11
11
|
def helper(name,&block)
|
12
|
-
|
12
|
+
singleton_class.send( :define_method, "#{name}_helper", &block )
|
13
13
|
end
|
14
14
|
|
15
|
-
private :
|
15
|
+
private :singleton_class, :attribute, :attributes, :action
|
16
16
|
|
17
17
|
def plugin_name(name=nil); @name ||= name; end
|
18
18
|
|
19
|
-
def format_name
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
19
|
+
#def format_name
|
20
|
+
# pattern = /Ruport::Format|Plugin/
|
21
|
+
# @name ||=
|
22
|
+
# self.name.gsub(pattern,"").downcase.delete(":").to_sym
|
23
|
+
#end
|
24
24
|
|
25
25
|
def renderer(render_type,&block)
|
26
26
|
m = "render_#{render_type}".to_sym
|
27
|
-
block
|
28
|
-
|
27
|
+
block ||= lambda { data }
|
28
|
+
singleton_class.send(:define_method, m, &block)
|
29
29
|
end
|
30
30
|
|
31
31
|
def format_field_names(&block)
|
32
|
-
|
32
|
+
singleton_class.send( :define_method, :build_field_names, &block)
|
33
33
|
end
|
34
34
|
|
35
35
|
def register_on(klass)
|
36
36
|
|
37
37
|
if klass.kind_of? Symbol
|
38
|
-
klass = Format::Engine.
|
38
|
+
klass = Format::Engine.engine_classes[klass]
|
39
39
|
end
|
40
40
|
|
41
41
|
klass.accept_format_plugin(self)
|
@@ -65,7 +65,8 @@ module Ruport
|
|
65
65
|
rendered_field_names +
|
66
66
|
FasterCSV.generate { |csv| data.each { |r| csv << r } }
|
67
67
|
end
|
68
|
-
|
68
|
+
|
69
|
+
plugin_name :csv
|
69
70
|
register_on :table_engine
|
70
71
|
end
|
71
72
|
|
@@ -91,9 +92,9 @@ module Ruport
|
|
91
92
|
|
92
93
|
width = self.right_margin || SystemExtensions.terminal_width
|
93
94
|
|
94
|
-
a.
|
95
|
-
r.gsub!(/\A.{#{width},}/) { |m| m[0,width-2]
|
96
|
-
}.join
|
95
|
+
a.to_a.each { |r|
|
96
|
+
r.gsub!(/\A.{#{width+1},}/) { |m| m[0,width-2] + ">>" }
|
97
|
+
}.join
|
97
98
|
end
|
98
99
|
|
99
100
|
format_field_names do
|
@@ -129,7 +130,7 @@ module Ruport
|
|
129
130
|
end
|
130
131
|
|
131
132
|
attribute :right_margin
|
132
|
-
|
133
|
+
plugin_name :text
|
133
134
|
register_on :table_engine
|
134
135
|
register_on :document_engine
|
135
136
|
end
|
@@ -154,7 +155,8 @@ module Ruport
|
|
154
155
|
end
|
155
156
|
|
156
157
|
format_field_names { data.column_names }
|
157
|
-
|
158
|
+
|
159
|
+
plugin_name :pdf
|
158
160
|
register_on :table_engine
|
159
161
|
end
|
160
162
|
|
@@ -176,6 +178,7 @@ module Ruport
|
|
176
178
|
s = "|_." + data.column_names.join(" |_.") + "|\n"
|
177
179
|
end
|
178
180
|
|
181
|
+
plugin_name :html
|
179
182
|
register_on :table_engine
|
180
183
|
register_on :document_engine
|
181
184
|
|
data/lib/ruport/meta_tools.rb
CHANGED
@@ -1,19 +1,42 @@
|
|
1
1
|
module Ruport
|
2
|
+
# This module provides a few tools for doing some manipulations of the
|
3
|
+
# eigenclass on an object. These are used in the implementation of Ruport's
|
4
|
+
# formatting system, and might be helpful for other things.
|
5
|
+
#
|
2
6
|
module MetaTools
|
3
|
-
|
4
|
-
|
7
|
+
# allows you to define an attribute accessor on the singleton_class.
|
8
|
+
#
|
9
|
+
# Example:
|
10
|
+
#
|
11
|
+
# class A
|
12
|
+
# class << self; include MetaTools; end
|
13
|
+
#
|
14
|
+
# attribute :foo
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# A.foo #=> nil
|
18
|
+
# A.foo = 7 #=> 7
|
5
19
|
def attribute(sym,value = nil)
|
6
|
-
|
20
|
+
singleton_class.send(:attr_accessor, sym )
|
7
21
|
self.send("#{sym}=",value)
|
8
22
|
end
|
9
23
|
|
24
|
+
# same as accessor, but takes an array of attributes
|
25
|
+
#
|
26
|
+
# e.g. attributes [:foo,:bar,:baz]
|
10
27
|
def attributes(syms)
|
11
28
|
syms.each { |s| attribute s }
|
12
29
|
end
|
13
30
|
|
14
31
|
def action(name,&block)
|
15
|
-
|
32
|
+
singleton_class.send(:define_method, name, &block)
|
16
33
|
end
|
17
34
|
end
|
18
35
|
end
|
19
36
|
|
37
|
+
class Module
|
38
|
+
|
39
|
+
# provides the singleton_class object
|
40
|
+
def singleton_class; (class << self; self; end); end
|
41
|
+
|
42
|
+
end
|
data/lib/ruport/query.rb
CHANGED
@@ -99,7 +99,7 @@ module Ruport
|
|
99
99
|
|
100
100
|
# Standard each iterator, iterates through result set row by row.
|
101
101
|
def each(&action)
|
102
|
-
Ruport
|
102
|
+
Ruport.log(
|
103
103
|
"no block given!", :status => :fatal,
|
104
104
|
:level => :log_only, :exception => LocalJumpError
|
105
105
|
) unless action
|
@@ -115,7 +115,7 @@ module Ruport
|
|
115
115
|
|
116
116
|
# clears the contents of the cache
|
117
117
|
def clear_cache
|
118
|
-
@
|
118
|
+
@cached_data = nil
|
119
119
|
end
|
120
120
|
|
121
121
|
# clears the contents of the cache and then runs the query, filling the
|
@@ -179,19 +179,19 @@ module Ruport
|
|
179
179
|
|
180
180
|
def load_file( query_file )
|
181
181
|
begin; File.read( query_file ).strip ; rescue
|
182
|
-
Ruport
|
182
|
+
Ruport.log "Could not open #{query_file}",
|
183
183
|
:status => :fatal, :exception => LoadError
|
184
184
|
end
|
185
185
|
end
|
186
186
|
|
187
|
-
def fetch
|
187
|
+
def fetch
|
188
188
|
data = nil
|
189
189
|
if @cache_enabled and @cached_data
|
190
190
|
data = @cached_data
|
191
191
|
else
|
192
192
|
@statements.each { |query_text| data = query_data( query_text ) }
|
193
193
|
end
|
194
|
-
data.each { |r|
|
194
|
+
data.each { |r| yield(r) } if block_given? ; data
|
195
195
|
@cached_data = data if @cache_enabled
|
196
196
|
return data
|
197
197
|
end
|
@@ -1,17 +1,23 @@
|
|
1
1
|
module Ruport
|
2
|
+
|
2
3
|
module Reportable
|
4
|
+
|
3
5
|
def formatted_table(type,options={})
|
4
6
|
to_ds(:find => options[:find],:columns => options[:columns]).as(type){ |e|
|
5
7
|
yield(e) if block_given?
|
6
8
|
}
|
7
9
|
end
|
10
|
+
|
8
11
|
def to_ds(options={})
|
9
12
|
options[:columns] ||= column_names
|
10
13
|
find(:all,options[:find]).
|
11
14
|
to_ds(column_names).select_columns(*options[:columns])
|
12
15
|
end
|
16
|
+
|
13
17
|
end
|
18
|
+
|
14
19
|
class DataSet
|
20
|
+
|
15
21
|
alias_method :old_append, :<<
|
16
22
|
def <<( stuff, filler=@default )
|
17
23
|
if stuff.kind_of?(ActiveRecord::Base)
|
@@ -20,6 +26,7 @@ module Ruport
|
|
20
26
|
old_append(stuff,filler)
|
21
27
|
end
|
22
28
|
end
|
29
|
+
|
23
30
|
end
|
24
31
|
end
|
25
32
|
|
data/lib/ruport/report.rb
CHANGED
@@ -83,7 +83,8 @@ module Ruport
|
|
83
83
|
def initialize( source_name=:default, mailer_name=:default )
|
84
84
|
use_source source_name
|
85
85
|
use_mailer mailer_name
|
86
|
-
@report_name =
|
86
|
+
@report_name = ""
|
87
|
+
@results = ""
|
87
88
|
@file = nil
|
88
89
|
end
|
89
90
|
|
@@ -100,7 +101,6 @@ module Ruport
|
|
100
101
|
# Preserved for backwards compabilitity, please do not use this.
|
101
102
|
alias_method :report=, :results=
|
102
103
|
|
103
|
-
|
104
104
|
# Simplified interface to Ruport::Query
|
105
105
|
#
|
106
106
|
# === Can read SQL statements from file or string
|
@@ -157,7 +157,7 @@ module Ruport
|
|
157
157
|
# This code will be evaluated in the context of the instance on which it is
|
158
158
|
# called.
|
159
159
|
def eval_template( code, filename=nil )
|
160
|
-
filename =~ /\.rb/ ? eval(code) : ERB.new(code, 0, "%").
|
160
|
+
filename =~ /\.rb/ ? eval(code) : ERB.new(code, 0, "%").result(binding)
|
161
161
|
end
|
162
162
|
|
163
163
|
# sets the active source to the Ruport::Config source requested by label.
|
@@ -261,6 +261,19 @@ module Ruport
|
|
261
261
|
def run(&block)
|
262
262
|
self.class.run(self,&block)
|
263
263
|
end
|
264
|
+
|
265
|
+
def load_csv(file,options={})
|
266
|
+
case options[:as]
|
267
|
+
when :table
|
268
|
+
Data::Table.load(file)
|
269
|
+
when :array
|
270
|
+
a = []
|
271
|
+
Data::Table.load(file) { |s,r| a << r }
|
272
|
+
return a
|
273
|
+
else
|
274
|
+
DataSet.load(file)
|
275
|
+
end
|
276
|
+
end
|
264
277
|
|
265
278
|
# Preserved for backwards compatibility, please do not use this.
|
266
279
|
alias_method :generate_report, :run
|
@@ -271,7 +284,6 @@ module Ruport
|
|
271
284
|
# Creates a new Mailer and sets the <tt>to</tt> attribute to the addresses
|
272
285
|
# specified. Yields a Mailer object, which can be modified before delivery.
|
273
286
|
#
|
274
|
-
# By default, this will
|
275
287
|
def send_to(adds)
|
276
288
|
m = Mailer.new
|
277
289
|
m.to = adds
|
data/test/tc_config.rb
CHANGED
@@ -4,7 +4,6 @@ require "ruport"
|
|
4
4
|
class TestConfiguration < Test::Unit::TestCase
|
5
5
|
|
6
6
|
def setup
|
7
|
-
Ruport::Config.init!
|
8
7
|
Ruport::Config.log_file = "test/unit.log"
|
9
8
|
end
|
10
9
|
|
@@ -16,14 +15,6 @@ class TestConfiguration < Test::Unit::TestCase
|
|
16
15
|
assert_equal(nil, Ruport::Config.default_mailer)
|
17
16
|
end
|
18
17
|
|
19
|
-
def test_init
|
20
|
-
Ruport::Config.init!
|
21
|
-
assert_equal({}, Ruport::Config.sources)
|
22
|
-
assert_equal({}, Ruport::Config.mailers)
|
23
|
-
assert_equal(nil,Ruport::Config.logger)
|
24
|
-
assert_equal(false,Ruport::Config.paranoid?)
|
25
|
-
end
|
26
|
-
|
27
18
|
def test_missing_dsn
|
28
19
|
assert_raise(ArgumentError) {
|
29
20
|
Ruport::Config.source :foo, :user => "root", :password => "fff"
|
@@ -68,10 +59,6 @@ class TestConfiguration < Test::Unit::TestCase
|
|
68
59
|
# We have a logger running now, dont we?
|
69
60
|
assert(Ruport::Config.logger.kind_of?(Logger))
|
70
61
|
|
71
|
-
# If we could go back in time and never define one...
|
72
|
-
Ruport::Config.init!
|
73
|
-
assert Ruport::Config.logger.nil?
|
74
|
-
|
75
62
|
# And then we change are mind again. Back logging?
|
76
63
|
Ruport::Config.log_file = "test/unit.log"
|
77
64
|
assert(Ruport::Config.logger.kind_of?(Logger))
|
data/test/tc_data_set.rb
CHANGED
data/test/tc_format.rb
CHANGED