object-proxy 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/Gemfile.lock +3 -6
- data/README.md +5 -0
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/object-proxy.rb +150 -39
- data/object-proxy.gemspec +6 -6
- data/test +49 -3
- metadata +34 -14
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -2,13 +2,10 @@ GEM
|
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
4
|
git (1.2.5)
|
5
|
-
hash-utils (
|
5
|
+
hash-utils (2.0.0)
|
6
6
|
ruby-version
|
7
|
-
|
8
|
-
bundler (~> 1.0)
|
7
|
+
jeweler2 (2.0.9)
|
9
8
|
git (>= 1.2.5)
|
10
|
-
rake
|
11
|
-
rake (0.9.2)
|
12
9
|
riot (0.12.5)
|
13
10
|
rr
|
14
11
|
rr (1.0.4)
|
@@ -20,5 +17,5 @@ PLATFORMS
|
|
20
17
|
DEPENDENCIES
|
21
18
|
bundler (>= 1.0.0)
|
22
19
|
hash-utils (>= 0.12.1)
|
23
|
-
|
20
|
+
jeweler2 (>= 2.0.0)
|
24
21
|
riot (>= 0.12.1)
|
data/README.md
CHANGED
@@ -8,6 +8,11 @@ where isn't possible to derive them as homogenic functional units or
|
|
8
8
|
where it's simply impractical to derive them. Provides four base
|
9
9
|
proxy types.
|
10
10
|
|
11
|
+
*In all examples, object instance proxying is used, but both class objects
|
12
|
+
and object instances proxying are supported. Simply give object instance
|
13
|
+
instead of class object to the constructor. Wrapped object instance will
|
14
|
+
be returned.*
|
15
|
+
|
11
16
|
### Standard Proxy
|
12
17
|
Works as intermediate layer between caller and called. Allows to invoke
|
13
18
|
an handler both before method call and adjust its arguments and after
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/lib/object-proxy.rb
CHANGED
@@ -14,14 +14,24 @@ module ObjectProxy
|
|
14
14
|
# Creates proxy object. "Proxy object" means, it calls handler
|
15
15
|
# if defined before and after each method call.
|
16
16
|
#
|
17
|
-
# @param [Object] object proxied object
|
18
|
-
# @return [Class] anonymous proxy class with before and after
|
17
|
+
# @param [Object, Class] object proxied object or class
|
18
|
+
# @return [Object, Class] anonymous proxy instance or class with before and after
|
19
19
|
# handlers functionality
|
20
20
|
# @since 0.2.0
|
21
21
|
#
|
22
22
|
|
23
23
|
def self.proxy(object)
|
24
|
-
|
24
|
+
|
25
|
+
### Takes class object
|
26
|
+
|
27
|
+
_class = object
|
28
|
+
if not _class.kind_of? Class
|
29
|
+
_class = object.class
|
30
|
+
end
|
31
|
+
|
32
|
+
### Defines class
|
33
|
+
|
34
|
+
cls = Class::new(_class)
|
25
35
|
cls.instance_eval do
|
26
36
|
|
27
37
|
# Eviscerates instances methods and replace them by
|
@@ -51,9 +61,16 @@ module ObjectProxy
|
|
51
61
|
end
|
52
62
|
|
53
63
|
# Adds constructor
|
54
|
-
|
55
|
-
|
56
|
-
|
64
|
+
if object.kind_of? Class
|
65
|
+
define_method :initialize do |*args, &block|
|
66
|
+
@handlers = { }
|
67
|
+
@wrapped = _class::new(*args, &block)
|
68
|
+
end
|
69
|
+
else
|
70
|
+
define_method :initialize do |*args, &block|
|
71
|
+
@handlers = { }
|
72
|
+
@wrapped = object
|
73
|
+
end
|
57
74
|
end
|
58
75
|
|
59
76
|
# Event handlers assigning interceptor
|
@@ -68,16 +85,26 @@ module ObjectProxy
|
|
68
85
|
@handlers[name] = block
|
69
86
|
end
|
70
87
|
|
88
|
+
# Wrapped accessor
|
89
|
+
|
71
90
|
attr_accessor :wrapped
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
if object.kind_of? Class
|
95
|
+
result = cls
|
96
|
+
else
|
97
|
+
result = cls::new
|
72
98
|
end
|
73
99
|
|
74
|
-
return
|
100
|
+
return result
|
75
101
|
end
|
76
102
|
|
77
103
|
##
|
78
104
|
# Alias for +ObjectProxy::proxy+.
|
79
105
|
#
|
80
|
-
# @
|
106
|
+
# @param [Object, Class] object
|
107
|
+
# @return [Object, Class]
|
81
108
|
# @since 0.2.0
|
82
109
|
#
|
83
110
|
|
@@ -88,7 +115,8 @@ module ObjectProxy
|
|
88
115
|
##
|
89
116
|
# Alias for +ObjectProxy::proxy+.
|
90
117
|
#
|
91
|
-
# @
|
118
|
+
# @param [Object, Class] object
|
119
|
+
# @return [Object, Class]
|
92
120
|
# @since 0.1.0
|
93
121
|
#
|
94
122
|
|
@@ -140,21 +168,31 @@ module ObjectProxy
|
|
140
168
|
#
|
141
169
|
# Also doesn't support customizing the arguments or result.
|
142
170
|
#
|
143
|
-
# @param [Object] object proxied object
|
144
|
-
# @return [Class] anonymous proxy class with before and after
|
171
|
+
# @param [Object, Class] object proxied object or class
|
172
|
+
# @return [Object, Class] anonymous proxy instance or class with before and after
|
145
173
|
# handlers functionality
|
146
174
|
# @since 0.2.0
|
147
175
|
#
|
148
176
|
|
149
177
|
def self.track(object)
|
150
|
-
|
151
|
-
|
178
|
+
|
179
|
+
### Takes class object
|
180
|
+
|
181
|
+
_class = object
|
182
|
+
if not _class.kind_of? Class
|
183
|
+
_class = object.class
|
184
|
+
end
|
185
|
+
|
186
|
+
### Defines class
|
187
|
+
|
188
|
+
cls = Class::new(_class)
|
189
|
+
cls.class_eval do
|
152
190
|
|
153
191
|
# Eviscerates instances methods and replace them by
|
154
192
|
# +#on_method+ invoker
|
155
193
|
|
156
194
|
public_instance_methods.each do |method|
|
157
|
-
if not method.in? [:object_id, :__send__]
|
195
|
+
if not method.in? [:object_id, :__send__, :class]
|
158
196
|
define_method method do |*args, &block|
|
159
197
|
if not @before_call.nil?
|
160
198
|
@before_call.call(method, args, block)
|
@@ -173,10 +211,14 @@ module ObjectProxy
|
|
173
211
|
|
174
212
|
# Adds constructor
|
175
213
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
214
|
+
if object.kind_of? Class
|
215
|
+
define_method :initialize do |*args, &block|
|
216
|
+
@wrapped = _class::new(*args, &block)
|
217
|
+
end
|
218
|
+
else
|
219
|
+
define_method :initialize do |*args, &block|
|
220
|
+
@wrapped = object
|
221
|
+
end
|
180
222
|
end
|
181
223
|
|
182
224
|
# Defines handler assigners
|
@@ -189,9 +231,19 @@ module ObjectProxy
|
|
189
231
|
@after_call = block
|
190
232
|
end
|
191
233
|
|
234
|
+
# Wrapped accessor
|
235
|
+
|
236
|
+
attr_accessor :wrapped
|
237
|
+
|
238
|
+
end
|
239
|
+
|
240
|
+
if object.kind_of? Class
|
241
|
+
result = cls
|
242
|
+
else
|
243
|
+
result = cls::new
|
192
244
|
end
|
193
245
|
|
194
|
-
return
|
246
|
+
return result
|
195
247
|
end
|
196
248
|
|
197
249
|
##
|
@@ -199,50 +251,109 @@ module ObjectProxy
|
|
199
251
|
# and forwards them to +#method_call+ handler which calls wrapped object
|
200
252
|
# by default, but can be overriden, so calls can be controlled.
|
201
253
|
#
|
202
|
-
# @param [Object] object proxied object
|
203
|
-
# @
|
254
|
+
# @param [Object, Class] object proxied object or class
|
255
|
+
# @param [Proc] block default +#method_call+ handler for whole class
|
256
|
+
# @return [Object, Class] anonymous proxy instance or class
|
204
257
|
# @since 0.2.0
|
205
258
|
#
|
259
|
+
|
260
|
+
def self.catch(object, &block)
|
261
|
+
|
262
|
+
### Takes class object
|
263
|
+
|
264
|
+
_class = object
|
265
|
+
if not _class.kind_of? Class
|
266
|
+
_class = object.class
|
267
|
+
end
|
268
|
+
|
269
|
+
### Defines class
|
270
|
+
|
271
|
+
cls = Class::new(_class)
|
272
|
+
cls.class_eval do
|
206
273
|
|
207
|
-
def self.catch(object)
|
208
|
-
cls = Class::new(object.class)
|
209
|
-
cls.instance_eval do
|
210
|
-
|
211
274
|
# Eviscerates instances methods and replace them by
|
212
275
|
# +#handle_call+ invoker
|
213
276
|
|
214
277
|
public_instance_methods.each do |method|
|
215
|
-
if not method.in? [:object_id, :__send__]
|
278
|
+
if not method.in? [:object_id, :__send__, :class]
|
216
279
|
define_method method do |*args, &block|
|
217
|
-
|
280
|
+
self.method_call.call(method, args, block)
|
218
281
|
end
|
219
282
|
end
|
220
283
|
end
|
221
284
|
|
222
285
|
# Adds constructor
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
286
|
+
|
287
|
+
if not object.kind_of? Class
|
288
|
+
define_method :initialize do |&block|
|
289
|
+
@wrapped = object
|
290
|
+
|
291
|
+
if not block.nil?
|
292
|
+
@method_call = block
|
293
|
+
else
|
294
|
+
@method_call = cls.class_variable_get(:@@method_call)
|
295
|
+
end
|
296
|
+
|
297
|
+
if @method_call.nil?
|
298
|
+
@method_call = Proc::new do |method, args, block|
|
299
|
+
@wrapped.send(method, *args, &block)
|
300
|
+
end
|
301
|
+
end
|
228
302
|
end
|
303
|
+
else
|
304
|
+
define_method :initialize do |*args, &block|
|
305
|
+
@wrapped = _class::new(*args, &block)
|
306
|
+
|
307
|
+
ic = cls.class_variable_get(:@@instance_created)
|
308
|
+
if not ic.nil?
|
309
|
+
ic.call(self)
|
310
|
+
end
|
311
|
+
end
|
229
312
|
end
|
313
|
+
|
314
|
+
# Defines handler assigners
|
230
315
|
|
231
|
-
|
316
|
+
class_variable_set(:@@method_call, nil)
|
317
|
+
define_singleton_method :method_call do |&block|
|
318
|
+
cls.class_variable_set(:@@method_call, block)
|
319
|
+
end
|
232
320
|
|
233
|
-
|
234
|
-
|
321
|
+
class_variable_set(:@@instance_created, nil)
|
322
|
+
define_singleton_method :instance_created do |&block|
|
323
|
+
cls.class_variable_set(:@@instance_created, block)
|
235
324
|
end
|
236
325
|
|
237
|
-
#
|
326
|
+
# Sets up accessors and default handler
|
327
|
+
attr_accessor :wrapped
|
238
328
|
|
239
|
-
define_method :
|
240
|
-
|
329
|
+
define_method :method_call do |&block|
|
330
|
+
if not block.nil? # set
|
331
|
+
@method_call = block
|
332
|
+
else # get
|
333
|
+
result = @method_call
|
334
|
+
|
335
|
+
if result.nil?
|
336
|
+
result = Proc::new do |method, args, block|
|
337
|
+
@wrapped.send(method, *args, &block)
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
return result
|
342
|
+
end
|
241
343
|
end
|
344
|
+
|
345
|
+
attr_writer :method_call
|
242
346
|
|
243
347
|
end
|
244
348
|
|
245
|
-
|
349
|
+
if object.kind_of? Class
|
350
|
+
result = cls
|
351
|
+
else
|
352
|
+
result = cls::new
|
353
|
+
end
|
354
|
+
|
355
|
+
return result
|
356
|
+
|
246
357
|
end
|
247
358
|
end
|
248
359
|
|
data/object-proxy.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "object-proxy"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Martin Koz\u{e1}k"]
|
12
|
-
s.date = "
|
12
|
+
s.date = "2012-05-24"
|
13
13
|
s.email = "martinkozak@martinkozak.net"
|
14
14
|
s.extra_rdoc_files = [
|
15
15
|
"LICENSE.txt",
|
@@ -30,7 +30,7 @@ Gem::Specification.new do |s|
|
|
30
30
|
s.homepage = "http://github.com/martinkozak/object-proxy"
|
31
31
|
s.licenses = ["MIT"]
|
32
32
|
s.require_paths = ["lib"]
|
33
|
-
s.rubygems_version = "1.8.
|
33
|
+
s.rubygems_version = "1.8.24"
|
34
34
|
s.summary = "Provides collection of four proxy objects intended for intercepting calls to instance methods. Works as intermediate layer between caller and called. Allows to invoke an handler both before method call and adjust its arguments and after call and post-proccess result. Aimed as tool for instant adapting the complex objects without complete deriving and extending whole classes in cases, where isn't possible to derive them as homogenic functional units or where it's simply impractical to derive them."
|
35
35
|
|
36
36
|
if s.respond_to? :specification_version then
|
@@ -39,18 +39,18 @@ Gem::Specification.new do |s|
|
|
39
39
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
40
40
|
s.add_runtime_dependency(%q<hash-utils>, [">= 0.12.1"])
|
41
41
|
s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
|
42
|
-
s.add_development_dependency(%q<
|
42
|
+
s.add_development_dependency(%q<jeweler2>, [">= 2.0.0"])
|
43
43
|
s.add_development_dependency(%q<riot>, [">= 0.12.1"])
|
44
44
|
else
|
45
45
|
s.add_dependency(%q<hash-utils>, [">= 0.12.1"])
|
46
46
|
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
47
|
-
s.add_dependency(%q<
|
47
|
+
s.add_dependency(%q<jeweler2>, [">= 2.0.0"])
|
48
48
|
s.add_dependency(%q<riot>, [">= 0.12.1"])
|
49
49
|
end
|
50
50
|
else
|
51
51
|
s.add_dependency(%q<hash-utils>, [">= 0.12.1"])
|
52
52
|
s.add_dependency(%q<bundler>, [">= 1.0.0"])
|
53
|
-
s.add_dependency(%q<
|
53
|
+
s.add_dependency(%q<jeweler2>, [">= 2.0.0"])
|
54
54
|
s.add_dependency(%q<riot>, [">= 0.12.1"])
|
55
55
|
end
|
56
56
|
end
|
data/test
CHANGED
@@ -6,7 +6,7 @@ $:.push("./lib")
|
|
6
6
|
require "object-proxy"
|
7
7
|
require "riot"
|
8
8
|
|
9
|
-
context "ObjectProxy" do
|
9
|
+
context "ObjectProxy (instances)" do
|
10
10
|
asserts("#create") do
|
11
11
|
s = OP["a,b,c,d"]
|
12
12
|
|
@@ -21,6 +21,52 @@ context "ObjectProxy" do
|
|
21
21
|
|
22
22
|
(s << ",1,2,3" == "alfa beta") and (s == "a,b,c,d,A,B,C")
|
23
23
|
end
|
24
|
+
asserts("#track") do
|
25
|
+
log = [ ]
|
26
|
+
s = OP::track("a,b,c,d")
|
27
|
+
s.before_call do |name|
|
28
|
+
log << name
|
29
|
+
end
|
30
|
+
s.after_call do |name|
|
31
|
+
log << name
|
32
|
+
end
|
33
|
+
s.gsub!(",", "")
|
34
|
+
|
35
|
+
(log == [:gsub!, :gsub!]) and (s == "abcd")
|
36
|
+
end
|
37
|
+
asserts("#catch") do
|
38
|
+
s = OP::catch("alfa")
|
39
|
+
log = [ ]
|
40
|
+
|
41
|
+
s.method_call do |name, args, block|
|
42
|
+
if name == :to_s
|
43
|
+
log << name
|
44
|
+
s.wrapped.send(name, *args, &block)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
s.replace("beta")
|
49
|
+
s.to_s
|
50
|
+
|
51
|
+
(log == [:to_s]) and (s.to_s == "alfa")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "ObjectProxy (classes)" do
|
56
|
+
asserts("#create") do
|
57
|
+
s = ObjectProxy::proxy(String)::new("a,b,c,d")
|
58
|
+
|
59
|
+
s.register_handler(:"before_<<") do |args|
|
60
|
+
args = [",A,B,C"]
|
61
|
+
args
|
62
|
+
end
|
63
|
+
|
64
|
+
s.register_handler(:"after_<<") do |result|
|
65
|
+
"alfa beta"
|
66
|
+
end
|
67
|
+
|
68
|
+
(s << ",1,2,3" == "alfa beta") and (s == "a,b,c,d,A,B,C")
|
69
|
+
end
|
24
70
|
asserts("#fake") do
|
25
71
|
pr = OP::fake(String) do
|
26
72
|
define_method :to_s do
|
@@ -33,7 +79,7 @@ context "ObjectProxy" do
|
|
33
79
|
end
|
34
80
|
asserts("#track") do
|
35
81
|
log = [ ]
|
36
|
-
s = OP::track("a,b,c,d")
|
82
|
+
s = OP::track(String)::new("a,b,c,d")
|
37
83
|
s.before_call do |name|
|
38
84
|
log << name
|
39
85
|
end
|
@@ -45,7 +91,7 @@ context "ObjectProxy" do
|
|
45
91
|
(log == [:gsub!, :gsub!]) and (s == "abcd")
|
46
92
|
end
|
47
93
|
asserts("#catch") do
|
48
|
-
s = OP::catch("alfa")
|
94
|
+
s = OP::catch(String)::new("alfa")
|
49
95
|
log = [ ]
|
50
96
|
|
51
97
|
s.method_call do |name, args, block|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: object-proxy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2012-05-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: hash-utils
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,15 @@ dependencies:
|
|
21
21
|
version: 0.12.1
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.12.1
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: bundler
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ! '>='
|
@@ -32,21 +37,31 @@ dependencies:
|
|
32
37
|
version: 1.0.0
|
33
38
|
type: :development
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.0.0
|
36
46
|
- !ruby/object:Gem::Dependency
|
37
|
-
name:
|
38
|
-
requirement:
|
47
|
+
name: jeweler2
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
39
49
|
none: false
|
40
50
|
requirements:
|
41
51
|
- - ! '>='
|
42
52
|
- !ruby/object:Gem::Version
|
43
|
-
version:
|
53
|
+
version: 2.0.0
|
44
54
|
type: :development
|
45
55
|
prerelease: false
|
46
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.0.0
|
47
62
|
- !ruby/object:Gem::Dependency
|
48
63
|
name: riot
|
49
|
-
requirement:
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
50
65
|
none: false
|
51
66
|
requirements:
|
52
67
|
- - ! '>='
|
@@ -54,7 +69,12 @@ dependencies:
|
|
54
69
|
version: 0.12.1
|
55
70
|
type: :development
|
56
71
|
prerelease: false
|
57
|
-
version_requirements:
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.12.1
|
58
78
|
description:
|
59
79
|
email: martinkozak@martinkozak.net
|
60
80
|
executables: []
|
@@ -88,7 +108,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
88
108
|
version: '0'
|
89
109
|
segments:
|
90
110
|
- 0
|
91
|
-
hash: -
|
111
|
+
hash: -3695544286830733883
|
92
112
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
113
|
none: false
|
94
114
|
requirements:
|
@@ -97,7 +117,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
97
117
|
version: '0'
|
98
118
|
requirements: []
|
99
119
|
rubyforge_project:
|
100
|
-
rubygems_version: 1.8.
|
120
|
+
rubygems_version: 1.8.24
|
101
121
|
signing_key:
|
102
122
|
specification_version: 3
|
103
123
|
summary: Provides collection of four proxy objects intended for intercepting calls
|