proxified 0.1.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/proxified.rb CHANGED
@@ -3,39 +3,46 @@
3
3
  require 'active_support'
4
4
  require 'active_support/core_ext'
5
5
 
6
- # =====Allows to "proxify" and "unproxify" any instance method with custom code and to inherit and change the behaviour down the class hierarchy.
6
+ # Allows to _proxify_ and _unproxify_ any instance method of a class with
7
+ # custom code and to inherit and change the behaviour down the class hierarchy.
8
+ #
9
+ # The global methods allow to dinamically _proxify_ and _unproxify_ a class or
10
+ # an object injecting Proxified in the class or the object's singleton class.
11
+ #
12
+ # This makes possible to dinamically wrap a proxy around any class with no need
13
+ # for the class to know it, and to change the behaviour of one or more objects
14
+ # without side effects on other objects of the same class.
7
15
  module Proxified
8
16
  extend ::ActiveSupport::Concern
9
17
 
10
18
  included do
11
- # Stores the methods to proxify allowing descendants to override them
19
+ # Stores the methods to _proxify_ allowing descendants to override them
12
20
  # without affecting the parent.
13
21
  class_attribute :proxified_methods, default: {}, instance_accessor: false
14
22
  end
15
23
 
16
24
  class_methods do
17
- # For each +method+ in +methods+, defines a +proxified_method+ that runs
18
- # the given +block+ when +method+ is called, or raises ArgumentError if no
19
- # block or no method is given.
25
+ # For each +method+ in +methods+, defines a _proxified_ _method_ that
26
+ # runs the given +block+ when +method+ is called, or raises ArgumentError
27
+ # if no +block+ or no +methods+ are given.
20
28
  #
21
- # In order to not change the class interface, a method is only +proxified+
29
+ # In order not to change the class interface, a method is only _proxified_
22
30
  # when the corresponding instance method is defined (before or after the
23
- # proxy definition), while a +proxified_method+ is removed whenever the
31
+ # proxy definition), while a _proxified_ _method_ is removed whenever the
24
32
  # corresponding instance method is removed from the class. Moreover, the
25
- # +proxified_methods+ take the arguments specified by the +block+, so the
26
- # +block+ should take the same arguments as the original +methods+
27
- # (although it can take any number of arguments). Finally, it's possible
28
- # to call the actual +methods+ invoking +super+ inside the +block+.
33
+ # _proxified_ _methods_ take the arguments specified by the +block+, so the
34
+ # +block+ should take the same arguments as the original +methods+.
35
+ # Finally, it's possible to call the original +methods+ invoking +super+
36
+ # inside the +block+.
29
37
  #
30
- # The +proxified_methods+ are defined in a proxy module that is prepended
31
- # automatically to the class only the first time a +proxified_method+ is
32
- # defined within that class and the proxy module's name is prefixed with the
33
- # class name. In this way, descendants who redefine a +proxified_method+
34
- # get their own proxy module, while those who do not redefine a
35
- # +proxified_method+ get the parent's proxy module.
38
+ # The _proxified_ _methods_ are defined in a proxy module that is
39
+ # automatically prepended to the class only the first time a _proxified_
40
+ # _method_ is defined within that class. In this way, descendants who
41
+ # redefine a _proxified_ _method_ get their own proxy module, while those
42
+ # who do not redefine a _proxified_ _method_ get the parent's proxy module.
36
43
  #
37
- # Beware: if a child redefines a +proxified_method+ to call +super+, the
38
- # parent's +proxified_method+ will be called.
44
+ # Beware: if a child redefines a _proxified_ _method_ to call +super+, the
45
+ # parent's _proxified_ _method_ will be called.
39
46
  #
40
47
  # ======Examples
41
48
  #
@@ -53,7 +60,7 @@ module Proxified
53
60
  # end
54
61
  #
55
62
  # def welcome(name)
56
- # puts "hello #{name}!"
63
+ # puts "welcome #{name}!"
57
64
  # end
58
65
  #
59
66
  # def goodbye(name)
