watch_methods 0.0.4
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/.gitignore +4 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/README.md +63 -0
- data/Rakefile +10 -0
- data/examples/array.rb +17 -0
- data/examples/before_and_after_declartion.rb +25 -0
- data/examples/callbacks.rb +65 -0
- data/examples/class_methods.rb +48 -0
- data/examples/combination.rb +27 -0
- data/examples/regex.rb +21 -0
- data/examples/simple.rb +13 -0
- data/examples/test_framework.rb +36 -0
- data/examples/watch_only_once.rb +16 -0
- data/lib/watch_methods/version.rb +3 -0
- data/lib/watch_methods.rb +76 -0
- data/spec/method_added_hook_spec.rb +364 -0
- data/spec/spec_helper.rb +2 -0
- data/watch_methods.gemspec +24 -0
- metadata +88 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
watch_methods
|
2
|
+
=============
|
3
|
+
|
4
|
+
## What is this thing?
|
5
|
+
|
6
|
+
Monitor when methods are added to classes or modules and take action when they do.
|
7
|
+
|
8
|
+
## Why would I want this?
|
9
|
+
You are:
|
10
|
+
|
11
|
+
- developing a kick-ass gem and you want your users to use your class methods before methods are actually defined (think AR validators, callback etc.)
|
12
|
+
- Want to monitor all methods starting with queue_ for your new awesome queueing gem.
|
13
|
+
- and more!
|
14
|
+
|
15
|
+
##Install
|
16
|
+
|
17
|
+
[sudo] gem install method_added_hook
|
18
|
+
|
19
|
+
|
20
|
+
### Skip all the crap, give me the examples.
|
21
|
+
[Examples](https://github.com/mikelewis/method_added_hook/tree/master/examples)
|
22
|
+
|
23
|
+
##Usage
|
24
|
+
The method that you'll be interacting with is the `watch_methods` method that is defined as:
|
25
|
+
|
26
|
+
watch_methods(methods, opts={}, &blk)
|
27
|
+
|
28
|
+
Where:
|
29
|
+
|
30
|
+
- methods can be a symbol, string, array, regex or any combination. This will be all the methods you want to monitor.
|
31
|
+
|
32
|
+
- opts currently has two optional parameters `:class_methods` to watch for class methods and `:once` to
|
33
|
+
only run the given block once for a given method.
|
34
|
+
|
35
|
+
- a given block, which will get run after a given method to watch was added.
|
36
|
+
|
37
|
+
Here are some valid uses of `watch_methods`:
|
38
|
+
|
39
|
+
watch_methods(:special_func1, :special_func2) do |meth|
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
# this will watch any class method starting with test_, queue_
|
45
|
+
watch_methods(/^test_.+$/, /^queue_.+$/, :class _methods => true) do |meth|
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
watch_methods([:meth_one, :meth_two]) do |meth|
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
or a combination of all of the above:
|
54
|
+
|
55
|
+
watch_methods(:special_func, /^test_meth$/, [:meth1, :meth2]) do |meth|
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
To see all examples/cases, see the examples directory and the spec file.
|
60
|
+
|
61
|
+
###Supports
|
62
|
+
Ruby 1.8.7, 1.9.2, 1.9.3
|
63
|
+
|
data/Rakefile
ADDED
data/examples/array.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'watch_methods'
|
2
|
+
|
3
|
+
class BeforeAndAfter
|
4
|
+
watch_methods :yo do |meth|
|
5
|
+
puts "yo was added!"
|
6
|
+
end
|
7
|
+
|
8
|
+
def yo
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
def hey
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
watch_methods :hey do |meth|
|
17
|
+
puts "Hey was added!"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# Prints
|
23
|
+
# yo was added!
|
24
|
+
# Hey was added!
|
25
|
+
#
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'watch_methods'
|
2
|
+
|
3
|
+
module Callbacks
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
[:after, :before].each do |action|
|
10
|
+
define_method(action) do |*args|
|
11
|
+
meth, opts = args
|
12
|
+
watch_methods meth, :once => true do |m|
|
13
|
+
register_callback(action, m, opts)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def register_callback(type, meth, opts={})
|
19
|
+
alias_method :"old_#{meth}", meth
|
20
|
+
before_proc, after_proc = [proc{}] * 2
|
21
|
+
case type
|
22
|
+
when :after
|
23
|
+
after_proc = proc { send(opts[:do]) }
|
24
|
+
when :before
|
25
|
+
before_proc = proc { send(opts[:do]) }
|
26
|
+
end
|
27
|
+
|
28
|
+
define_method(meth) do |*args, &blk|
|
29
|
+
instance_eval &before_proc
|
30
|
+
send(:"old_#{meth}", *args, &blk)
|
31
|
+
instance_eval &after_proc
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class Test
|
38
|
+
include Callbacks
|
39
|
+
after :jump, :do => :crawl
|
40
|
+
before :crawl, :do => :stretch
|
41
|
+
|
42
|
+
def jump
|
43
|
+
puts "I'm jumpin"
|
44
|
+
end
|
45
|
+
|
46
|
+
def stretch
|
47
|
+
puts "I'm stretchin"
|
48
|
+
end
|
49
|
+
|
50
|
+
def crawl
|
51
|
+
puts "I'm crawlin"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
t = Test.new
|
57
|
+
|
58
|
+
t.jump
|
59
|
+
|
60
|
+
#
|
61
|
+
# prints
|
62
|
+
# I'm jumpin
|
63
|
+
# I'm stretchin
|
64
|
+
# I'm crawlin
|
65
|
+
#
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'watch_methods'
|
2
|
+
|
3
|
+
class ClassMethodHook
|
4
|
+
watch_methods /crawl|jump|sit/, :class_methods => true do |meth|
|
5
|
+
puts "#{meth} was added!"
|
6
|
+
end
|
7
|
+
|
8
|
+
watch_methods :smile, :class_methods => true do |meth|
|
9
|
+
puts "Smile was added!"
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
watch_methods :scream do |meth|
|
14
|
+
puts "scream was added"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.crawl
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.scream
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.jump
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.sit
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
class << self
|
35
|
+
def smile
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# prints
|
43
|
+
# crawl was added!
|
44
|
+
# scream was added
|
45
|
+
# jump was added!
|
46
|
+
# sit was added!
|
47
|
+
# Smile was added!
|
48
|
+
#
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'watch_methods'
|
2
|
+
|
3
|
+
class Combo
|
4
|
+
watch_methods :test, "jump", [:cry, :dance], /^sing$/ do |meth|
|
5
|
+
puts "#{meth} was added!"
|
6
|
+
end
|
7
|
+
|
8
|
+
def sing
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
def dance
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
def test
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
#
|
23
|
+
# print
|
24
|
+
# sing was added!
|
25
|
+
# dance was added!
|
26
|
+
# test was added!
|
27
|
+
#
|
data/examples/regex.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'watch_methods'
|
2
|
+
|
3
|
+
class Queues
|
4
|
+
watch_methods /^queue_(.+)$/ do |meth|
|
5
|
+
puts "Queue #{meth} was added!"
|
6
|
+
end
|
7
|
+
|
8
|
+
def queue_jump
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
def queue_smile
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
#prints
|
19
|
+
# Queue queue_jump was added!
|
20
|
+
# Queue queue_smile was added!
|
21
|
+
#
|
data/examples/simple.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'watch_methods'
|
2
|
+
|
3
|
+
class TestFramework
|
4
|
+
def self.inherited(base)
|
5
|
+
at_exit { instance = base.new; @tests.each{|test| instance.send(test)} }
|
6
|
+
base.watch_methods /^test_.+$/ do |meth|
|
7
|
+
(@tests ||= []) << meth
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class TestName < TestFramework
|
13
|
+
def test_valid_name
|
14
|
+
puts "Run me! test_valid_name"
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_invalid_name
|
18
|
+
puts "Run me! test_invalid_name"
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_length
|
22
|
+
puts "Run me! test_length"
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_injections
|
26
|
+
puts "Run me! test_injections"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# prints
|
32
|
+
# Run me! test_valid_name
|
33
|
+
# Run me! test_invalid_name
|
34
|
+
# Run me! test_length
|
35
|
+
# Run me! test_injections
|
36
|
+
#
|
@@ -0,0 +1,76 @@
|
|
1
|
+
class Module
|
2
|
+
|
3
|
+
def call_callback(method_added_hash, key, meth)
|
4
|
+
return unless method_added_hash.include?(key)
|
5
|
+
callback_hash = method_added_hash[key]
|
6
|
+
callback = callback_hash[:callback]
|
7
|
+
once = callback_hash[:once]
|
8
|
+
method_added_hash.delete(key) if once
|
9
|
+
callback.call(meth)
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
private :call_callback
|
14
|
+
|
15
|
+
def watch_methods(*watch_for, &blk)
|
16
|
+
class_methods = false
|
17
|
+
once = false
|
18
|
+
if watch_for.last.is_a? Hash
|
19
|
+
opts = watch_for.pop
|
20
|
+
class_methods = opts[:class_methods] || class_methods
|
21
|
+
once = opts[:once] || once
|
22
|
+
end
|
23
|
+
|
24
|
+
context = class_methods ? (class << self; self; end) : self
|
25
|
+
|
26
|
+
added_watcher = context.class_eval { @method_added_watcher ||= {} }
|
27
|
+
|
28
|
+
watch_for.each do |f|
|
29
|
+
key = case f
|
30
|
+
when Regexp
|
31
|
+
f
|
32
|
+
when Symbol
|
33
|
+
f.to_s
|
34
|
+
when String
|
35
|
+
f
|
36
|
+
when Array
|
37
|
+
f.each {|*sub_f| sub_f << opts if opts; watch_methods(*sub_f, &blk)}
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
if key
|
43
|
+
added_watcher[key] = {:callback => blk, :once => once}
|
44
|
+
if meth = context.instance_methods(false).find{|m| key.match(m.to_s)}
|
45
|
+
call_callback(added_watcher, key, meth)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def maybe_call_callback(meth, context)
|
52
|
+
context.class_eval do
|
53
|
+
return unless @method_added_watcher
|
54
|
+
|
55
|
+
str_meth = meth.to_s
|
56
|
+
if found = @method_added_watcher.find{|key,value| key.match(str_meth)}
|
57
|
+
key, callback_hash = found
|
58
|
+
call_callback(@method_added_watcher, key, meth)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
private :maybe_call_callback
|
64
|
+
|
65
|
+
def method_added(meth)
|
66
|
+
maybe_call_callback(meth, self)
|
67
|
+
end
|
68
|
+
|
69
|
+
def singleton_method_added(meth)
|
70
|
+
context = class << self; self; end
|
71
|
+
maybe_call_callback(meth, context)
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
end
|
@@ -0,0 +1,364 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Method Added Hook" do
|
4
|
+
context "Instance Methods" do
|
5
|
+
before do
|
6
|
+
if defined?(SampleObject)
|
7
|
+
Object.send(:remove_const, :SampleObject)
|
8
|
+
end
|
9
|
+
SampleObject = Class.new do
|
10
|
+
watch_methods :mike, /^test_.*/, "jump" do |method|
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should add a class method watch_for_method_added" do
|
16
|
+
Module.should respond_to(:watch_methods)
|
17
|
+
SampleObject.should respond_to(:watch_methods)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should create a class instance variable with the correct hash method_added_watcher" do
|
21
|
+
h = SampleObject.class_eval{ @method_added_watcher }
|
22
|
+
|
23
|
+
h.each_key do |key|
|
24
|
+
key.should respond_to(:match)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should accept being called more than once" do
|
29
|
+
h = SampleObject.class_eval{ @method_added_watcher }
|
30
|
+
old_keys = h.keys
|
31
|
+
|
32
|
+
SampleObject.class_eval { watch_methods(:up) {} }
|
33
|
+
|
34
|
+
new_hash = SampleObject.class_eval{ @method_added_watcher }
|
35
|
+
|
36
|
+
new_hash.keys.should =~ (old_keys << "up")
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should accept an optional parameter once and only monitor a method once" do
|
40
|
+
result = nil
|
41
|
+
SampleObject.class_eval do
|
42
|
+
watch_methods(:up, :once => true) { result = 5 }
|
43
|
+
|
44
|
+
def up
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
result.should == 5
|
50
|
+
result = 20
|
51
|
+
|
52
|
+
new_hash = SampleObject.class_eval { @method_added_watcher }
|
53
|
+
new_hash.should_not include("up")
|
54
|
+
|
55
|
+
SampleObject.class_eval do
|
56
|
+
def up
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# in other words, its not 5
|
62
|
+
result.should == 20
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should accept an optional parameter once and only monitor a method once (in practice)" do
|
66
|
+
lambda {
|
67
|
+
result = nil
|
68
|
+
SampleObject.class_eval do
|
69
|
+
watch_methods(:up, :once => true) do |meth|
|
70
|
+
alias_method :"old_#{meth}", meth
|
71
|
+
define_method(meth) {}
|
72
|
+
end
|
73
|
+
|
74
|
+
def up
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
}.should_not raise_error(SystemStackError)
|
80
|
+
# if we didn't pass in once, we would get into an infinite loop of defining a method
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should expand all arrays" do
|
84
|
+
SampleObject.class_eval { watch_methods(["meth1", "meth2"]) {} }
|
85
|
+
h = SampleObject.class_eval{ @method_added_watcher }
|
86
|
+
h.each_key do |key|
|
87
|
+
key.class.should_not == Array
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
{:string => "my_method", :symbol => :my_method, :regex => /^my_method$/, :array => [1,2,3, "my_method"]}.each do |type, value|
|
92
|
+
it "should call a callback when a method is added with a #{type}" do
|
93
|
+
result = nil
|
94
|
+
SampleObject.class_eval do
|
95
|
+
watch_methods value do |meth|
|
96
|
+
result = 5
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class SampleObject
|
101
|
+
def my_method
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
result.should == 5
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
{:string => "my_method", :symbol => :my_method, :regex => /^my_method$/, :array => [1,2,3, "my_method"]}.each do |type, value|
|
111
|
+
it "should call a callback when a method is added with a #{type} before watch_methods was called" do
|
112
|
+
result = nil
|
113
|
+
SampleObject.class_eval do
|
114
|
+
def my_method
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
watch_methods value do |meth|
|
119
|
+
result = 5
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
result.should == 5
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should yield the method name (Symbol) to the block" do
|
128
|
+
result = nil
|
129
|
+
SampleObject.class_eval do
|
130
|
+
watch_methods /^t.*$/ do |meth|
|
131
|
+
result = meth
|
132
|
+
end
|
133
|
+
|
134
|
+
def test
|
135
|
+
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
result.should == :test
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
context "class methods" do
|
145
|
+
before do
|
146
|
+
if defined?(SampleClassObject)
|
147
|
+
Object.send(:remove_const, :SampleClassObject)
|
148
|
+
end
|
149
|
+
SampleClassObject = Class.new
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should work with eigenclass methods and eigenclass watch_methods" do
|
153
|
+
result = nil
|
154
|
+
meta = class << SampleClassObject; self; end
|
155
|
+
meta.class_eval do
|
156
|
+
watch_methods :game do |meth|
|
157
|
+
result = 5
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
class SampleClassObject
|
162
|
+
class << self
|
163
|
+
def game
|
164
|
+
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
result.should == 5
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should work with singleton methods and eigenclass" do
|
173
|
+
result = nil
|
174
|
+
meta = class << SampleClassObject; self; end
|
175
|
+
meta.class_eval do
|
176
|
+
watch_methods :game do |meth|
|
177
|
+
result = 5
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
class SampleClassObject
|
182
|
+
def self.game
|
183
|
+
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
result.should == 5
|
188
|
+
end
|
189
|
+
|
190
|
+
it "should work with singleton methods and optional parameter" do
|
191
|
+
result = nil
|
192
|
+
SampleClassObject.class_eval do
|
193
|
+
watch_methods :game, :class_methods => true do |meth|
|
194
|
+
result = 5
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
class SampleClassObject
|
199
|
+
def self.game
|
200
|
+
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
result.should == 5
|
205
|
+
end
|
206
|
+
|
207
|
+
it "should work with eigenclass methods and optional parameter" do
|
208
|
+
result = nil
|
209
|
+
SampleClassObject.class_eval do
|
210
|
+
watch_methods :game, :class_methods => true do |meth|
|
211
|
+
result = 5
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
class SampleClassObject
|
216
|
+
class << self
|
217
|
+
def game
|
218
|
+
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
result.should == 5
|
224
|
+
end
|
225
|
+
|
226
|
+
{:string => "my_method", :symbol => :my_method, :regex => /^my_method$/, :array => [1,2,3, "my_method"]}.each do |type, value|
|
227
|
+
it "should call a callback when a method is added with a #{type} before watch_methods was called" do
|
228
|
+
result = nil
|
229
|
+
SampleClassObject.class_eval do
|
230
|
+
class << self
|
231
|
+
def my_method
|
232
|
+
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
watch_methods value, :class_methods => true do |meth|
|
237
|
+
result = 5
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
result.should == 5
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
|
246
|
+
it "should work with an array and the optional parameter" do
|
247
|
+
result = nil
|
248
|
+
SampleClassObject.class_eval do
|
249
|
+
watch_methods [:game, :test], :class_methods => true do |meth|
|
250
|
+
result = 5
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
class SampleClassObject
|
255
|
+
class << self
|
256
|
+
def test
|
257
|
+
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
result.should == 5
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
context "Modules" do
|
267
|
+
before do
|
268
|
+
if defined?(SampleModuleObject)
|
269
|
+
Object.send(:remove_const, :SampleModuleObject)
|
270
|
+
end
|
271
|
+
SampleModuleObject = Module.new
|
272
|
+
end
|
273
|
+
|
274
|
+
it "should work for an instance method" do
|
275
|
+
result = nil
|
276
|
+
SampleModuleObject.module_eval do
|
277
|
+
watch_methods :hi do
|
278
|
+
result = 5
|
279
|
+
end
|
280
|
+
end
|
281
|
+
module SampleModuleObject
|
282
|
+
def hi
|
283
|
+
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
result.should == 5
|
288
|
+
end
|
289
|
+
|
290
|
+
it "should work for a singleton method" do
|
291
|
+
result = nil
|
292
|
+
SampleModuleObject.module_eval do
|
293
|
+
watch_methods :hi, :class_methods => true do
|
294
|
+
result = 5
|
295
|
+
end
|
296
|
+
end
|
297
|
+
module SampleModuleObject
|
298
|
+
def self.hi
|
299
|
+
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
result.should == 5
|
304
|
+
end
|
305
|
+
|
306
|
+
|
307
|
+
it "should work for an eigenclass method" do
|
308
|
+
result = nil
|
309
|
+
SampleModuleObject.module_eval do
|
310
|
+
watch_methods :hi, :class_methods => true do
|
311
|
+
result = 5
|
312
|
+
end
|
313
|
+
end
|
314
|
+
module SampleModuleObject
|
315
|
+
class << self
|
316
|
+
def hi
|
317
|
+
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
result.should == 5
|
323
|
+
end
|
324
|
+
|
325
|
+
it "should work for an eigenclass method, watched from an eigenclass" do
|
326
|
+
result = nil
|
327
|
+
meta = (class << SampleModuleObject; self; end)
|
328
|
+
meta.class_eval do
|
329
|
+
watch_methods :hi do
|
330
|
+
result = 5
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
module SampleModuleObject
|
335
|
+
class << self
|
336
|
+
def hi
|
337
|
+
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
result.should == 5
|
343
|
+
end
|
344
|
+
|
345
|
+
it "should work for a singleton method, watched from an eigenclass" do
|
346
|
+
result = nil
|
347
|
+
meta = (class << SampleModuleObject; self; end)
|
348
|
+
meta.class_eval do
|
349
|
+
watch_methods :hi do
|
350
|
+
result = 5
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
module SampleModuleObject
|
355
|
+
def self.hi
|
356
|
+
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
result.should == 5
|
361
|
+
end
|
362
|
+
|
363
|
+
end
|
364
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "watch_methods/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "watch_methods"
|
7
|
+
s.version = WatchMethods::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Mike Lewis"]
|
10
|
+
s.email = ["ft.mikelewis@gmail.com"]
|
11
|
+
s.homepage = "http://github.com/mikelewis/method_added_hook"
|
12
|
+
s.summary = %q{Easily monitor methods added within classes and modules.}
|
13
|
+
s.description = %q{Easily monitor methods added within classes and modules.}
|
14
|
+
|
15
|
+
s.rubyforge_project = "method_added_hook"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.add_development_dependency "rake"
|
23
|
+
s.add_development_dependency "rspec"
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: watch_methods
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.4
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mike Lewis
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-11-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: &2152721360 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2152721360
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rspec
|
27
|
+
requirement: &2152720480 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2152720480
|
36
|
+
description: Easily monitor methods added within classes and modules.
|
37
|
+
email:
|
38
|
+
- ft.mikelewis@gmail.com
|
39
|
+
executables: []
|
40
|
+
extensions: []
|
41
|
+
extra_rdoc_files: []
|
42
|
+
files:
|
43
|
+
- .gitignore
|
44
|
+
- .rspec
|
45
|
+
- Gemfile
|
46
|
+
- README.md
|
47
|
+
- Rakefile
|
48
|
+
- examples/array.rb
|
49
|
+
- examples/before_and_after_declartion.rb
|
50
|
+
- examples/callbacks.rb
|
51
|
+
- examples/class_methods.rb
|
52
|
+
- examples/combination.rb
|
53
|
+
- examples/regex.rb
|
54
|
+
- examples/simple.rb
|
55
|
+
- examples/test_framework.rb
|
56
|
+
- examples/watch_only_once.rb
|
57
|
+
- lib/watch_methods.rb
|
58
|
+
- lib/watch_methods/version.rb
|
59
|
+
- spec/method_added_hook_spec.rb
|
60
|
+
- spec/spec_helper.rb
|
61
|
+
- watch_methods.gemspec
|
62
|
+
homepage: http://github.com/mikelewis/method_added_hook
|
63
|
+
licenses: []
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options: []
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ! '>='
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ! '>='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
80
|
+
requirements: []
|
81
|
+
rubyforge_project: method_added_hook
|
82
|
+
rubygems_version: 1.8.10
|
83
|
+
signing_key:
|
84
|
+
specification_version: 3
|
85
|
+
summary: Easily monitor methods added within classes and modules.
|
86
|
+
test_files:
|
87
|
+
- spec/method_added_hook_spec.rb
|
88
|
+
- spec/spec_helper.rb
|