proxified 0.1.0 → 1.0.1

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/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