@@ -61,50 +68,54 @@ module Proxified
61
68
  # end
62
69
  # end
63
70
  #
64
- # A.ancestors => [A::Proxy, A, Proxified, ...]
71
+ # A.ancestors # => [A::Proxy, A, Proxified, ...]
65
72
  #
66
73
  # a = A.new
67
- # a.welcome('jack') => 'checking jack'; 'welcome jack!';
68
- # a.goodbye('jack') => 'checking jack'; 'goodbye jack!';
69
- # a.welcome => raises ArgumentError
70
- # a.check('jack') => 'checking jack' # not proxified
74
+ # a.welcome('jack') # => 'checking jack'; 'welcome jack!';
75
+ # a.goodbye('jack') # => 'checking jack'; 'goodbye jack!';
76
+ # a.welcome # => raises ArgumentError
77
+ # a.check('jack') # => 'checking jack' (not proxified)
78
+ #
71
79
  #
72
80
  # Just inheriting:
73
81
  # class B < A; end
74
82
  #
75
- # B.ancestors => [B, A::Proxy, A, Proxified, ...]
83
+ # B.ancestors # => [B, A::Proxy, A, Proxified, ...]
76
84
  #
77
85
  # b = B.new
78
- # b.welcome('jack') => 'checking jack'; 'welcome jack!';
79
- # b.goodbye('jack') => 'checking jack'; 'goodbye jack!';
86
+ # b.welcome('jack') # => 'checking jack'; 'welcome jack!';
87
+ # b.goodbye('jack') # => 'checking jack'; 'goodbye jack!';
80
88
  #
81
- # Redefining a +proxified_method+:
89
+ #
90
+ # Inheriting and redefining a _proxified_ _method_:
82
91
  # class C < A
83
92
  # def welcome(name)
84
93
  # puts "welcome #{name.upcase}!"
85
94
  # end
86
95
  # end
87
96
  #
88
- # C.ancestors => [C::Proxy, C, A::Proxy, A, Proxified, ...]
97
+ # C.ancestors # => [C::Proxy, C, A::Proxy, A, Proxified, ...]
89
98
  #
90
99
  # c = C.new
91
- # c.welcome('jack') => 'checking jack'; 'welcome JACK!';
92
- # c.goodbye('jack') => 'checking jack'; 'goodbye jack!';
100
+ # c.welcome('jack') # => 'checking jack'; 'welcome JACK!';
101
+ # c.goodbye('jack') # => 'checking jack'; 'goodbye jack!';
102
+ #
93
103
  #
94
- # Reproxifing a +proxified_method+:
104
+ # Inheriting and _reproxifing_ a _proxified_ _method_:
95
105
  # class D < A
96
106
  # proxify :welcome do |name|
97
107
  # super(name.upcase)
98
108
  # end
99
109
  # end
100
110
  #
101
- # D.ancestors => [D::Proxy, D, A::Proxy, A, Proxified, ...]
111
+ # D.ancestors # => [D::Proxy, D, A::Proxy, A, Proxified, ...]
102
112
  #
103
113
  # d = D.new
104
- # d.welcome('jack') => 'checking JACK'; 'welcome JACK!';
105
- # d.goodbye('jack') => 'checking jack'; 'goodbye jack!';
114
+ # d.welcome('jack') # => 'checking JACK'; 'welcome JACK!';
115
+ # d.goodbye('jack') # => 'checking jack'; 'goodbye jack!';
116
+ #
106
117
  #
107
- # Reproxifing and redefining a +proxified_method+:
118
+ # Inheriting, _reproxifing_ and redefining a _proxified_ _method_:
108
119
  # class E < A
109
120
  # proxify :welcome do |name|
110
121
  # super(name.upcase)
@@ -115,13 +126,14 @@ module Proxified
115
126
  # end
116
127
  # end
117
128
  #
118
- # E.ancestors => [E::Proxy, E, A::Proxy, A, Proxified, ...]
129
+ # E.ancestors # => [E::Proxy, E, A::Proxy, A, Proxified, ...]
119
130
  #
120
131
  # e = E.new
