sentinel 0.1.0 → 0.2.0
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.textile +19 -18
- data/VERSION +1 -1
- data/lib/metaid.rb +17 -0
- data/lib/sentinel.rb +10 -13
- data/sentinel.gemspec +6 -5
- data/spec/fixtures/{subject.rb → sentinel_subject.rb} +1 -1
- data/spec/sentinel_spec.rb +18 -18
- metadata +31 -15
data/README.textile
CHANGED
@@ -14,9 +14,9 @@ First, install the gem:
|
|
14
14
|
$ [sudo] gem install sentinel
|
15
15
|
</pre>
|
16
16
|
|
17
|
-
Then, add it as a dependency in your code using your favorite way (a simple require or mechanisms the bundler gem).
|
17
|
+
Then, add it as a dependency in your code using your favorite way (a simple require or mechanisms like the bundler gem).
|
18
18
|
|
19
|
-
To use it, first you'll need an observer class that responds to a method called *_notify_
|
19
|
+
To use it, first you'll need an observer class that responds to a class method called *_notify_*. All the observed method's arguments will be passed to this method, hence the _args_ splat.
|
20
20
|
|
21
21
|
<pre>
|
22
22
|
class MyObserver
|
@@ -26,12 +26,25 @@ class MyObserver
|
|
26
26
|
end
|
27
27
|
</pre>
|
28
28
|
|
29
|
-
Then,
|
29
|
+
Then, simply include the _Sentinel_ module in the observer, setting up the desired class (or classes) and method (or methods) to be observed.
|
30
30
|
|
31
31
|
<pre>
|
32
|
-
class
|
32
|
+
class MyObserver
|
33
33
|
include Sentinel
|
34
34
|
|
35
|
+
observe MyClass, :instance_method
|
36
|
+
observe MyClass, :class_method, :class_method => true #to observe a class method
|
37
|
+
|
38
|
+
def self.notify(*args)
|
39
|
+
puts "Do your thing!"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
</pre>
|
43
|
+
|
44
|
+
As you can see, Sentinel can observe both class and instance methods. Now, our actual class:
|
45
|
+
|
46
|
+
<pre>
|
47
|
+
class MyClass
|
35
48
|
def instance_method
|
36
49
|
puts "Hi from the instance method!"
|
37
50
|
end
|
@@ -39,25 +52,13 @@ class MyClass
|
|
39
52
|
def self.class_method
|
40
53
|
puts "Hi from the class method!"
|
41
54
|
end
|
42
|
-
|
43
|
-
observe :instance_method, :notify => MyObserver
|
44
|
-
observe :class_method, :notify => MyObserver, :class_method => true #to observe a class method
|
45
55
|
end
|
46
56
|
</pre>
|
47
57
|
|
48
|
-
|
49
|
-
|
50
|
-
<pre>
|
51
|
-
observe :instance_method, :notify => MyObserver.new
|
52
|
-
observe :class_method, :notify => MyObserver.new, :class_method => true #to observe a class method
|
53
|
-
</pre>
|
54
|
-
|
55
|
-
In summary, any object that responds to *_notify_* will be accepted.
|
56
|
-
|
57
|
-
And... that's it! Every time the observed method is called, the _notify_ method from the defined Observer will be called *before* it, then it will run normally.
|
58
|
+
And... that's it! Every time the observed method is called, the _notify_ method from the defined _observer class_ will be called *before* it, then it will run normally.
|
58
59
|
|
59
60
|
h2. Note on Patches/Pull Requests
|
60
|
-
|
61
|
+
|
61
62
|
* Fork the project.
|
62
63
|
* Make your feature addition or bug fix.
|
63
64
|
* Add tests for it. This is important so I don't break it in a
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/lib/metaid.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# Code by why_the_lucky_stiff
|
2
|
+
|
3
|
+
class Object
|
4
|
+
# The hidden singleton lurks behind everyone
|
5
|
+
def metaclass; class << self; self; end; end
|
6
|
+
def meta_eval &blk; metaclass.instance_eval &blk; end
|
7
|
+
|
8
|
+
# Adds methods to a metaclass
|
9
|
+
def meta_def name, &blk
|
10
|
+
meta_eval { define_method name, &blk }
|
11
|
+
end
|
12
|
+
|
13
|
+
# Defines an instance method within a class
|
14
|
+
def class_def name, &blk
|
15
|
+
class_eval { define_method name, &blk }
|
16
|
+
end
|
17
|
+
end
|
data/lib/sentinel.rb
CHANGED
@@ -1,33 +1,30 @@
|
|
1
|
+
require "metaid"
|
2
|
+
|
1
3
|
module Sentinel
|
2
4
|
def self.included(base)
|
3
5
|
base.extend(ClassMethods)
|
4
6
|
end
|
5
|
-
|
7
|
+
|
6
8
|
module ClassMethods
|
7
|
-
def observe(method_name, options = {})
|
8
|
-
|
9
|
-
|
10
|
-
end
|
9
|
+
def observe(class_name, method_name, options = {})
|
10
|
+
sentinel = self
|
11
|
+
|
11
12
|
body = <<-CODE
|
12
13
|
define_method "#{method_name}_with_observer" do |*args|
|
13
|
-
|
14
|
+
sentinel.notify(*args)
|
14
15
|
self.send("#{method_name}_without_observer", *args)
|
15
16
|
end
|
16
17
|
|
17
18
|
alias_method "#{method_name}_without_observer", method_name
|
18
19
|
alias_method method_name, "#{method_name}_with_observer"
|
19
20
|
CODE
|
20
|
-
|
21
|
-
if options[:class_method]
|
22
|
-
|
23
|
-
metaclass = class << self; self; end
|
24
21
|
|
25
|
-
|
22
|
+
if options[:class_method]
|
23
|
+
class_name.meta_eval do
|
26
24
|
eval body
|
27
25
|
end
|
28
|
-
|
29
26
|
else
|
30
|
-
|
27
|
+
class_name.send(:class_eval, body)
|
31
28
|
end
|
32
29
|
end
|
33
30
|
end
|
data/sentinel.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{sentinel}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Lucas H\303\272ngaro"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-03-02}
|
13
13
|
s.description = %q{Transparent (unobtrusive) Observers for your Ruby code}
|
14
14
|
s.email = %q{lucashungaro@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -23,10 +23,11 @@ Gem::Specification.new do |s|
|
|
23
23
|
"README.textile",
|
24
24
|
"Rakefile",
|
25
25
|
"VERSION",
|
26
|
+
"lib/metaid.rb",
|
26
27
|
"lib/sentinel.rb",
|
27
28
|
"sentinel.gemspec",
|
28
29
|
"spec/fixtures/my_observer.rb",
|
29
|
-
"spec/fixtures/
|
30
|
+
"spec/fixtures/sentinel_subject.rb",
|
30
31
|
"spec/sentinel_spec.rb",
|
31
32
|
"spec/spec.opts",
|
32
33
|
"spec/spec_helper.rb"
|
@@ -34,11 +35,11 @@ Gem::Specification.new do |s|
|
|
34
35
|
s.homepage = %q{http://github.com/lucashungaro/sentinel}
|
35
36
|
s.rdoc_options = ["--charset=UTF-8"]
|
36
37
|
s.require_paths = ["lib"]
|
37
|
-
s.rubygems_version = %q{1.3.
|
38
|
+
s.rubygems_version = %q{1.3.6}
|
38
39
|
s.summary = %q{Transparent (unobtrusive) Observers for your Ruby code}
|
39
40
|
s.test_files = [
|
40
41
|
"spec/fixtures/my_observer.rb",
|
41
|
-
"spec/fixtures/
|
42
|
+
"spec/fixtures/sentinel_subject.rb",
|
42
43
|
"spec/sentinel_spec.rb",
|
43
44
|
"spec/spec_helper.rb"
|
44
45
|
]
|
data/spec/sentinel_spec.rb
CHANGED
@@ -1,46 +1,46 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
2
|
require File.expand_path(File.dirname(__FILE__) + '/fixtures/my_observer')
|
3
|
-
require File.expand_path(File.dirname(__FILE__) + '/fixtures/
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/fixtures/sentinel_subject')
|
4
4
|
|
5
5
|
describe Sentinel, "defining an observer for a method" do
|
6
6
|
before(:all) do
|
7
|
-
|
7
|
+
MyObserver.send(:include, Sentinel)
|
8
8
|
end
|
9
9
|
|
10
10
|
context "with the minimum required options" do
|
11
11
|
it "should notify the specified Observer when calling a class method" do
|
12
|
-
|
12
|
+
MyObserver.send(:observe, SentinelSubject, :instance_method)
|
13
13
|
MyObserver.expects(:notify)
|
14
14
|
|
15
|
-
|
15
|
+
SentinelSubject.new.instance_method
|
16
16
|
end
|
17
17
|
|
18
18
|
it "should notify the specified Observer when calling an instance method" do
|
19
|
-
|
19
|
+
MyObserver.send(:observe, SentinelSubject, :class_method, :class_method => true)
|
20
20
|
MyObserver.expects(:notify)
|
21
21
|
|
22
|
-
|
22
|
+
SentinelSubject.class_method
|
23
23
|
end
|
24
24
|
|
25
25
|
it "should not modify the observed methods output" do
|
26
|
-
|
27
|
-
|
26
|
+
MyObserver.send(:observe, SentinelSubject, :class_returning_something, :class_method => true)
|
27
|
+
MyObserver.send(:observe, SentinelSubject, :instance_returning_something)
|
28
28
|
|
29
29
|
MyObserver.expects(:notify).twice
|
30
30
|
|
31
|
-
|
32
|
-
|
31
|
+
SentinelSubject.class_returning_something.should == 42
|
32
|
+
SentinelSubject.new.instance_returning_something.should == 42
|
33
33
|
end
|
34
34
|
|
35
35
|
context "observing methods with parameters" do
|
36
36
|
it "should pass all parameters of the observed methods to the Observer" do
|
37
|
-
|
38
|
-
|
37
|
+
MyObserver.send(:observe, SentinelSubject, :class_method_with_params, :class_method => true)
|
38
|
+
MyObserver.send(:observe, SentinelSubject, :instance_method_with_params)
|
39
39
|
|
40
40
|
MyObserver.expects(:notify).twice.with("texto", 1)
|
41
41
|
|
42
|
-
|
43
|
-
|
42
|
+
SentinelSubject.class_method_with_params("texto", 1)
|
43
|
+
SentinelSubject.new.instance_method_with_params("texto", 1)
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
@@ -48,16 +48,16 @@ describe Sentinel, "defining an observer for a method" do
|
|
48
48
|
context "without the minimum required options" do
|
49
49
|
it "should raise ArgumentError when the observer of an instance method is not defined" do
|
50
50
|
MyObserver.expects(:notify).never
|
51
|
-
|
51
|
+
SentinelSubject.expects(:observe).raises(ArgumentError)
|
52
52
|
|
53
|
-
|
53
|
+
SentinelSubject.send(:observe, :instance_method) rescue nil
|
54
54
|
end
|
55
55
|
|
56
56
|
it "should raise ArgumentError when the observer of a class method is not defined" do
|
57
57
|
MyObserver.expects(:notify).never
|
58
|
-
|
58
|
+
SentinelSubject.expects(:observe).raises(ArgumentError)
|
59
59
|
|
60
|
-
|
60
|
+
SentinelSubject.send(:observe, :class_method, :class_method => true) rescue nil
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sentinel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- "Lucas H\xC3\xBAngaro"
|
@@ -9,29 +14,37 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date: 2010-
|
17
|
+
date: 2010-03-02 00:00:00 -03:00
|
13
18
|
default_executable:
|
14
19
|
dependencies:
|
15
20
|
- !ruby/object:Gem::Dependency
|
16
21
|
name: rspec
|
17
|
-
|
18
|
-
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
24
|
requirements:
|
21
25
|
- - ">="
|
22
26
|
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 1
|
29
|
+
- 2
|
30
|
+
- 9
|
23
31
|
version: 1.2.9
|
24
|
-
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
25
34
|
- !ruby/object:Gem::Dependency
|
26
35
|
name: mocha
|
27
|
-
|
28
|
-
|
29
|
-
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
38
|
requirements:
|
31
39
|
- - ">="
|
32
40
|
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
- 9
|
44
|
+
- 8
|
33
45
|
version: 0.9.8
|
34
|
-
|
46
|
+
type: :development
|
47
|
+
version_requirements: *id002
|
35
48
|
description: Transparent (unobtrusive) Observers for your Ruby code
|
36
49
|
email: lucashungaro@gmail.com
|
37
50
|
executables: []
|
@@ -48,10 +61,11 @@ files:
|
|
48
61
|
- README.textile
|
49
62
|
- Rakefile
|
50
63
|
- VERSION
|
64
|
+
- lib/metaid.rb
|
51
65
|
- lib/sentinel.rb
|
52
66
|
- sentinel.gemspec
|
53
67
|
- spec/fixtures/my_observer.rb
|
54
|
-
- spec/fixtures/
|
68
|
+
- spec/fixtures/sentinel_subject.rb
|
55
69
|
- spec/sentinel_spec.rb
|
56
70
|
- spec/spec.opts
|
57
71
|
- spec/spec_helper.rb
|
@@ -68,23 +82,25 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
68
82
|
requirements:
|
69
83
|
- - ">="
|
70
84
|
- !ruby/object:Gem::Version
|
85
|
+
segments:
|
86
|
+
- 0
|
71
87
|
version: "0"
|
72
|
-
version:
|
73
88
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
89
|
requirements:
|
75
90
|
- - ">="
|
76
91
|
- !ruby/object:Gem::Version
|
92
|
+
segments:
|
93
|
+
- 0
|
77
94
|
version: "0"
|
78
|
-
version:
|
79
95
|
requirements: []
|
80
96
|
|
81
97
|
rubyforge_project:
|
82
|
-
rubygems_version: 1.3.
|
98
|
+
rubygems_version: 1.3.6
|
83
99
|
signing_key:
|
84
100
|
specification_version: 3
|
85
101
|
summary: Transparent (unobtrusive) Observers for your Ruby code
|
86
102
|
test_files:
|
87
103
|
- spec/fixtures/my_observer.rb
|
88
|
-
- spec/fixtures/
|
104
|
+
- spec/fixtures/sentinel_subject.rb
|
89
105
|
- spec/sentinel_spec.rb
|
90
106
|
- spec/spec_helper.rb
|