proxy_machine 0.0.5 → 0.0.6
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.
- data/README.rdoc +193 -44
- data/Rakefile +16 -1
- data/VERSION +1 -1
- data/lib/kernel.rb +12 -1
- data/lib/proxy_machine.rb +1 -0
- data/lib/proxy_machine/config.rb +38 -0
- data/proxy_machine.gemspec +6 -5
- data/spec/proxy_spec.rb +265 -3
- data/spec/spec_helper.rb +8 -0
- metadata +8 -6
data/README.rdoc
CHANGED
@@ -1,38 +1,85 @@
|
|
1
1
|
= proxy_machine
|
2
2
|
|
3
|
-
== Description
|
4
|
-
|
5
3
|
A cool proxy implementation pattern in ruby
|
6
4
|
|
5
|
+
== Details
|
6
|
+
|
7
|
+
Proxy Machine is a proxy/delegate framework. It can create a proxy for standalone objects or change the behavior of the entire class, also it is possible to create an execution stack with the proxy life cycle.
|
8
|
+
|
7
9
|
== Install
|
8
10
|
|
9
11
|
sudo gem install proxy_machine
|
10
12
|
|
11
13
|
== Example usage
|
12
14
|
|
13
|
-
===
|
15
|
+
=== Proxy standalone objects
|
14
16
|
|
15
17
|
p = proxy_for [1, 2, 3]
|
16
|
-
p.
|
18
|
+
p.proxied? # => true
|
19
|
+
p.reverse # => [3, 2, 1]
|
20
|
+
|
21
|
+
=== Proxy the entire class
|
22
|
+
|
23
|
+
class MyClass
|
24
|
+
attr_accessor :name
|
25
|
+
|
26
|
+
# Configuring the proxy
|
27
|
+
auto_proxy do
|
28
|
+
before :name => lambda {|obj, args| puts "old name: #{obj.name}"}
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
obj = MyClass.new
|
34
|
+
obj.proxied? # => true
|
35
|
+
obj.name # => old name: nil
|
36
|
+
nil
|
17
37
|
|
18
38
|
=== Defining callbefores and callafters in method level
|
19
39
|
|
20
40
|
Callbefores:
|
21
41
|
|
42
|
+
==== Standalone way
|
22
43
|
p = proxy_for [1, 2, 3], :before => {
|
23
44
|
:reverse => lambda {|obj, args| puts 'before reverse'}
|
24
45
|
}
|
25
46
|
|
26
|
-
p.reverse => before reverse
|
27
|
-
|
47
|
+
p.reverse # => before reverse
|
48
|
+
[3, 2, 1]
|
49
|
+
|
50
|
+
==== Class way
|
51
|
+
|
52
|
+
class MyClass
|
53
|
+
# ...
|
54
|
+
auto_proxy do
|
55
|
+
before :method => lambda {|obj, args| puts 'implementation'}
|
56
|
+
end
|
57
|
+
# ...
|
58
|
+
end
|
59
|
+
|
60
|
+
obj = MyClass.new
|
61
|
+
obj.proxied? # => true
|
62
|
+
|
63
|
+
Every instance of "MyClass" will be proxied
|
28
64
|
|
29
65
|
Callafters:
|
30
|
-
|
66
|
+
|
67
|
+
==== Standalone way
|
31
68
|
p = proxy_for [1, 2, 3], :after => {
|
32
69
|
:reverse => lambda {|obj, result, args| result.sort}
|
33
70
|
}
|
34
71
|
|
35
|
-
p.reverse => [1, 2, 3] # We reordered the list
|
72
|
+
p.reverse # => [1, 2, 3] # We reordered the list
|
73
|
+
|
74
|
+
==== Class way
|
75
|
+
|
76
|
+
class MyClass
|
77
|
+
# ...
|
78
|
+
auto_proxy do
|
79
|
+
after :method => lambda {|obj, result, args| puts 'implementation'}
|
80
|
+
end
|
81
|
+
# ...
|
82
|
+
end
|
36
83
|
|
37
84
|
You will always receive the arguments passed to the original method.
|
38
85
|
|
@@ -42,23 +89,47 @@ Callbefores:
|
|
42
89
|
This callback will receive a reference of the object, the symbol of the called method and the
|
43
90
|
original arguments passed.
|
44
91
|
|
92
|
+
==== Standalone way
|
93
|
+
|
45
94
|
p = proxy_for [1, 2, 3], :before_all => lambda {|obj, method, args| puts 'before all'}
|
46
|
-
p.reverse => before all
|
47
|
-
|
95
|
+
p.reverse # => before all
|
96
|
+
[3, 2, 1]
|
48
97
|
|
49
|
-
p.size => before all
|
50
|
-
|
98
|
+
p.size # => before all
|
99
|
+
3
|
51
100
|
|
101
|
+
==== Class way
|
102
|
+
|
103
|
+
class MyClass
|
104
|
+
# ...
|
105
|
+
auto_proxy do
|
106
|
+
before_all {|obj, method, args| puts 'implementation'}
|
107
|
+
end
|
108
|
+
# ...
|
109
|
+
end
|
110
|
+
|
52
111
|
Callafters:
|
53
112
|
This callback will receive a reference of the object, the result of execution (this result could be nil),
|
54
113
|
the symbol of the called method and the arguments passed.
|
114
|
+
|
115
|
+
==== Standalone way
|
55
116
|
|
56
117
|
p = proxy_for [1, 2, 3], :after_all => lambda {|obj, result, method, args| puts result}
|
57
|
-
p.reverse => [1, 2, 3]
|
58
|
-
|
118
|
+
p.reverse # => [1, 2, 3]
|
119
|
+
[1, 2, 3] # puts
|
59
120
|
|
60
|
-
p.size => 3
|
61
|
-
|
121
|
+
p.size # => 3
|
122
|
+
3 # puts
|
123
|
+
|
124
|
+
==== Class way
|
125
|
+
|
126
|
+
class MyClass
|
127
|
+
# ...
|
128
|
+
auto_proxy do
|
129
|
+
after_all {|obj, result, method, args| puts 'implementation'}
|
130
|
+
end
|
131
|
+
# ...
|
132
|
+
end
|
62
133
|
|
63
134
|
=== Registering a class to perform the callafter or callbefore
|
64
135
|
|
@@ -74,12 +145,24 @@ every time it need to use it. You could use this feature with the before_all and
|
|
74
145
|
|
75
146
|
def call; @object.sort! end
|
76
147
|
end
|
148
|
+
|
149
|
+
==== Standalone way
|
77
150
|
|
78
151
|
p = proxy_for [1, 2, 3], :after => {
|
79
152
|
:reverse => SortPerformer
|
80
153
|
}
|
81
154
|
|
82
|
-
p.reverse => [1, 2, 3]
|
155
|
+
p.reverse # => [1, 2, 3]
|
156
|
+
|
157
|
+
==== Class way
|
158
|
+
|
159
|
+
class MyClass
|
160
|
+
# ...
|
161
|
+
auto_proxy do
|
162
|
+
after :method => Performer
|
163
|
+
end
|
164
|
+
# ...
|
165
|
+
end
|
83
166
|
|
84
167
|
=== Controlling the method execution with regexp
|
85
168
|
|
@@ -93,27 +176,56 @@ For before_all and after_all you could use regexp to configure which methods wil
|
|
93
176
|
def another_method; @value ? @value : 'another' end
|
94
177
|
def crazy_one; @value ? @value : 'crazy' end
|
95
178
|
end
|
179
|
+
|
180
|
+
==== Standalone way
|
96
181
|
|
97
182
|
p = proxy_for MyRegexMethods.new, :before_all => [
|
98
183
|
[/^get_/, lambda {|obj, method, args| obj.value = 'gotcha!' }]
|
99
184
|
]
|
100
185
|
|
101
|
-
p.get_value1 => gotcha!
|
102
|
-
p.get_value2 => gotcha!
|
103
|
-
p.another_method => 'another
|
104
|
-
proxy.crazy_one => 'crazy'
|
186
|
+
p.get_value1 # => gotcha!
|
187
|
+
p.get_value2 # => gotcha!
|
188
|
+
p.another_method # => 'another
|
189
|
+
proxy.crazy_one # => 'crazy'
|
190
|
+
|
191
|
+
==== Class way
|
192
|
+
|
193
|
+
class MyRegexMethods
|
194
|
+
# ...
|
195
|
+
auto_proxy do
|
196
|
+
before_all [
|
197
|
+
[/^get_/, lambda {|obj, method, args| obj.value = 'gotcha!' }]
|
198
|
+
]
|
199
|
+
end
|
200
|
+
# ...
|
201
|
+
end
|
105
202
|
|
106
203
|
You could use many definitions if you want, the calls will happen in the declared order.
|
107
204
|
|
205
|
+
==== Standalone way
|
206
|
+
|
108
207
|
p = proxy_for MyRegexMethods.new, :before_all => [
|
109
208
|
[/get_/, lambda {|obj, method, args| obj.value = "it_"}]
|
110
209
|
[/value/, lambda {|obj, method, args| obj.value = "#{obj.value}works"}]
|
111
210
|
]
|
112
211
|
|
113
|
-
p.get_value1 => it_works
|
114
|
-
p.get_value2 => it_works
|
115
|
-
p.another_method => another
|
116
|
-
p.crazy_one => crazy
|
212
|
+
p.get_value1 # => it_works
|
213
|
+
p.get_value2 # => it_works
|
214
|
+
p.another_method # => another
|
215
|
+
p.crazy_one # => crazy
|
216
|
+
|
217
|
+
==== Class way
|
218
|
+
|
219
|
+
class MyRegexMethods
|
220
|
+
# ...
|
221
|
+
auto_proxy do
|
222
|
+
before_all [
|
223
|
+
[/get_/, lambda {|obj, method, args| obj.value = "it_"}]
|
224
|
+
[/value/, lambda {|obj, method, args| obj.value = "#{obj.value}works"}]
|
225
|
+
]
|
226
|
+
end
|
227
|
+
# ...
|
228
|
+
end
|
117
229
|
|
118
230
|
It is also possible to use classes instead of procs.
|
119
231
|
|
@@ -131,10 +243,10 @@ It is also possible to use classes instead of procs.
|
|
131
243
|
[/value/, Change2Performer]
|
132
244
|
]
|
133
245
|
|
134
|
-
p.get_value1 => it_works
|
135
|
-
p.get_value2 => it_works
|
136
|
-
p.another_method => another
|
137
|
-
p.crazy_one => crazy
|
246
|
+
p.get_value1 # => it_works
|
247
|
+
p.get_value2 # => it_works
|
248
|
+
p.another_method # => another
|
249
|
+
p.crazy_one # => crazy
|
138
250
|
|
139
251
|
=== Building an execution stack
|
140
252
|
|
@@ -160,18 +272,20 @@ It is also possible to use classes instead of procs.
|
|
160
272
|
:company_name => [make_lower, make_round_brackets2]
|
161
273
|
}
|
162
274
|
|
163
|
-
p.name => (IMPORTANT-NAME)
|
164
|
-
p.company_name => [company name]
|
275
|
+
p.name # => (IMPORTANT-NAME)
|
276
|
+
p.company_name # => [company name]
|
165
277
|
|
166
278
|
=== How to detect that the object is a proxy?
|
167
279
|
|
168
280
|
The beautiful way:
|
169
281
|
|
170
282
|
o1 = [1, 2, 3]
|
171
|
-
o1.proxied? => false
|
283
|
+
o1.proxied? # => false
|
172
284
|
|
173
285
|
o2 = proxy_for [1, 2, 3]
|
174
|
-
o2.proxied? => true
|
286
|
+
o2.proxied? # => true
|
287
|
+
|
288
|
+
It will work with +auto_proxy+ usage too.
|
175
289
|
|
176
290
|
Other way:
|
177
291
|
|
@@ -183,8 +297,10 @@ Other way:
|
|
183
297
|
Call original_object method in the proxy object.
|
184
298
|
|
185
299
|
proxy = proxy_for [1, 2, 3]
|
186
|
-
proxy.proxied? => true
|
187
|
-
proxy.original_object.proxied? => false
|
300
|
+
proxy.proxied? # => true
|
301
|
+
proxy.original_object.proxied? # => false
|
302
|
+
|
303
|
+
It will work with +auto_proxy+ usage too.
|
188
304
|
|
189
305
|
=== Special options
|
190
306
|
|
@@ -197,15 +313,30 @@ Default is false.
|
|
197
313
|
attr_accessor :value
|
198
314
|
def method_missing(symbol, *args); 'nice!'; end
|
199
315
|
end
|
316
|
+
|
317
|
+
==== Standalone way
|
200
318
|
|
201
319
|
p = proxy_for MyClass.new, :allow_dinamic => true, :before => {
|
202
320
|
:magic_method => lambda {|obj| obj.value = 'other value' }
|
203
321
|
}
|
204
322
|
|
205
|
-
p.magic_method => 'other value'
|
323
|
+
p.magic_method # => 'other value'
|
324
|
+
|
325
|
+
==== Class way
|
326
|
+
|
327
|
+
class MyClass
|
328
|
+
# ...
|
329
|
+
auto_proxy do
|
330
|
+
allow_dinamic true
|
331
|
+
before :magic_method => lambda {|obj| obj.value = 'other value' }
|
332
|
+
end
|
333
|
+
# ...
|
334
|
+
end
|
206
335
|
|
207
336
|
2 - avoid_original_execution: When this option is enabled, proxy_machine will not call the original method.
|
208
337
|
Default is false.
|
338
|
+
|
339
|
+
==== Standalone way
|
209
340
|
|
210
341
|
p = proxy_for [3, 2, 1],
|
211
342
|
:avoid_original_execution => true,
|
@@ -213,21 +344,39 @@ Default is false.
|
|
213
344
|
:empty? => lambda {|obj| obj.sort!}
|
214
345
|
}
|
215
346
|
|
216
|
-
p.empty? => nil
|
217
|
-
p.original_object => [1, 2, 3]
|
347
|
+
p.empty? # => nil
|
348
|
+
p.original_object # => [1, 2, 3]
|
349
|
+
|
350
|
+
==== Class way
|
351
|
+
|
352
|
+
class MyClass
|
353
|
+
# ...
|
354
|
+
auto_proxy do
|
355
|
+
avoid_original_execution true
|
356
|
+
end
|
357
|
+
# ...
|
358
|
+
end
|
218
359
|
|
219
360
|
=== Trying it in irb
|
220
361
|
|
221
362
|
irb
|
222
363
|
require 'proxy_machine'
|
364
|
+
|
223
365
|
proxy_for...
|
224
366
|
|
367
|
+
class XYZ
|
368
|
+
auto_proxy do
|
369
|
+
...
|
370
|
+
end
|
371
|
+
...
|
372
|
+
end
|
373
|
+
|
225
374
|
=== Other ways:
|
226
375
|
|
227
376
|
1º - Creates a proxy for the informed object
|
228
377
|
|
229
378
|
p = Proxy.new [1,2,3]
|
230
|
-
p.size => 3
|
379
|
+
p.size # => 3
|
231
380
|
|
232
381
|
2º - A proxy with a before callback.
|
233
382
|
|
@@ -235,8 +384,8 @@ Default is false.
|
|
235
384
|
:size => lambda {|obj| puts "before: #{obj.inspect}"}
|
236
385
|
}
|
237
386
|
|
238
|
-
p.size => before: [1, 2, 3]
|
239
|
-
|
387
|
+
p.size # => before: [1, 2, 3]
|
388
|
+
3
|
240
389
|
|
241
390
|
3º - A proxy with a after callback
|
242
391
|
|
@@ -244,8 +393,8 @@ Default is false.
|
|
244
393
|
:size => lambda {|obj, result| puts "after: #{obj.inspect}: result => #{result}"}
|
245
394
|
}
|
246
395
|
|
247
|
-
p.size => after: [1, 2, 3]: result => 3
|
248
|
-
|
396
|
+
p.size # => after: [1, 2, 3]: result => 3
|
397
|
+
3
|
249
398
|
|
250
399
|
4º - Both
|
251
400
|
|
@@ -258,4 +407,4 @@ Default is false.
|
|
258
407
|
|
259
408
|
== Copyright
|
260
409
|
|
261
|
-
Copyright (c) 2010 Túlio Ornelas. See LICENSE for details.
|
410
|
+
Copyright (c) 2010, 2011 Túlio Ornelas. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -14,4 +14,19 @@ begin
|
|
14
14
|
Jeweler::GemcutterTasks.new
|
15
15
|
rescue LoadError
|
16
16
|
puts "Jeweler not available. Install it with: gem install jeweler"
|
17
|
-
end
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'rspec/core'
|
20
|
+
require 'rspec/core/rake_task'
|
21
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
22
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
23
|
+
spec.rspec_opts = '-c --format documentation'
|
24
|
+
end
|
25
|
+
|
26
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
27
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
28
|
+
spec.rcov = true
|
29
|
+
spec.rspec_opts = '-c --format documentation'
|
30
|
+
end
|
31
|
+
|
32
|
+
task :default => :spec
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.6
|
data/lib/kernel.rb
CHANGED
@@ -3,7 +3,18 @@ require 'proxy_machine'
|
|
3
3
|
module Kernel
|
4
4
|
|
5
5
|
def proxy_for object, callbacks = nil
|
6
|
-
Proxy.new object, callbacks
|
6
|
+
ProxyMachine::Proxy.new object, callbacks
|
7
|
+
end
|
8
|
+
|
9
|
+
def auto_proxy &block
|
10
|
+
@proxy_machine_config = ProxyMachine::Config.new
|
11
|
+
@proxy_machine_config.apply!(&block)
|
12
|
+
|
13
|
+
def self.new(*args)
|
14
|
+
obj = allocate
|
15
|
+
obj.send(:initialize, *args)
|
16
|
+
proxy_for obj, @proxy_machine_config.callbacks
|
17
|
+
end
|
7
18
|
end
|
8
19
|
|
9
20
|
end
|
data/lib/proxy_machine.rb
CHANGED
@@ -0,0 +1,38 @@
|
|
1
|
+
module ProxyMachine
|
2
|
+
class Config
|
3
|
+
|
4
|
+
attr_reader :callbacks
|
5
|
+
def initialize
|
6
|
+
@callbacks = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def apply! &block
|
10
|
+
instance_exec(&block)
|
11
|
+
end
|
12
|
+
|
13
|
+
def allow_dinamic boolean
|
14
|
+
@callbacks[:allow_dinamic] = boolean
|
15
|
+
end
|
16
|
+
|
17
|
+
def avoid_original_execution boolean
|
18
|
+
@callbacks[:avoid_original_execution] = boolean
|
19
|
+
end
|
20
|
+
|
21
|
+
def before hash
|
22
|
+
@callbacks[:before] = hash
|
23
|
+
end
|
24
|
+
|
25
|
+
def before_all params = nil, &block
|
26
|
+
@callbacks[:before_all] = params ? params : block
|
27
|
+
end
|
28
|
+
|
29
|
+
def after hash
|
30
|
+
@callbacks[:after] = hash
|
31
|
+
end
|
32
|
+
|
33
|
+
def after_all params = nil, &block
|
34
|
+
@callbacks[:after_all] = params ? params : block
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
data/proxy_machine.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{proxy_machine}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.6"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["T\303\272lio Ornelas"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2011-03-23}
|
13
13
|
s.description = %q{A cool proxy implementation pattern in ruby}
|
14
14
|
s.email = %q{ornelas.tulio@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -26,23 +26,24 @@ Gem::Specification.new do |s|
|
|
26
26
|
"lib/kernel.rb",
|
27
27
|
"lib/object.rb",
|
28
28
|
"lib/proxy_machine.rb",
|
29
|
+
"lib/proxy_machine/config.rb",
|
29
30
|
"lib/proxy_machine/proxy.rb",
|
30
31
|
"lib/symbol.rb",
|
31
32
|
"proxy_machine.gemspec",
|
32
33
|
"script/console",
|
33
|
-
"spec/proxy_spec.rb"
|
34
|
+
"spec/proxy_spec.rb",
|
35
|
+
"spec/spec_helper.rb"
|
34
36
|
]
|
35
37
|
s.homepage = %q{http://github.com/tulios/proxy_machine}
|
36
38
|
s.rdoc_options = ["--charset=UTF-8"]
|
37
39
|
s.require_paths = ["lib"]
|
38
|
-
s.rubygems_version = %q{1.
|
40
|
+
s.rubygems_version = %q{1.4.1}
|
39
41
|
s.summary = %q{A cool proxy implementation pattern in ruby}
|
40
42
|
s.test_files = [
|
41
43
|
"spec/proxy_spec.rb"
|
42
44
|
]
|
43
45
|
|
44
46
|
if s.respond_to? :specification_version then
|
45
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
46
47
|
s.specification_version = 3
|
47
48
|
|
48
49
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
data/spec/proxy_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
require '
|
1
|
+
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe "proxy_machine" do
|
4
4
|
|
5
5
|
it 'should create a proxy object from the given one' do
|
6
6
|
array = [1, 2, 3]
|
@@ -128,7 +128,7 @@ describe Proxy do
|
|
128
128
|
|
129
129
|
end
|
130
130
|
|
131
|
-
context 'for kernel method' do
|
131
|
+
context 'for kernel method proxy_for' do
|
132
132
|
|
133
133
|
it 'should call proxy' do
|
134
134
|
array = [1, 2, 3]
|
@@ -415,6 +415,268 @@ describe Proxy do
|
|
415
415
|
end
|
416
416
|
|
417
417
|
end
|
418
|
+
|
419
|
+
context 'for kernel method auto_proxy' do
|
420
|
+
class ProxiedConstructor
|
421
|
+
attr_accessor :name, :count
|
422
|
+
def initialize; @count = 0 end
|
423
|
+
end
|
424
|
+
|
425
|
+
context 'when generate a object already proxied' do
|
426
|
+
|
427
|
+
it 'should work even if the class have a parametrized initialize' do
|
428
|
+
class ProxiedConstructorWithArgs
|
429
|
+
attr_accessor :var1, :var2
|
430
|
+
def initialize(v1, v2); @var1 = v1; @var2 = v2; end
|
431
|
+
auto_proxy { before :var1 => lambda {|obj, args| obj.var1 = 'proxied' if obj.var1 == 1} }
|
432
|
+
end
|
433
|
+
|
434
|
+
obj = ProxiedConstructorWithArgs.new(1,2)
|
435
|
+
obj.proxied?.should be_true
|
436
|
+
obj.send(:var1).should eql(1) # by passing proxy_machine
|
437
|
+
obj.var1.should eql('proxied')
|
438
|
+
obj.var2.should eql(2)
|
439
|
+
|
440
|
+
obj = ProxiedConstructorWithArgs.new('a', 'b')
|
441
|
+
obj.proxied?.should be_true
|
442
|
+
obj.var1.should eql('a')
|
443
|
+
obj.var2.should eql('b')
|
444
|
+
end
|
445
|
+
|
446
|
+
context 'for a certain method' do
|
447
|
+
|
448
|
+
it 'should add a callbefore' do
|
449
|
+
class ProxiedConstructor
|
450
|
+
auto_proxy { before :name => lambda {|obj, args| obj.name = "#{obj.name}-2"} }
|
451
|
+
end
|
452
|
+
|
453
|
+
obj = ProxiedConstructor.new
|
454
|
+
obj.proxied?.should be_true
|
455
|
+
obj.name.should eql("-2")
|
456
|
+
obj.name = "house"
|
457
|
+
obj.name.should eql("house-2")
|
458
|
+
end
|
459
|
+
|
460
|
+
it 'should add a callafter' do
|
461
|
+
class ProxiedConstructor
|
462
|
+
auto_proxy { after :name => lambda {|obj, result, args| result.chars.to_a.sort.to_s} }
|
463
|
+
end
|
464
|
+
|
465
|
+
obj = ProxiedConstructor.new
|
466
|
+
obj.proxied?.should be_true
|
467
|
+
obj.name = "tulio"
|
468
|
+
obj.name.should eql("ilotu")
|
469
|
+
obj.name = "proxy"
|
470
|
+
obj.name.should eql("oprxy")
|
471
|
+
end
|
472
|
+
|
473
|
+
end
|
474
|
+
|
475
|
+
context 'for all methods' do
|
476
|
+
|
477
|
+
it 'should add a callbefore' do
|
478
|
+
class ProxiedConstructor
|
479
|
+
auto_proxy { before_all {|obj, method, args| obj.count+=1} }
|
480
|
+
end
|
481
|
+
|
482
|
+
obj = ProxiedConstructor.new
|
483
|
+
obj.proxied?.should be_true
|
484
|
+
obj.count.should eql(1)
|
485
|
+
obj.to_s
|
486
|
+
obj.count.should eql(3)
|
487
|
+
obj.display
|
488
|
+
obj.count.should eql(5)
|
489
|
+
end
|
490
|
+
|
491
|
+
it 'should add a callafter' do
|
492
|
+
class ProxiedConstructor
|
493
|
+
auto_proxy { after_all {|obj, method, args| obj.count-=1} }
|
494
|
+
end
|
495
|
+
|
496
|
+
obj = ProxiedConstructor.new
|
497
|
+
obj.proxied?.should be_true
|
498
|
+
obj.count.should eql(-1)
|
499
|
+
obj.to_s
|
500
|
+
obj.count.should eql(-3)
|
501
|
+
obj.display
|
502
|
+
obj.count.should eql(-5)
|
503
|
+
end
|
504
|
+
|
505
|
+
end
|
506
|
+
|
507
|
+
context 'filtering methods by regex' do
|
508
|
+
class MyRegexMethodsProxiedConstructor
|
509
|
+
attr_accessor :value
|
510
|
+
def get_value1; @value ? @value : 'get' end
|
511
|
+
def get_value2; @value ? @value : 'get' end
|
512
|
+
def another_method; @value ? @value : 'another' end
|
513
|
+
def crazy_one; @value ? @value : 'crazy' end
|
514
|
+
end
|
515
|
+
|
516
|
+
it 'should affect just the matched methods on callbefore' do
|
517
|
+
class MyRegexMethodsProxiedConstructor
|
518
|
+
auto_proxy do
|
519
|
+
before_all [
|
520
|
+
[/^get_/, lambda {|obj, method, args| obj.value = 'gotcha!' }],
|
521
|
+
[/method$/, lambda {|obj, method, args| obj.value = 'another gotcha!' }]
|
522
|
+
]
|
523
|
+
end
|
524
|
+
end
|
525
|
+
|
526
|
+
obj = MyRegexMethodsProxiedConstructor.new
|
527
|
+
obj.proxied?.should be_true
|
528
|
+
|
529
|
+
obj.original_object.value = nil
|
530
|
+
obj.get_value1.should == 'gotcha!'
|
531
|
+
|
532
|
+
obj.original_object.value = nil
|
533
|
+
obj.get_value2.should == 'gotcha!'
|
534
|
+
|
535
|
+
obj.original_object.value = nil
|
536
|
+
obj.another_method.should == 'another gotcha!'
|
537
|
+
|
538
|
+
obj.original_object.value = nil
|
539
|
+
obj.crazy_one.should == 'crazy'
|
540
|
+
end
|
541
|
+
|
542
|
+
it 'should affect just the matched methods on callafter' do
|
543
|
+
class MyRegexMethodsProxiedConstructor
|
544
|
+
auto_proxy do
|
545
|
+
after_all [
|
546
|
+
[/^get_/, lambda {|obj, result, method, args| obj.value = 'gotcha!' }],
|
547
|
+
[/method$/, lambda {|obj, result, method, args| obj.value = 'another gotcha!'}]
|
548
|
+
]
|
549
|
+
end
|
550
|
+
end
|
551
|
+
|
552
|
+
obj = MyRegexMethodsProxiedConstructor.new
|
553
|
+
obj.proxied?.should be_true
|
554
|
+
|
555
|
+
obj.original_object.value = nil
|
556
|
+
obj.get_value1.should == 'gotcha!'
|
557
|
+
|
558
|
+
obj.original_object.value = nil
|
559
|
+
obj.get_value2.should == 'gotcha!'
|
560
|
+
|
561
|
+
obj.original_object.value = nil
|
562
|
+
obj.another_method.should == 'another gotcha!'
|
563
|
+
|
564
|
+
obj.original_object.value = nil
|
565
|
+
obj.crazy_one.should == 'crazy'
|
566
|
+
end
|
567
|
+
|
568
|
+
end
|
569
|
+
|
570
|
+
end
|
571
|
+
|
572
|
+
context 'with dinamic methods' do
|
573
|
+
class MyClassProxiedConstructed
|
574
|
+
attr_accessor :value
|
575
|
+
auto_proxy do
|
576
|
+
allow_dinamic true
|
577
|
+
before :crazy_method => lambda {|obj, args| obj.value = "proxied value!" }
|
578
|
+
end
|
579
|
+
def method_missing(symbol, *args); @value; end
|
580
|
+
end
|
581
|
+
|
582
|
+
it 'should allow dinamic methods' do
|
583
|
+
obj = MyClassProxiedConstructed.new
|
584
|
+
obj.proxied?.should be_true
|
585
|
+
|
586
|
+
obj.value = "Crazy Value"
|
587
|
+
obj.value.should == "Crazy Value"
|
588
|
+
obj.crazy_method.should == "proxied value!"
|
589
|
+
obj.value.should == "proxied value!"
|
590
|
+
end
|
591
|
+
end
|
592
|
+
|
593
|
+
context 'avoiding original execution' do
|
594
|
+
class AvoidOriginalProxiedConstructed
|
595
|
+
attr_accessor :value
|
596
|
+
auto_proxy do
|
597
|
+
avoid_original_execution true
|
598
|
+
after_all {|obj, result, method, args| "avoided"}
|
599
|
+
end
|
600
|
+
def do_something; @value = "original" end
|
601
|
+
end
|
602
|
+
|
603
|
+
it 'should happen' do
|
604
|
+
obj = AvoidOriginalProxiedConstructed.new
|
605
|
+
obj.proxied?.should be_true
|
606
|
+
|
607
|
+
obj.do_something.should == "avoided"
|
608
|
+
obj.original_object.value.should be_nil
|
609
|
+
end
|
610
|
+
end
|
611
|
+
|
612
|
+
context 'when registering a class' do
|
613
|
+
class CounterPerformer
|
614
|
+
def initialize object, result = nil, method = nil, args = nil
|
615
|
+
@object = object; @result = result; @method = method, @args = args
|
616
|
+
end
|
617
|
+
|
618
|
+
def call; @object.count = @object.count ? @object.count+1 : 0 end
|
619
|
+
end
|
620
|
+
class RegisteredProxiedConstructed; attr_accessor :count; end
|
621
|
+
|
622
|
+
it 'should use a instance of the registered class for a callbefore' do
|
623
|
+
class RegisteredProxiedConstructed
|
624
|
+
auto_proxy {before :to_s => CounterPerformer}
|
625
|
+
end
|
626
|
+
|
627
|
+
obj = RegisteredProxiedConstructed.new
|
628
|
+
obj.proxied?.should be_true
|
629
|
+
obj.count.should eql(nil)
|
630
|
+
obj.to_s
|
631
|
+
obj.count.should eql(0)
|
632
|
+
obj.to_s
|
633
|
+
obj.count.should eql(1)
|
634
|
+
end
|
635
|
+
|
636
|
+
it 'should use a instance of the registered class for a callafter' do
|
637
|
+
class RegisteredProxiedConstructed
|
638
|
+
auto_proxy {after :to_s => CounterPerformer}
|
639
|
+
end
|
640
|
+
|
641
|
+
obj = RegisteredProxiedConstructed.new
|
642
|
+
obj.proxied?.should be_true
|
643
|
+
obj.count.should eql(nil)
|
644
|
+
obj.to_s
|
645
|
+
obj.count.should eql(0)
|
646
|
+
obj.to_s
|
647
|
+
obj.count.should eql(1)
|
648
|
+
end
|
649
|
+
|
650
|
+
it 'should use a instance of the registered class for callbefore_all' do
|
651
|
+
class RegisteredProxiedConstructed
|
652
|
+
auto_proxy {before_all CounterPerformer}
|
653
|
+
end
|
654
|
+
|
655
|
+
obj = RegisteredProxiedConstructed.new
|
656
|
+
obj.proxied?.should be_true
|
657
|
+
obj.count.should eql(0)
|
658
|
+
obj.to_s
|
659
|
+
obj.count.should eql(2)
|
660
|
+
obj.display
|
661
|
+
obj.count.should eql(4)
|
662
|
+
end
|
663
|
+
|
664
|
+
it 'should use a instance of the registered class for callafter_all' do
|
665
|
+
class RegisteredProxiedConstructed
|
666
|
+
auto_proxy {after_all CounterPerformer}
|
667
|
+
end
|
668
|
+
|
669
|
+
obj = RegisteredProxiedConstructed.new
|
670
|
+
obj.proxied?.should be_true
|
671
|
+
obj.count.should eql(0)
|
672
|
+
obj.to_s
|
673
|
+
obj.count.should eql(2)
|
674
|
+
obj.display
|
675
|
+
obj.count.should eql(4)
|
676
|
+
end
|
677
|
+
|
678
|
+
end
|
679
|
+
end
|
418
680
|
|
419
681
|
end
|
420
682
|
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: proxy_machine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 19
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 6
|
10
|
+
version: 0.0.6
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- "T\xC3\xBAlio Ornelas"
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
18
|
+
date: 2011-03-23 00:00:00 -03:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -69,11 +69,13 @@ files:
|
|
69
69
|
- lib/kernel.rb
|
70
70
|
- lib/object.rb
|
71
71
|
- lib/proxy_machine.rb
|
72
|
+
- lib/proxy_machine/config.rb
|
72
73
|
- lib/proxy_machine/proxy.rb
|
73
74
|
- lib/symbol.rb
|
74
75
|
- proxy_machine.gemspec
|
75
76
|
- script/console
|
76
77
|
- spec/proxy_spec.rb
|
78
|
+
- spec/spec_helper.rb
|
77
79
|
has_rdoc: true
|
78
80
|
homepage: http://github.com/tulios/proxy_machine
|
79
81
|
licenses: []
|
@@ -104,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
106
|
requirements: []
|
105
107
|
|
106
108
|
rubyforge_project:
|
107
|
-
rubygems_version: 1.
|
109
|
+
rubygems_version: 1.4.1
|
108
110
|
signing_key:
|
109
111
|
specification_version: 3
|
110
112
|
summary: A cool proxy implementation pattern in ruby
|