121
- # e.welcome('jack') => 'hello JACK!';
122
- # e.goodbye('jack') => 'checking jack'; 'goodbye jack!';
132
+ # e.welcome('jack') # => 'hello JACK!';
133
+ # e.goodbye('jack') # => 'checking jack'; 'goodbye jack!';
123
134
  #
124
- # Redefining a +proxified_method+ to call +super+:
135
+ #
136
+ # Inheriting and redefining a _proxified_ _method_ to call +super+:
125
137
  # class F < A
126
138
  # def welcome(name)
127
139
  # super(name)
@@ -129,11 +141,11 @@ module Proxified
129
141
  # end
130
142
  # end
131
143
  #
132
- # F.ancestors => [F::Proxy, F, A::Proxy, A, Proxified, ...]
144
+ # F.ancestors # => [F::Proxy, F, A::Proxy, A, Proxified, ...]
133
145
  #
134
146
  # f = F.new
135
- # f.welcome('tom') => 'checking tom'; 'checking tom'; 'welcome tom!'; 'hi';
136
- # f.goodbye('jack') => 'checking jack'; 'goodbye jack!';
147
+ # f.welcome('jack') # => 'checking jack'; 'checking jack'; 'welcome jack!'; 'hi';
148
+ # f.goodbye('jack') # => 'checking jack'; 'goodbye jack!';
137
149
  def proxify(*methods, &block)
138
150
  raise ArgumentError, 'no block given' unless block_given?
139
151
  raise ArgumentError, 'no methods given' if methods.empty?
@@ -144,54 +156,97 @@ module Proxified
144
156
  end
145
157
  end
146
158
 
147
- # Removes +methods+ from the proxy.
159
+ # Unproxifies the given +methods+ removing them from the proxy module. If no
160
+ # +methods+ are given, all the _proxified_ _methods_ are removed.
148
161
  #
149
162
  # ======Examples
150
163
  #
151
164
  # class A
152
165
  # include Proxified
153
166
  #
154
- # proxify :welcome, :goodbye do |name|
155
- # check(name)
156
- # super(name)
167
+ # proxify :foo, :bar, :biz do
168
+ # super().upcase
157
169
  # end
158
170
  #
159
- # def check(name)
160
- # puts "checking #{name}"
171
+ # def foo
172
+ # 'foo'
161
173
  # end
162
174
  #
163
- # def welcome(name)
164
- # puts "welcome #{name}!"
175
+ # def bar
176
+ # 'bar'
165
177
  # end
166
178
  #
167
- # def goodbye(name)
168
- # puts "goodbye #{name}!"
179
+ # def biz
180
+ # 'biz'
169
181
  # end
170
182
  # end
171
183
  #
172
- # a = A.new
173
- # a.welcome('jack') => 'checking jack'; 'welcome jack!';
174
- # a.goodbye('jack') => 'checking jack'; 'goodbye jack!';
184
+ # A.unproxify(:foo)
185
+ # a.foo # => 'foo;
186
+ # a.bar # => 'BAR'
187
+ # a.biz # => 'BIZ'
175
188
  #
176
- # a.class.unproxify(:welcome)
177
- #
178
- # a.welcome('jack') => 'welcome jack!';
179
- # a.goodbye('jack') => 'checking jack'; 'goodbye jack!';
189
+ # A.unproxify
190
+ # a.foo # => 'foo;
191
+ # a.bar # => 'bar'
192
+ # a.biz # => 'biz'
180
193
  def unproxify(*methods)
194
+ methods = proxified_methods.keys if methods.empty?
195
+
181
196
  self.proxified_methods = proxified_methods.except(*methods)
182
197
 
183
198
  methods.each { |method| remove_proxy_method(method) }
184
199
  end
185
200
 
