unobservable 0.8.0 → 0.10.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/VERSION +1 -1
- data/lib/unobservable.rb +27 -12
- data/spec/instance_event_container_spec.rb +130 -0
- data/spec/support_spec.rb +118 -0
- data/spec/unobservable_spec.rb +0 -63
- metadata +5 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.10.1
|
data/lib/unobservable.rb
CHANGED
@@ -53,22 +53,33 @@ module Unobservable
|
|
53
53
|
private
|
54
54
|
|
55
55
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
@unobservable_instance_events ||= Set.new
|
56
|
+
def define_event(name, args = {})
|
57
|
+
args = {:create_method => true}.merge(args)
|
58
|
+
name = name.to_sym
|
60
59
|
|
61
|
-
|
62
|
-
define_method
|
63
|
-
return event(
|
60
|
+
if args[:create_method]
|
61
|
+
define_method name do
|
62
|
+
return event(name)
|
64
63
|
end
|
65
|
-
@unobservable_instance_events.add(n.to_sym)
|
66
64
|
end
|
67
65
|
|
68
|
-
|
66
|
+
@unobservable_instance_events ||= Set.new
|
67
|
+
if @unobservable_instance_events.include? name
|
68
|
+
return false
|
69
|
+
else
|
70
|
+
@unobservable_instance_events.add name
|
71
|
+
return true
|
72
|
+
end
|
69
73
|
end
|
70
74
|
|
71
|
-
|
75
|
+
|
76
|
+
# This helper method is similar to attr_reader and attr_accessor. It allows
|
77
|
+
# for instance events to be declared inside the body of the class.
|
78
|
+
def attr_event(*names)
|
79
|
+
args = (names[-1].is_a? Hash) ? names.pop : {}
|
80
|
+
names.each {|n| define_event(n, args) }
|
81
|
+
return nil
|
82
|
+
end
|
72
83
|
|
73
84
|
end
|
74
85
|
|
@@ -105,8 +116,8 @@ module Unobservable
|
|
105
116
|
end
|
106
117
|
|
107
118
|
# Defines an event directly on the object.
|
108
|
-
def define_singleton_event(
|
109
|
-
self.singleton_class.send(:
|
119
|
+
def define_singleton_event(name, args = {})
|
120
|
+
self.singleton_class.send(:define_event, name, args)
|
110
121
|
end
|
111
122
|
|
112
123
|
# Obtains the names of the events that are supported by this object. If
|
@@ -185,6 +196,8 @@ module Unobservable
|
|
185
196
|
@handlers << h
|
186
197
|
return h
|
187
198
|
end
|
199
|
+
|
200
|
+
alias :add :register
|
188
201
|
|
189
202
|
|
190
203
|
# Removes a single instance of the specified event handler
|
@@ -203,6 +216,8 @@ module Unobservable
|
|
203
216
|
end
|
204
217
|
|
205
218
|
|
219
|
+
alias :delete :unregister
|
220
|
+
|
206
221
|
|
207
222
|
# Pass the specific arguments / block to all of the
|
208
223
|
# event handlers. Return true if there was at least
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
include Unobservable::SpecHelper
|
4
|
+
|
5
|
+
|
6
|
+
shared_examples_for "instance event container" do
|
7
|
+
|
8
|
+
context "Unobservable::Support is not included" do
|
9
|
+
it "does not have any instance events" do
|
10
|
+
c = described_class.new
|
11
|
+
Unobservable::instance_events_for(c, true).should be_empty
|
12
|
+
Unobservable::instance_events_for(c, false).should be_empty
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
context "Unobservable::Support is included" do
|
18
|
+
|
19
|
+
let(:mixin_module) do
|
20
|
+
module_with_instance_events :one, :two
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:instance_event_container) do
|
24
|
+
m = mixin_module
|
25
|
+
described_class.new do
|
26
|
+
include Unobservable::Support
|
27
|
+
include m
|
28
|
+
|
29
|
+
attr_event :three, :four
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
let(:c){ described_class.new{ include Unobservable::Support } }
|
34
|
+
|
35
|
+
it "does not have any events by default" do
|
36
|
+
c = described_class.new { include Unobservable::Support }
|
37
|
+
Unobservable::instance_events_for(c, true).should be_empty
|
38
|
+
Unobservable::instance_events_for(c, false).should be_empty
|
39
|
+
end
|
40
|
+
|
41
|
+
it "knows which events have been defined explicitly" do
|
42
|
+
events = Unobservable::instance_events_for(instance_event_container, false)
|
43
|
+
events.size.should == 2
|
44
|
+
events.should include(:three)
|
45
|
+
events.should include(:four)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "inherits instance events defined by included Modules" do
|
49
|
+
events = Unobservable::instance_events_for(instance_event_container, true)
|
50
|
+
events.size.should == 4
|
51
|
+
events.should include(:one)
|
52
|
+
events.should include(:two)
|
53
|
+
events.should include(:three)
|
54
|
+
events.should include(:four)
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
describe "#define_event" do
|
59
|
+
|
60
|
+
it "returns true if the specified event did not already exist" do
|
61
|
+
c.send(:define_event, :quux).should be_true
|
62
|
+
end
|
63
|
+
|
64
|
+
it "returns false if the specified event already existed" do
|
65
|
+
c.send(:define_event, :quux)
|
66
|
+
c.send(:define_event, :quux).should be_false
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
it "defines an instance event" do
|
71
|
+
c.instance_events.should_not include(:quux)
|
72
|
+
c.send(:define_event, :quux)
|
73
|
+
c.instance_events.should include(:quux)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "creates a corresponding instance method when :create_method => true" do
|
77
|
+
c.instance_methods.should_not include(:quux)
|
78
|
+
c.send(:define_event, :quux, :create_method => true)
|
79
|
+
c.instance_methods.should include(:quux)
|
80
|
+
end
|
81
|
+
|
82
|
+
it "does not create a corresponding instance method when :create_method => false" do
|
83
|
+
c.instance_methods.should_not include(:quux)
|
84
|
+
c.send(:define_event, :quux, :create_method => false)
|
85
|
+
c.instance_methods.should_not include(:quux)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "creates corresponding instance method by default" do
|
89
|
+
c.instance_methods.should_not include(:quux)
|
90
|
+
c.send(:define_event, :quux)
|
91
|
+
c.instance_methods.should include(:quux)
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
describe "#attr_event" do
|
98
|
+
|
99
|
+
it "defines several events at once" do
|
100
|
+
c.instance_events.should_not include(:one, :two, :three)
|
101
|
+
c.send(:attr_event, :one, :two, :three)
|
102
|
+
c.instance_events.should include(:one, :two, :three)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "creates corresponding instance methods when :create_method => true" do
|
106
|
+
c.instance_methods.should_not include(:one, :two, :three)
|
107
|
+
c.send(:attr_event, :one, :two, :three, :create_method => true)
|
108
|
+
c.instance_methods.should include(:one, :two, :three)
|
109
|
+
end
|
110
|
+
|
111
|
+
it "does not create corresponding instance methods when :create_method => false" do
|
112
|
+
c.instance_methods.should_not include(:one, :two, :three)
|
113
|
+
c.send(:attr_event, :one, :two, :three, :create_method => false)
|
114
|
+
c.instance_methods.should_not include(:one, :two, :three)
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
describe Module do
|
125
|
+
it_behaves_like "instance event container"
|
126
|
+
end
|
127
|
+
|
128
|
+
describe Class do
|
129
|
+
it_behaves_like "instance event container"
|
130
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
include Unobservable::SpecHelper
|
4
|
+
|
5
|
+
module Unobservable
|
6
|
+
describe Support do
|
7
|
+
let(:my_class) { class_with_instance_events(:foo, :bar) }
|
8
|
+
let(:obj) { my_class.new }
|
9
|
+
|
10
|
+
context "when included by a module" do
|
11
|
+
it "causes the module to extend Unobservable::ModuleSupport" do
|
12
|
+
m = Module.new{ include Unobservable::Support }
|
13
|
+
|
14
|
+
m.should include(Unobservable::Support)
|
15
|
+
m.singleton_class.should include(Unobservable::ModuleSupport)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
context "when extended by an Object" do
|
21
|
+
it "causes the object's singleton class to extend Unobservable::ModuleSupport" do
|
22
|
+
x = Object.new
|
23
|
+
x.extend Unobservable::Support
|
24
|
+
|
25
|
+
x.singleton_class.should include(Unobservable::Support)
|
26
|
+
x.singleton_class.singleton_class.should include(Unobservable::ModuleSupport)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
describe "#define_singleton_event" do
|
32
|
+
|
33
|
+
it "defines a new singleton event directly on the object" do
|
34
|
+
the_singleton_event = :quux
|
35
|
+
|
36
|
+
obj.class.instance_events.should_not include(the_singleton_event)
|
37
|
+
obj.singleton_events(false).should_not include(the_singleton_event)
|
38
|
+
expect{ obj.event(the_singleton_event) }.to raise_error
|
39
|
+
|
40
|
+
expect{ obj.define_singleton_event the_singleton_event }.to change{ obj.singleton_events(false).size }.by(1)
|
41
|
+
|
42
|
+
obj.class.instance_events.should_not include(the_singleton_event)
|
43
|
+
obj.singleton_events(false).should include(the_singleton_event)
|
44
|
+
expect{ obj.event(the_singleton_event) }.to_not raise_error
|
45
|
+
end
|
46
|
+
|
47
|
+
it "returns True if the object did not already define the event as a singleton event" do
|
48
|
+
obj.define_singleton_event(:foo).should be_true
|
49
|
+
end
|
50
|
+
|
51
|
+
it "returns False if the object already defined the event as a singleton event" do
|
52
|
+
obj.define_singleton_event(:foo)
|
53
|
+
obj.define_singleton_event(:foo).should be_false
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
it "creates a corresponding instance method when :create_method => true" do
|
58
|
+
obj.methods.should_not include(:quux)
|
59
|
+
obj.define_singleton_event :quux, :create_method => true
|
60
|
+
obj.methods.should include(:quux)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "does not create a corresponding instance method when :create_method => false" do
|
64
|
+
obj.methods.should_not include(:quux)
|
65
|
+
obj.define_singleton_event :quux, :create_method => false
|
66
|
+
obj.methods.should_not include(:quux)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "creates a corresponding instance method by default" do
|
70
|
+
obj.methods.should_not include(:quux)
|
71
|
+
obj.define_singleton_event :quux
|
72
|
+
obj.methods.should include(:quux)
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
describe "#event" do
|
79
|
+
it "raises a NameError when the specified event is not defined" do
|
80
|
+
expect{ obj.event(:not_exist) }.to raise_error(NameError)
|
81
|
+
end
|
82
|
+
|
83
|
+
it "maps different names to different Event instances" do
|
84
|
+
obj.event(:foo).should_not === obj.event(:bar)
|
85
|
+
end
|
86
|
+
|
87
|
+
it "maps the same name to the same Event instance" do
|
88
|
+
obj.event(:foo).should === obj.event(:foo)
|
89
|
+
obj.event(:bar).should === obj.event(:bar)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "maintains separate Events for each object" do
|
93
|
+
x = my_class.new
|
94
|
+
y = my_class.new
|
95
|
+
|
96
|
+
x.event(:foo).should_not === y.event(:foo)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
describe "#raise_event" do
|
102
|
+
|
103
|
+
it "raises a NameError when the specified event is not defined" do
|
104
|
+
expect{ obj.send :raise_event, :not_exist }.to raise_error(NameError)
|
105
|
+
expect{ obj.send :raise_event, :not_exist, 1, 2, 3 }.to raise_error(NameError)
|
106
|
+
end
|
107
|
+
|
108
|
+
it "calls the specified event" do
|
109
|
+
args = [1, 2, 3]
|
110
|
+
obj.event(:foo).should_receive(:call).with(*args)
|
111
|
+
obj.send :raise_event, :foo, *args
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
data/spec/unobservable_spec.rb
CHANGED
@@ -3,69 +3,6 @@ require 'spec_helper'
|
|
3
3
|
include Unobservable::SpecHelper
|
4
4
|
|
5
5
|
|
6
|
-
shared_examples_for "instance event container" do
|
7
|
-
|
8
|
-
context "Unobservable::Support is not included" do
|
9
|
-
it "does not have any instance events" do
|
10
|
-
c = described_class.new
|
11
|
-
Unobservable::instance_events_for(c, true).should be_empty
|
12
|
-
Unobservable::instance_events_for(c, false).should be_empty
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
|
17
|
-
context "Unobservable::Support is included" do
|
18
|
-
|
19
|
-
let(:mixin_module) do
|
20
|
-
module_with_instance_events :one, :two
|
21
|
-
end
|
22
|
-
|
23
|
-
let(:instance_event_container) do
|
24
|
-
m = mixin_module
|
25
|
-
described_class.new do
|
26
|
-
include Unobservable::Support
|
27
|
-
include m
|
28
|
-
|
29
|
-
attr_event :three, :four
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
it "does not have any events by default" do
|
34
|
-
c = described_class.new { include Unobservable::Support }
|
35
|
-
Unobservable::instance_events_for(c, true).should be_empty
|
36
|
-
Unobservable::instance_events_for(c, false).should be_empty
|
37
|
-
end
|
38
|
-
|
39
|
-
it "knows which events have been defined explicitly" do
|
40
|
-
events = Unobservable::instance_events_for(instance_event_container, false)
|
41
|
-
events.size.should == 2
|
42
|
-
events.should include(:three)
|
43
|
-
events.should include(:four)
|
44
|
-
end
|
45
|
-
|
46
|
-
it "inherits instance events defined by included Modules" do
|
47
|
-
events = Unobservable::instance_events_for(instance_event_container, true)
|
48
|
-
events.size.should == 4
|
49
|
-
events.should include(:one)
|
50
|
-
events.should include(:two)
|
51
|
-
events.should include(:three)
|
52
|
-
events.should include(:four)
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|
58
|
-
|
59
|
-
|
60
|
-
describe Module do
|
61
|
-
it_behaves_like "instance event container"
|
62
|
-
end
|
63
|
-
|
64
|
-
describe Class do
|
65
|
-
it_behaves_like "instance event container"
|
66
|
-
end
|
67
|
-
|
68
|
-
|
69
6
|
|
70
7
|
describe Unobservable do
|
71
8
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unobservable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-12-
|
12
|
+
date: 2012-12-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: shoulda
|
@@ -108,7 +108,9 @@ files:
|
|
108
108
|
- VERSION
|
109
109
|
- lib/unobservable.rb
|
110
110
|
- spec/event_spec.rb
|
111
|
+
- spec/instance_event_container_spec.rb
|
111
112
|
- spec/spec_helper.rb
|
113
|
+
- spec/support_spec.rb
|
112
114
|
- spec/unobservable_spec.rb
|
113
115
|
- test/helper.rb
|
114
116
|
- test/test_unobservable.rb
|
@@ -127,7 +129,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
127
129
|
version: '0'
|
128
130
|
segments:
|
129
131
|
- 0
|
130
|
-
hash:
|
132
|
+
hash: -1060921785598011427
|
131
133
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
134
|
none: false
|
133
135
|
requirements:
|