hookable 0.0.5

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.
@@ -0,0 +1,11 @@
1
+ = Hookable
2
+
3
+ Patch any method with before, after and around hooks.
4
+
5
+ == Installation
6
+
7
+ $ sudo gem install hookable --source http://gemcutter.org
8
+
9
+ == Usage
10
+
11
+ Still very alpha, documentation will come later.
@@ -0,0 +1,20 @@
1
+ require "rake/testtask"
2
+
3
+ begin
4
+ require "hanna/rdoctask"
5
+ rescue LoadError
6
+ require "rake/rdoctask"
7
+ end
8
+
9
+ task :default => [:test]
10
+
11
+ Rake::TestTask.new do |t|
12
+ t.test_files = Dir["test/*_test.rb"]
13
+ end
14
+
15
+ Rake::RDocTask.new do |t|
16
+ t.title = "Hookable Documentation"
17
+ t.main = "README.rdoc"
18
+ t.rdoc_files.include("README.rdoc", "lib/**/*.rb")
19
+ t.rdoc_dir = "doc"
20
+ end
@@ -0,0 +1,141 @@
1
+ require 'rubygems'
2
+ require 'kinda-core'
3
+
4
+ module Kinda
5
+ module Hookable
6
+ include Core
7
+
8
+ ClassMethods = inheritable_extend do
9
+ [:before, :after, :around].each do |kind|
10
+ define_method(kind) do |method_name, &block|
11
+ add_hook(kind, method_name, &block)
12
+ end
13
+ end
14
+
15
+ alias_method :on, :after
16
+
17
+ def method_hooked?(method_name)
18
+ self_and_ancestors.each do |ancestor|
19
+ ancestor.is_a?(Module) ? next : break unless ancestor.respond_to?(:hooked_methods)
20
+ return true if ancestor.hooked_methods.include?(method_name)
21
+ end
22
+ false
23
+ end
24
+
25
+ protected
26
+
27
+ def hooked_methods
28
+ @hooked_methods ||= Hash.new do |hash, method_name|
29
+ hash[method_name] = Hookable::HookedMethod.new(self, method_name)
30
+ end
31
+ end
32
+
33
+ def patch_method(method_name)
34
+ return if Thread.current[:__adding_method__]
35
+ # puts "Patching method ##{method_name} in #{self.inspect}"
36
+ original_method = instance_method(method_name)
37
+ Thread.current[:__adding_method__] = true
38
+ define_method(method_name) do |*args, &block|
39
+ singleton_class_send(:exec_method, method_name, original_method, self, *args, &block)
40
+ end
41
+ Thread.current[:__adding_method__] = false
42
+ hooked_methods[method_name].method_patched = true
43
+ end
44
+
45
+ private
46
+
47
+ def add_hook(kind, method_name, &block)
48
+ hooked_methods[method_name.to_sym].hooks[kind] << block
49
+ patch_method_if_necessary(method_name.to_sym)
50
+ end
51
+
52
+ def exec_method(method_name, original_method, original_self, *args, &block)
53
+ result = nil
54
+
55
+ chained_hooks = [] << lambda do |*args, &block|
56
+ find_hooks(method_name, :before).each do |hook|
57
+ original_self.call_with_this(hook, *args, &block)
58
+ end
59
+ result = original_method.bind(original_self).call(*args, &block) if original_method
60
+ find_hooks(method_name, :after).each do |hook|
61
+ original_self.call_with_this(hook, *args, &block)
62
+ end
63
+ end
64
+
65
+ hooks = find_hooks(method_name, :around)
66
+ hooks.each_index do |index|
67
+ chained_hooks << lambda do |*args, &block|
68
+ original_self.call_with_this(hooks[index], chained_hooks[index], *args, &block)
69
+ end
70
+ end
71
+ chained_hooks.last.call(*args, &block)
72
+
73
+ result
74
+ end
75
+
76
+ def find_hooks(method_name, kind)
77
+ hooks = []
78
+ self_and_ancestors.each do |ancestor|
79
+ ancestor.is_a?(Module) ? next : break unless ancestor.respond_to?(:hooked_methods)
80
+ next unless ancestor.hooked_methods.include?(method_name)
81
+ next unless ancestor.hooked_methods[method_name].hooks.include?(kind)
82
+ hooks.concat(ancestor.hooked_methods[method_name].hooks[kind])
83
+ end
84
+ hooks
85
+ end
86
+
87
+ def method_added(method_name)
88
+ super
89
+ if method_hooked?(method_name)
90
+ patch_method(method_name)
91
+ end
92
+ end
93
+
94
+ def patch_method_if_necessary(method_name)
95
+ self_and_ancestors.each do |ancestor|
96
+ ancestor.is_a?(Module) ? next : break unless ancestor.respond_to?(:patch_method)
97
+ method_defined_in_this_class = ancestor.instance_method(method_name).owner == ancestor rescue false
98
+ if method_defined_in_this_class
99
+ ancestor.patch_method(method_name) unless ancestor.hooked_methods[method_name].method_patched
100
+ break
101
+ end
102
+ end
103
+ end
104
+ end
105
+
106
+ ###
107
+
108
+ delegate_to_class ClassMethods.public_instance_methods
109
+ delegate_to_class :singleton_method_added => :method_added
110
+
111
+ def respond_to?(method_name, include_private=false)
112
+ super || method_hooked?(method_name)
113
+ end
114
+
115
+ private
116
+
117
+ def method_missing(method_name, *args, &block)
118
+ if method_hooked?(method_name)
119
+ singleton_class_send(:exec_method, method_name, nil, self, *args, &block)
120
+ else
121
+ super
122
+ end
123
+ end
124
+
125
+ ###
126
+
127
+ class HookedMethod
128
+ attr_reader :klass, :name
129
+ attr_accessor :method_patched
130
+
131
+ def initialize(klass, name)
132
+ @klass = klass
133
+ @name = name
134
+ end
135
+
136
+ def hooks
137
+ @hooks ||= Hash.new { |hash, kind| hash[kind] = [] }
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), 'hookable')
@@ -0,0 +1,567 @@
1
+ #!/usr/bin/ruby19
2
+ # encoding: utf-8
3
+
4
+ require 'test/unit'
5
+
6
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')).uniq!
7
+ require 'kinda-hookable'
8
+
9
+ class HookableClassTest < Test::Unit::TestCase
10
+ def setup
11
+ @simple_class = Class.new do
12
+ include Kinda::Hookable
13
+ end
14
+
15
+ @simple = @simple_class.new
16
+ end
17
+
18
+ def test_no_method_error
19
+ assert_raise NoMethodError do
20
+ @simple.hello
21
+ end
22
+ end
23
+
24
+ def test_before
25
+ result = []
26
+ @simple.before(:hello) { result << 'before' }
27
+ @simple.hello
28
+ assert_equal ['before'], result
29
+ end
30
+
31
+ def test_before_and_after
32
+ result = []
33
+ @simple.before(:hello) { result << 'before' }
34
+ @simple.after(:hello) { result << 'after' }
35
+ @simple.hello
36
+ assert_equal ['before', 'after'], result
37
+ end
38
+
39
+ def test_before_after_and_around
40
+ result = []
41
+ @simple.before(:hello) { result << 'before' }
42
+ @simple.after(:hello) { result << 'after' }
43
+ @simple.around(:hello) do |original_method|
44
+ result << 'around begin'
45
+ original_method.call
46
+ result << 'around end'
47
+ end
48
+ @simple.hello
49
+ assert_equal ['around begin', 'before', 'after', 'around end'], result
50
+ end
51
+
52
+ def test_respond_to
53
+ assert @simple.respond_to?(:before)
54
+ @simple.before(:hello) { result << 'before' }
55
+ assert @simple.respond_to?(:hello)
56
+ assert !@simple.respond_to?(:undefined_method)
57
+ end
58
+ end
59
+
60
+ ###
61
+
62
+ class HookableClassWithAMethodTest < Test::Unit::TestCase
63
+ def setup
64
+ @simple_class = Class.new do
65
+ include Kinda::Hookable
66
+
67
+ attr_accessor :result
68
+
69
+ def initialize
70
+ @result = []
71
+ end
72
+
73
+ def hello
74
+ @result << 'hello'
75
+ end
76
+ end
77
+
78
+ @simple = @simple_class.new
79
+ end
80
+
81
+ def test_hello
82
+ @simple.hello
83
+ assert_equal ['hello'], @simple.result
84
+ end
85
+
86
+ def test_before
87
+ @simple.before(:hello) { this.result << 'before' }
88
+ @simple.hello
89
+ assert_equal ['before', 'hello'], @simple.result
90
+ end
91
+
92
+ def test_two_befores
93
+ @simple.before(:hello) { this.result << 'before 1' }
94
+ @simple.before(:hello) { this.result << 'before 2' }
95
+ @simple.hello
96
+ assert_equal ['before 1', 'before 2', 'hello'], @simple.result
97
+ end
98
+
99
+ def test_before_after_and_around
100
+ @simple.before(:hello) { this.result << 'before' }
101
+ @simple.after(:hello) { this.result << 'after' }
102
+ @simple.around(:hello) do |original_method|
103
+ this.result << 'around begin'
104
+ original_method.call
105
+ this.result << 'around end'
106
+ end
107
+ @simple.hello
108
+ assert_equal ['around begin', 'before', 'hello', 'after', 'around end'], @simple.result
109
+ end
110
+
111
+ def test_two_arounds
112
+ @simple.around(:hello) do |original_method|
113
+ this.result << 'around 1 begin'
114
+ original_method.call
115
+ this.result << 'around 1 end'
116
+ end
117
+ @simple.around(:hello) do |original_method|
118
+ this.result << 'around 2 begin'
119
+ original_method.call
120
+ this.result << 'around 2 end'
121
+ end
122
+ @simple.hello
123
+ assert_equal ['around 2 begin', 'around 1 begin', 'hello',
124
+ 'around 1 end', 'around 2 end'], @simple.result
125
+ end
126
+
127
+ def test_respond_to
128
+ assert @simple.respond_to?(:hello)
129
+ end
130
+ end
131
+
132
+ ###
133
+
134
+ class HookableClassWithAMethodWithParametersAndResultTest < Test::Unit::TestCase
135
+ def setup
136
+ @simple_class = Class.new do
137
+ include Kinda::Hookable
138
+
139
+ attr_accessor :result
140
+
141
+ def initialize
142
+ @result = []
143
+ end
144
+
145
+ def hello(first_name, last_name)
146
+ greeting = "hello #{first_name} #{last_name}"
147
+ @result << greeting
148
+ greeting
149
+ end
150
+ end
151
+
152
+ @simple = @simple_class.new
153
+ end
154
+
155
+ def test_hello
156
+ greeting = @simple.hello('Manuel', 'Vila')
157
+ assert_equal 'hello Manuel Vila', greeting
158
+ assert_equal ['hello Manuel Vila'], @simple.result
159
+ end
160
+
161
+ def test_before
162
+ @simple.before(:hello) { |first, last| this.result << "before hello #{first} #{last}" }
163
+ greeting = @simple.hello('Manuel', 'Vila')
164
+ assert_equal 'hello Manuel Vila', greeting
165
+ assert_equal ['before hello Manuel Vila', 'hello Manuel Vila'], @simple.result
166
+ end
167
+
168
+ def test_after
169
+ @simple.after(:hello) { |first, last| this.result << "after hello #{first} #{last}" }
170
+ greeting = @simple.hello('Manuel', 'Vila')
171
+ assert_equal 'hello Manuel Vila', greeting
172
+ assert_equal ['hello Manuel Vila', 'after hello Manuel Vila'], @simple.result
173
+ end
174
+
175
+ def test_before_and_around
176
+ @simple.before(:hello) { |first, last| this.result << "before hello #{first} #{last}" }
177
+ @simple.around(:hello) do |original_method, first, last|
178
+ this.result << "around hello #{first} #{last} begin"
179
+ original_method.call(first, last)
180
+ this.result << "around hello #{first} #{last} end"
181
+ end
182
+ greeting = @simple.hello('Manuel', 'Vila')
183
+ assert_equal 'hello Manuel Vila', greeting
184
+ assert_equal ['around hello Manuel Vila begin', 'before hello Manuel Vila',
185
+ 'hello Manuel Vila', 'around hello Manuel Vila end'], @simple.result
186
+ end
187
+ end
188
+
189
+ ###
190
+
191
+ class HookableSuperClassTest < Test::Unit::TestCase
192
+ def setup
193
+ @super_simple_class = Class.new do
194
+ include Kinda::Hookable
195
+
196
+ attr_accessor :result
197
+
198
+ def initialize
199
+ @result = []
200
+ end
201
+ end
202
+
203
+ @simple_class = Class.new(@super_simple_class)
204
+
205
+ @simple = @simple_class.new
206
+ end
207
+
208
+ def test_before_in_superclass
209
+ @super_simple_class.class_eval { before(:hello) { this.result << self } }
210
+ @simple.hello
211
+ assert_equal [@simple.class.superclass], @simple.result
212
+ end
213
+
214
+ def test_respond_to_with_before_in_superclass
215
+ @super_simple_class.class_eval { before(:hello) { this.result << self } }
216
+ assert @simple.respond_to?(:hello)
217
+ end
218
+
219
+ def test_before_in_class
220
+ @simple_class.class_eval { before(:hello) { this.result << self } }
221
+ @simple.hello
222
+ assert_equal [@simple.class], @simple.result
223
+ end
224
+
225
+ def test_respond_to_with_before_in_class
226
+ @simple_class.class_eval { before(:hello) { this.result << self } }
227
+ assert @simple.respond_to?(:hello)
228
+ end
229
+
230
+ def test_before_in_singleton_class
231
+ @simple.before(:hello) { this.result << self }
232
+ @simple.hello
233
+ assert_equal [self], @simple.result
234
+ end
235
+
236
+ def test_before_in_superclass_class_and_singleton_class
237
+ @super_simple_class.class_eval { before(:hello) { this.result << self } }
238
+ @simple_class.class_eval { before(:hello) { this.result << self } }
239
+ @simple.before(:hello) { this.result << self }
240
+ @simple.hello
241
+ assert_equal [self, @simple.class, @simple.class.superclass], @simple.result
242
+ end
243
+ end
244
+
245
+ ###
246
+
247
+ class HookableSuperClassWithAMethodTest < Test::Unit::TestCase
248
+ def setup
249
+ @super_simple_class = Class.new do
250
+ include Kinda::Hookable
251
+
252
+ attr_accessor :result
253
+
254
+ def initialize
255
+ @result = []
256
+ end
257
+
258
+ def hello
259
+ @result << 'hello'
260
+ end
261
+ end
262
+
263
+ @simple_class = Class.new(@super_simple_class)
264
+
265
+ @simple = @simple_class.new
266
+ end
267
+
268
+ def test_respond_to
269
+ assert @simple.respond_to?(:hello)
270
+ end
271
+
272
+ def test_before_in_superclass
273
+ @super_simple_class.class_eval { before(:hello) { this.result << self } }
274
+ @simple.hello
275
+ assert_equal [@simple.class.superclass, 'hello'], @simple.result
276
+ end
277
+
278
+ def test_respond_to_with_before_in_superclass
279
+ @super_simple_class.class_eval { before(:hello) { this.result << self } }
280
+ assert @simple.respond_to?(:hello)
281
+ end
282
+
283
+ def test_before_in_class
284
+ @simple_class.class_eval { before(:hello) { this.result << self } }
285
+ @simple.hello
286
+ assert_equal [@simple.class, 'hello'], @simple.result
287
+ end
288
+
289
+ def test_respond_to_with_before_in_class
290
+ @simple_class.class_eval { before(:hello) { this.result << self } }
291
+ assert @simple.respond_to?(:hello)
292
+ end
293
+
294
+ def test_before_in_singleton_class
295
+ @simple.before(:hello) { this.result << self }
296
+ @simple.hello
297
+ assert_equal [self, 'hello'], @simple.result
298
+ end
299
+
300
+ def test_before_in_superclass_class_and_singleton_class
301
+ @super_simple_class.class_eval { before(:hello) { this.result << self } }
302
+ @simple_class.class_eval { before(:hello) { this.result << self } }
303
+ @simple.before(:hello) { this.result << self }
304
+ @simple.hello
305
+ assert_equal [self, @simple.class, @simple.class.superclass, 'hello'], @simple.result
306
+ end
307
+ end
308
+
309
+ ###
310
+
311
+ class HookableSuperClassWithAMethodInClassTest < Test::Unit::TestCase
312
+ def setup
313
+ @super_simple_class = Class.new do
314
+ include Kinda::Hookable
315
+
316
+ attr_accessor :result
317
+
318
+ def initialize
319
+ @result = []
320
+ end
321
+ end
322
+
323
+ @simple_class = Class.new(@super_simple_class) do
324
+ def hello
325
+ @result << 'hello'
326
+ end
327
+ end
328
+
329
+ @simple = @simple_class.new
330
+ end
331
+
332
+ def test_respond_to
333
+ assert @simple.respond_to?(:hello)
334
+ end
335
+
336
+ def test_before_in_superclass
337
+ @super_simple_class.class_eval { before(:hello) { this.result << self } }
338
+ @simple.hello
339
+ assert_equal ['hello'], @simple.result
340
+ end
341
+
342
+ def test_before_in_class
343
+ @simple_class.class_eval { before(:hello) { this.result << self } }
344
+ @simple.hello
345
+ assert_equal [@simple.class, 'hello'], @simple.result
346
+ end
347
+
348
+ def test_before_in_singleton_class
349
+ @simple.before(:hello) { this.result << self }
350
+ @simple.hello
351
+ assert_equal [self, 'hello'], @simple.result
352
+ end
353
+
354
+ def test_before_in_superclass_class_and_singleton_class
355
+ @super_simple_class.class_eval { before(:hello) { this.result << self } }
356
+ @simple_class.class_eval { before(:hello) { this.result << self } }
357
+ @simple.before(:hello) { this.result << self }
358
+ @simple.hello
359
+ assert_equal [self, @simple.class, @simple.class.superclass, 'hello'], @simple.result
360
+ end
361
+ end
362
+
363
+ ###
364
+
365
+ class HookableSuperClassWithAMethodInSingletonClassTest < Test::Unit::TestCase
366
+ def setup
367
+ @super_simple_class = Class.new do
368
+ include Kinda::Hookable
369
+
370
+ attr_accessor :result
371
+
372
+ def initialize
373
+ @result = []
374
+ end
375
+ end
376
+
377
+ @simple_class = Class.new(@super_simple_class)
378
+
379
+ @simple = @simple_class.new
380
+
381
+ def @simple.hello
382
+ @result << 'hello'
383
+ end
384
+ end
385
+
386
+ def test_respond_to
387
+ assert @simple.respond_to?(:hello)
388
+ end
389
+
390
+ def test_before_in_superclass
391
+ @super_simple_class.class_eval { before(:hello) { this.result << self } }
392
+ @simple.hello
393
+ assert_equal ['hello'], @simple.result
394
+ end
395
+
396
+ def test_before_in_class
397
+ @simple_class.class_eval { before(:hello) { this.result << self } }
398
+ @simple.hello
399
+ assert_equal ['hello'], @simple.result
400
+ end
401
+
402
+ def test_before_in_singleton_class
403
+ @simple.before(:hello) { this.result << self }
404
+ @simple.hello
405
+ assert_equal [self, 'hello'], @simple.result
406
+ end
407
+
408
+ def test_before_in_superclass_class_and_singleton_class
409
+ @super_simple_class.class_eval { before(:hello) { this.result << self } }
410
+ @simple_class.class_eval { before(:hello) { this.result << self } }
411
+ @simple.before(:hello) { this.result << self }
412
+ @simple.hello
413
+ assert_equal [self, @simple.class, @simple.class.superclass, 'hello'], @simple.result
414
+ end
415
+ end
416
+
417
+ ###
418
+
419
+ class HookableModuleTest < Test::Unit::TestCase
420
+ def setup
421
+ @super_simple_class = Class.new do
422
+ include Kinda::Hookable
423
+
424
+ attr_accessor :result
425
+
426
+ def initialize
427
+ @result = []
428
+ end
429
+ end
430
+
431
+ @simple_module = Module.new do
432
+ include Kinda::Hookable
433
+ end
434
+
435
+ @simple_class = Class.new(@super_simple_class)
436
+ @simple_class.send(:include, @simple_module)
437
+
438
+ @simple = @simple_class.new
439
+ end
440
+
441
+ def test_before_in_superclass
442
+ @super_simple_class.class_eval { before(:hello) { this.result << self } }
443
+ @simple.hello
444
+ assert_equal [@simple.class.superclass], @simple.result
445
+ end
446
+
447
+ def test_respond_to_with_before_in_superclass
448
+ @super_simple_class.class_eval { before(:hello) { this.result << self } }
449
+ assert @simple.respond_to?(:hello)
450
+ end
451
+
452
+ def test_before_in_module
453
+ @simple_module.module_eval { before(:hello) { this.result << self } }
454
+ @simple.hello
455
+ assert_equal [@simple_module], @simple.result
456
+ end
457
+
458
+ def test_respond_to_with_before_in_module
459
+ @simple_module.module_eval { before(:hello) { this.result << self } }
460
+ assert @simple.respond_to?(:hello)
461
+ end
462
+
463
+ def test_before_in_class
464
+ @simple_class.class_eval { before(:hello) { this.result << self } }
465
+ @simple.hello
466
+ assert_equal [@simple.class], @simple.result
467
+ end
468
+
469
+ def test_respond_to_with_before_in_class
470
+ @simple_class.class_eval { before(:hello) { this.result << self } }
471
+ assert @simple.respond_to?(:hello)
472
+ end
473
+
474
+ def test_before_in_singleton_class
475
+ @simple.before(:hello) { this.result << self }
476
+ @simple.hello
477
+ assert_equal [self], @simple.result
478
+ end
479
+
480
+ def test_before_in_superclass_class_and_singleton_class
481
+ @super_simple_class.class_eval { before(:hello) { this.result << self } }
482
+ @simple_class.class_eval { before(:hello) { this.result << self } }
483
+ @simple.before(:hello) { this.result << self }
484
+ @simple.hello
485
+ assert_equal [self, @simple.class, @simple.class.superclass], @simple.result
486
+ end
487
+ end
488
+
489
+ ###
490
+
491
+ class HookableModuleWithAMethodTest < Test::Unit::TestCase
492
+ def setup
493
+ @super_simple_class = Class.new do
494
+ include Kinda::Hookable
495
+
496
+ attr_accessor :result
497
+
498
+ def initialize
499
+ @result = []
500
+ end
501
+ end
502
+
503
+ @simple_module = Module.new do
504
+ include Kinda::Hookable
505
+
506
+ def hello
507
+ @result << 'hello'
508
+ end
509
+ end
510
+
511
+ @simple_class = Class.new(@super_simple_class)
512
+ @simple_class.send(:include, @simple_module)
513
+
514
+ @simple = @simple_class.new
515
+ end
516
+
517
+ def test_respond_to
518
+ assert @simple.respond_to?(:hello)
519
+ end
520
+
521
+ def test_before_in_superclass
522
+ @super_simple_class.class_eval { before(:hello) { this.result << self } } # not executed
523
+ @simple.hello
524
+ assert_equal ['hello'], @simple.result
525
+ end
526
+
527
+ def test_respond_to_with_before_in_superclass
528
+ @super_simple_class.class_eval { before(:hello) { this.result << self } }
529
+ assert @simple.respond_to?(:hello)
530
+ end
531
+
532
+ def test_before_in_module
533
+ @simple_module.module_eval { before(:hello) { this.result << self } }
534
+ @simple.hello
535
+ assert_equal [@simple_module, 'hello'], @simple.result
536
+ end
537
+
538
+ def test_respond_to_with_before_in_module
539
+ @simple_module.module_eval { before(:hello) { this.result << self } }
540
+ assert @simple.respond_to?(:hello)
541
+ end
542
+
543
+ def test_before_in_class
544
+ @simple_class.class_eval { before(:hello) { this.result << self } }
545
+ @simple.hello
546
+ assert_equal [@simple.class, 'hello'], @simple.result
547
+ end
548
+
549
+ def test_respond_to_with_before_in_class
550
+ @simple_class.class_eval { before(:hello) { this.result << self } }
551
+ assert @simple.respond_to?(:hello)
552
+ end
553
+
554
+ def test_before_in_singleton_class
555
+ @simple.before(:hello) { this.result << self }
556
+ @simple.hello
557
+ assert_equal [self, 'hello'], @simple.result
558
+ end
559
+
560
+ def test_before_in_superclass_class_and_singleton_class
561
+ @super_simple_class.class_eval { before(:hello) { this.result << self } }
562
+ @simple_class.class_eval { before(:hello) { this.result << self } }
563
+ @simple.before(:hello) { this.result << self }
564
+ @simple.hello
565
+ assert_equal [self, @simple.class, @simple.class.superclass, 'hello'], @simple.result
566
+ end
567
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hookable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.5
5
+ platform: ruby
6
+ authors:
7
+ - Manuel Vila
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-12 00:00:00 +02:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: kinda-core
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.1
24
+ version:
25
+ description: Patch any method with before, after and around hooks
26
+ email: mvila@3base.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README.rdoc
33
+ files:
34
+ - Rakefile
35
+ - lib/hookable.rb
36
+ - lib/kinda-hookable.rb
37
+ - README.rdoc
38
+ has_rdoc: true
39
+ homepage: http://github.com/kinda/hookable
40
+ licenses: []
41
+
42
+ post_install_message:
43
+ rdoc_options: []
44
+
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: 1.9.1
52
+ version:
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ requirements: []
60
+
61
+ rubyforge_project: kinda-hookable
62
+ rubygems_version: 1.3.5
63
+ signing_key:
64
+ specification_version: 3
65
+ summary: Patch any method with before, after and around hooks
66
+ test_files:
67
+ - test/hookable_test.rb