186
- # Checks whether +method+ has been proxified.
187
- def proxified?(method)
188
- method.in?(proxified_methods)
201
+ # If given no +method+, checks whether any instance method is _proxified_,
202
+ # otherwise it checks for the given +method+.
203
+ #
204
+ # ======Examples
205
+ #
206
+ # class A
207
+ # include Proxified
208
+ #
209
+ # proxify :foo, :bar do |name|
210
+ # super().upcase
211
+ # end
212
+ #
213
+ # def foo
214
+ # 'foo'
215
+ # end
216
+ #
217
+ # def bar
218
+ # 'bar'
219
+ # end
220
+ #
221
+ # def biz
222
+ # 'biz'
223
+ # end
224
+ # end
225
+ #
226
+ # A.proxified? # => true
227
+ # A.proxified?(:foo) # => true
228
+ # A.proxified?(:bar) # => true
229
+ # A.proxified?(:biz) # => false
230
+ #
231
+ # A.unproxify(:foo)
232
+ # A.proxified? # => true
233
+ # A.proxified?(:foo) # => false
234
+ # A.proxified?(:bar) # => true
235
+ # A.proxified?(:biz) # => false
236
+ #
237
+ # A.unproxify(:bar)
238
+ # A.proxified? # => false
239
+ # A.proxified?(:foo) # => false
240
+ # A.proxified?(:bar) # => false
241
+ # A.proxified?(:biz) # => false
242
+ def proxified?(method = nil)
243
+ method.nil? ? proxified_methods.any? : method.in?(proxified_methods)
189
244
  end
190
245
 
191
246
  private
192
247
 
193
248
  # Adds the +method+ to the proxy only if it has been proxified.
194
- def method_added(method)
249
+ def method_added(method) # :nodoc:
195
250
  # Don't do nothing if the attribute is not defined and initialized yet
196
251
  return unless respond_to?(:proxified_methods) && proxified_methods?
197
252
 
@@ -199,7 +254,7 @@ module Proxified
199
254
  end
200
255
 
201
256
  # Unproxifies the +method+ only if it has been proxified.
202
- def method_removed(method)
257
+ def method_removed(method) # :nodoc:
203
258
  # Don't do nothing if the attribute is not defined and initialized yet
204
259
  return unless respond_to?(:proxified_methods) && proxified_methods?
205
260
 
@@ -207,22 +262,375 @@ module Proxified
207
262
  end
208
263
 
209
264
  # Defines the +method+ in the proxy module.
210
- def add_proxy_method(method)
265
+ def add_proxy_method(method) # :nodoc:
211
266
  # Redefine to avoid warnings if the method has already been defined
212
267
  proxy.redefine_method(method, &proxified_methods[method])
213
268
  end
214
269
 
215
270
  # Removes the +method+ from the proxy module.
216
- def remove_proxy_method(method)
271
+ def remove_proxy_method(method) # :nodoc:
217
272
  proxy.remove_method(method) if proxy.method_defined?(method)
218
273
  end
219
274
 
220
275
  # Returns the proxy module prepending it only if it's not already present
221
276
  # in this class.
222
- def proxy
277
+ def proxy # :nodoc:
223
278
  return const_get('Proxy', false) if const_defined?('Proxy', false)
224
279
 
225
280
  const_set('Proxy', Module.new).tap { |proxy| prepend proxy }
226
281
  end
227
282
  end
228
283
  end
284
+
285
+ # Injects Proxified in the +receiver+ and _proxifies_ the given +methods+, or
286
+ # raises ArgumentError if no +block+ or no +methods+ are given.
287
+ #
288
+ # +receiver+ can be a class or an ordinary object.
289
+ #
290
+ # If +receiver+ is a class, it is equivalent to including Proxified and calling
291
+ # .proxify.
292
+ #
293
+ # If +receiver+ is an object, Proxified is injected in its singleton class and
294
+ # other objects of the same class will not be affected.
295
+ #
296
+ # If +receiver+ is an object of a _proxified_ class, the class' proxy is
297
+ # overridden but other objects of the class will not be affected.
298
+ #
299
+ # See Proxified.proxify for further details.
300
+ #
301
+ # ======Examples
302
+ #
303
+ # _Proxifying_ a class:
304
+ # class A
305
+ # def foo
306
+ # 'foo'
307
+ # end
308
+ #
309
+ # def bar
310
+ # 'bar'
311
+ # end
312
+ # end
313
+ #
314
+ # a1, a2 = A.new, A.new
315
+ #
316
+ # Proxify(A, :foo) { super().upcase }
317
+ # a1.foo # => 'FOO'
318
+ # a2.foo # => 'FOO'
319
+ # a1.bar # => 'bar'
320
+ # a2.bar # => 'bar'
321
+ #
322
+ #
323
+ # _Proxifying_ an object:
324
+ # class B
325
+ # def foo
326
+ # 'foo'
327
+ # end
328
+ #
329
+ # def bar
330
+ # 'bar'
331
+ # end
332
+ # end
333
+ #
334
+ # b1, b2 = B.new, B.new
335
+ #
336
+ # Proxify(b1, :foo) { super().upcase }
337
+ # b1.foo # => 'FOO'
338
+ # b2.foo # => 'foo'
339
+ # b1.bar # => 'bar'
340
+ # b2.bar # => 'bar'
341
+ #
342
+ #
343
+ # _Reproxifying_ an object of a _proxified_ class:
344
+ # class C
345
+ # def foo
346
+ # 'foo'
347
+ # end
348
+ #
349
+ # def bar
350
+ # 'bar'
351
+ # end
352
+ # end
353
+ #
354
+ # c1, c2 = C.new, C.new
355
+ #
356
+ # Proxify(C, :foo, :bar) { super().upcase }
357
+ #
358
+ # # the class proxy is overridden
359
+ # Proxify(c1, :foo) { 'proxified' }
360
+ # c1.foo # => 'proxified'
361
+ # c2.foo # => 'FOO'
362
+ # c1.bar # => 'BAR'
363
+ # c2.bar # => 'BAR'
364
+ #
365
+ # # if super is called the class' proxy will also be called
366
+ # Proxify(c1, :foo) { "i am a proxified #{super()}"}
367
+ # c1.foo # => 'i am a proxified FOO'
368
+ # c2.foo # => 'FOO'
369
+ # c1.bar # => 'BAR'
370
+ # c2.bar # => 'BAR'
371
+ def Proxify(receiver, *methods, &block)
372
+ raise ArgumentError, 'no block given' unless block_given?
373
+ raise ArgumentError, 'no methods given' if methods.empty?
374
+
375
+ target = receiver.is_a?(Class) ? receiver : receiver.singleton_class
376
+
377
+ target.include(Proxified).proxify(*methods, &block)
378
+ end
379
+
380
+ # If the +receiver+ is _proxified_ unproxifies the given +methods+, or all the
381
+ # _proxified_ _methods_ if no +methods+ are given.
382
+ #
383
+ # +receiver+ can be a class or an ordinary object.
384
+ #
385
+ # If +receiver+ is an object of a _proxified_ class only its (eventual) proxy
386
+ # methods will be removed and the proxy of the class will not be affected.
387
+ #
388
+ # See Proxified.unproxify for further details.
389
+ #
390
+ # ======Examples
391
+ #
392
+ # _Unproxifying_ a _proxified_ class:
393
+ # class A
394
+ # def foo
395
+ # 'foo'
396
+ # end
397
+ #
398
+ # def bar
399
+ # 'bar'
400
+ # end
401
+ #
402
+ # def biz
403
+ # 'biz'
404
+ # end
405
+ # end
406
+ #
407
+ # a1, a2 = A.new, A.new
408
+ #
409
+ # Proxify(A, :foo, :bar, :biz) { super().upcase }
410
+ #
411
+ # Unproxify(A, :foo)
412
+ # a1.foo # => 'foo'
413
+ # a2.foo # => 'foo'
414
+ # a1.bar # => 'BAR'
415
+ # a2.bar # => 'BAR'
416
+ # a1.biz # => 'BIZ'
417
+ # a2.biz # => 'BIZ'
418
+ #
419
+ # Unproxify(A)
420
+ # a1.foo # => 'foo'
421
+ # a2.foo # => 'foo'
422
+ # a1.bar # => 'bar'
423
+ # a2.bar # => 'bar'
424
+ # a1.biz # => 'biz'
425
+ # a2.biz # => 'biz'
426
+ #
427
+ #
428
+ # _Unproxifying_ a _proxified_ object:
429
+ # class B
430
+ # def foo
431
+ # 'foo'
432
+ # end
433
+ #
434
+ # def bar
435
+ # 'bar'
436
+ # end
437
+ #
438
+ # def biz
439
+ # 'biz'
440
+ # end
441
+ # end
442
+ #
443
+ # b1, b2 = B.new, B.new
444
+ #
445
+ # Proxify(b1, :foo, :bar, :biz) { super().upcase }
446
+ #
447
+ # Unproxify(b1, :foo)
448
+ # b1.foo # => 'foo'
449
+ # b2.foo # => 'foo'
450
+ # b1.bar # => 'BAR'
451
+ # b2.bar # => 'BAR'
452
+ # b1.biz # => 'BIZ'
453
+ # b2.biz # => 'BIZ'
454
+ #
455
+ # Unproxify(b1)
456
+ # b1.foo # => 'foo'
457
+ # b2.foo # => 'foo'
458
+ # b1.bar # => 'bar'
459
+ # b2.bar # => 'bar'
460
+ # b1.biz # => 'biz'
461
+ # b2.biz # => 'biz'
462
+ #
463
+ #
464
+ # Trying to _unproxify_ an object of a _proxified_ class:
465
+ # class C
466
+ # def foo
467
+ # 'foo'
468
+ # end
469
+ # end
470
+ #
471
+ # c1, c2 = C.new, C.new
472
+ #
473
+ # Proxify(C, :foo) { super().upcase }
474
+ #
475
+ # Unproxify(c1)
476
+ # c1.foo # => 'FOO' (does not work because an object cannot affect its class)
477
+ # c2.foo # => 'FOO'
478
+ #
479
+ #
480
+ # _Unproxifying_ a _reproxified_ object of a _proxified_ class:
481
+ # class D
482
+ # def foo
483
+ # 'foo'
484
+ # end
485
+ # end
486
+ #
487
+ # d1, d2 = D.new, D.new
488
+ #
489
+ # Proxify(D, :foo) { super().upcase }
490
+ #
491
+ # Proxify(d1, :foo) { 'proxified'}
492
+ #
493
+ # Unproxify(d1)
494
+ # d1.foo # => 'FOO' (the class proxy is restored)
495
+ # d2.foo # => 'FOO'
496
+ def Unproxify(receiver, *methods)
497
+ target = receiver.is_a?(Class) ? receiver : receiver.singleton_class
498
+
499
+ Proxified?(target) ? target.unproxify(*methods) : methods
500
+ end
501
+
502
+ # If given no +method+, checks whether any of the +receiver+'s instance
503
+ # methods is _proxified_, otherwise it checks for the given +method+.
504
+ #
505
+ # +receiver+ can be a class or an ordinary object.
506
+ #
507
+ # If +receiver+ is an object of a _proxified_ class and the class has at least a
508
+ # _proxified_ method, will return true even when the +receiver+ has no
509
+ # _proxified_ methods.
510
+ #
511
+ # See Proxified.proxified? for further details.
512
+ #
513
+ # ======Examples
514
+ #
515
+ # Checking if a class is _proxified_:
516
+ # class A
517
+ # def foo
518
+ # 'foo'
519
+ # end
520
+ #
521
+ # def bar
522
+ # 'bar'
523
+ # end
524
+ # end
525
+ #
526
+ # Proxified?(A) # => false
527
+ # Proxified?(A, :foo) # => false
528
+ # Proxified?(A, :bar) # => false
529
+ #
530
+ # Proxify(A, :foo, :bar) { 'proxified' }
531
+ # Proxified?(A) # => true
532
+ # Proxified?(A, :foo) # => true
533
+ # Proxified?(A, :bar) # => true
534
+ #
535
+ # Unproxify(A, :foo)
536
+ # Proxified?(A) # => true
537
+ # Proxified?(A, :foo) # => false
538
+ # Proxified?(A, :bar) # => true
539
+ #
540
+ # Unproxify(A, :bar)
541
+ # Proxified?(A) # => false
542
+ # Proxified?(A, :foo) # => false
543
+ # Proxified?(A, :bar) # => false
544
+ #
545
+ #
546
+ # Checking if an object is _proxified_:
547
+ # class B
548
+ # def foo
549
+ # 'foo'
550
+ # end
551
+ #
552
+ # def bar
553
+ # 'bar'
554
+ # end
555
+ # end
556
+ #
557
+ # b1, b2 = B.new, B.new
558
+ #
559
+ # Proxified?(b1) # => false
560
+ # Proxified?(b1, :foo) # => false
561
+ # Proxified?(b1, :bar) # => false
562
+ # Proxified?(b2) # => false
563
+ # Proxified?(b2, :foo) # => false
564
+ # Proxified?(b2, :bar) # => false
565
+ #
566
+ # Proxify(b1, :foo) { 'proxified' }
567
+ # Proxified?(b1) # => true
568
+ # Proxified?(b1, :foo) # => true
569
+ # Proxified?(b1, :bar) # => false
570
+ # Proxified?(b2) # => false
571
+ # Proxified?(b2, :foo) # => false
572
+ # Proxified?(b2, :bar) # => false
573
+ #
574
+ # Unproxify(b1)
575
+ # Proxified?(b1) # => false
576
+ # Proxified?(b1, :foo) # => false
577
+ # Proxified?(b1, :bar) # => false
578
+ # Proxified?(b2) # => false
579
+ # Proxified?(b2, :foo) # => false
580
+ # Proxified?(b2, :bar) # => false
581
+ #
582
+ #
583
+ # Checking if an object of a _proxified_ class is _proxified_:
584
+ # class C
585
+ # def foo
586
+ # 'foo'
587
+ # end
588
+ #
589
+ # def bar
590
+ # 'bar'
591
+ # end
592
+ # end
593
+ #
594
+ # c1, c2 = C.new, C.new
595
+ #
596
+ # Proxify(C, :foo) { 'proxified' }
597
+ #
598
+ # Proxified?(c1) # => true
599
+ # Proxified?(c1, :foo) # => true
600
+ # Proxified?(c1, :bar) # => false
601
+ # Proxified?(c2) # => true
602
+ # Proxified?(c2, :foo) # => true
603
+ # Proxified?(c2, :bar) # => false
604
+ #
605
+ # Unproxify(c1)
606
+ # Proxified?(c1) # => true (the class is not affected)
607
+ # Proxified?(c1, :foo) # => true
608
+ # Proxified?(c1, :bar) # => false
609
+ # Proxified?(c2) # => true
610
+ # Proxified?(c2, :foo) # => true
611
+ # Proxified?(c2, :bar) # => false
612
+ #
613
+ # Unproxify(C)
614
+ # Proxified?(c1) # => false
615
+ # Proxified?(c1, :foo) # => false
616
+ # Proxified?(c1, :bar) # => false
617
+ # Proxified?(c2) # => false
618
+ # Proxified?(c2, :foo) # => false
619
+ # Proxified?(c2, :bar) # => false
620
+ #
621
+ # Proxify(c1, :foo) { 'proxified' }
622
+ # Unproxify(C)
623
+ # Proxified?(c1) # => true (is not affected by the class)
624
+ # Proxified?(c1, :foo) # => true
625
+ # Proxified?(c1, :bar) # => false
626
+ # Proxified?(c2) # => false
627
+ # Proxified?(c2, :foo) # => false
628
+ # Proxified?(c2, :bar) # => false
629
+ def Proxified?(receiver, method = nil)
630
+ if receiver.is_a?(Class)
631
+ receiver.include?(Proxified) && receiver.proxified?(method)
632
+ else
633
+ Proxified?(receiver.singleton_class, method) ||
634
+ Proxified?(receiver.class, method)
635
+ end
636
+ end