audible 0.2.0 → 0.4.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.
- checksums.yaml +15 -0
- data/.document +5 -5
- data/.travis.yml +12 -12
- data/Gemfile +6 -6
- data/Gemfile.lock +64 -62
- data/LICENSE.txt +20 -20
- data/README.md +9 -9
- data/Rakefile +33 -41
- data/VERSION +1 -1
- data/audible.gemspec +69 -67
- data/lib/audible.rb +3 -3
- data/lib/audible/audible.rb +50 -42
- data/lib/audible/pidfile.rb +16 -16
- data/spec/spec_helper.rb +7 -7
- data/spec/system.tests/drb/bin/server +44 -44
- data/spec/system.tests/drb/drb_observers_spec.rb +65 -65
- data/spec/system.tests/drb/support/drb_server.rb +26 -26
- data/spec/{and_how_it_differs_from_observable_spec.rb → unit.tests/and_how_it_differs_from_observable_spec.rb} +101 -101
- data/spec/{examples → unit.tests/examples}/a_notifying_shell_spec.rb +28 -28
- data/spec/{examples → unit.tests/examples}/logging_as_notifications_spec.rb +51 -51
- data/spec/unit.tests/it_notifies_despite_errors_spec.rb +30 -0
- data/spec/{listening_spec.rb → unit.tests/listening_spec.rb} +53 -53
- data/spec/{relaying_notifications → unit.tests/relaying_notifications}/about_the_notifications_spec.rb +69 -69
- data/spec/{relaying_notifications → unit.tests/relaying_notifications}/can_relay_notifications_spec.rb +43 -43
- metadata +12 -22
data/lib/audible.rb
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
dirname = File.expand_path File.dirname(__FILE__)
|
|
2
|
-
|
|
3
|
-
Dir.glob(File.join(dirname, "audible", "**", "*.rb")).each{|f| require f}
|
|
1
|
+
dirname = File.expand_path File.dirname(__FILE__)
|
|
2
|
+
|
|
3
|
+
Dir.glob(File.join(dirname, "audible", "**", "*.rb")).each{|f| require f}
|
data/lib/audible/audible.rb
CHANGED
|
@@ -1,42 +1,50 @@
|
|
|
1
|
-
module Audible
|
|
2
|
-
def on(*events, &block)
|
|
3
|
-
events.each{|e| attach(e, &block)}
|
|
4
|
-
end
|
|
5
|
-
|
|
6
|
-
def relay(source, event, opts ={})
|
|
7
|
-
name = opts[:as] || event
|
|
8
|
-
source.on(event){|e,args| notify name, args.first}
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
protected
|
|
12
|
-
|
|
13
|
-
def attach(event,&block)
|
|
14
|
-
fail no_way_to_notify unless block_given?
|
|
15
|
-
|
|
16
|
-
listeners_for(event) << block
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def notify(event, *args)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def
|
|
42
|
-
|
|
1
|
+
module Audible
|
|
2
|
+
def on(*events, &block)
|
|
3
|
+
events.each{|e| attach(e, &block)}
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def relay(source, event, opts ={})
|
|
7
|
+
name = opts[:as] || event
|
|
8
|
+
source.on(event){|e,args| notify name, args.first}
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
protected
|
|
12
|
+
|
|
13
|
+
def attach(event,&block)
|
|
14
|
+
fail no_way_to_notify unless block_given?
|
|
15
|
+
|
|
16
|
+
listeners_for(event) << block
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def notify(event, *args)
|
|
20
|
+
the_first_error = nil
|
|
21
|
+
|
|
22
|
+
listeners_for(event).each do |listener|
|
|
23
|
+
begin
|
|
24
|
+
listener.call event, args
|
|
25
|
+
rescue Exception => e
|
|
26
|
+
the_first_error ||= e
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
raise the_first_error if the_first_error
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def accepts?(e); accept_all_by_default; end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def no_way_to_notify
|
|
38
|
+
"No block supplied. How will I notify you?"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def accept_all_by_default; true; end
|
|
42
|
+
|
|
43
|
+
def listeners_for(event)
|
|
44
|
+
fail "Event <#{event}> not supported by #{self.class}." unless accepts?(event) === true
|
|
45
|
+
listeners[event] = [] unless listeners.has_key? event
|
|
46
|
+
listeners[event]
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def listeners; @listeners ||= {}; end
|
|
50
|
+
end
|
data/lib/audible/pidfile.rb
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
class Pidfile
|
|
2
|
-
require "fileutils"; extend FileUtils
|
|
3
|
-
|
|
4
|
-
class << self
|
|
5
|
-
def new(pid=$$)
|
|
6
|
-
File.open path, "w" do |f|
|
|
7
|
-
f.puts pid
|
|
8
|
-
end
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def missing?; false == exists? end
|
|
12
|
-
def exists?; File.exists? path; end
|
|
13
|
-
def delete; rm path; end
|
|
14
|
-
def path; File.join ".", ".pid"; end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
1
|
+
class Pidfile
|
|
2
|
+
require "fileutils"; extend FileUtils
|
|
3
|
+
|
|
4
|
+
class << self
|
|
5
|
+
def new(pid=$$)
|
|
6
|
+
File.open path, "w" do |f|
|
|
7
|
+
f.puts pid
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def missing?; false == exists? end
|
|
12
|
+
def exists?; File.exists? path; end
|
|
13
|
+
def delete; rm path; end
|
|
14
|
+
def path; File.join ".", ".pid"; end
|
|
15
|
+
end
|
|
16
|
+
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
require "rspec"
|
|
2
|
-
require File.join ".", "lib", "audible"
|
|
3
|
-
|
|
4
|
-
Object.class_eval do
|
|
5
|
-
alias :must :should
|
|
6
|
-
alias :must_not :should_not
|
|
7
|
-
end
|
|
1
|
+
require "rspec"
|
|
2
|
+
require File.join ".", "lib", "audible"
|
|
3
|
+
|
|
4
|
+
Object.class_eval do
|
|
5
|
+
alias :must :should
|
|
6
|
+
alias :must_not :should_not
|
|
7
|
+
end
|
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
require File.join ".", "lib", "audible"
|
|
2
|
-
|
|
3
|
-
class TimeServer
|
|
4
|
-
require 'drb/observer'
|
|
5
|
-
include DRb::DRbObservable
|
|
6
|
-
include Audible
|
|
7
|
-
|
|
8
|
-
def get_current_time
|
|
9
|
-
return Time.now
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def progress
|
|
13
|
-
3.times do
|
|
14
|
-
changed
|
|
15
|
-
notify_observers Time.now.to_s
|
|
16
|
-
notify :progress, Time.now.to_s
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
FRONT_OBJECT=TimeServer.new
|
|
22
|
-
|
|
23
|
-
$SAFE = 0
|
|
24
|
-
|
|
25
|
-
require 'drb/drb'
|
|
26
|
-
|
|
27
|
-
port = 9999
|
|
28
|
-
|
|
29
|
-
uri="druby://127.0.0.1:#{port}"
|
|
30
|
-
|
|
31
|
-
DRb.start_service(uri, FRONT_OBJECT)
|
|
32
|
-
|
|
33
|
-
puts "Server has started on port <#{port}>, process <#{$$}>"
|
|
34
|
-
|
|
35
|
-
Signal.trap("INT") do
|
|
36
|
-
puts "Stopping..."
|
|
37
|
-
|
|
38
|
-
Pidfile.delete
|
|
39
|
-
|
|
40
|
-
exit
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
Pidfile.new $$
|
|
44
|
-
|
|
1
|
+
require File.join ".", "lib", "audible"
|
|
2
|
+
|
|
3
|
+
class TimeServer
|
|
4
|
+
require 'drb/observer'
|
|
5
|
+
include DRb::DRbObservable
|
|
6
|
+
include Audible
|
|
7
|
+
|
|
8
|
+
def get_current_time
|
|
9
|
+
return Time.now
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def progress
|
|
13
|
+
3.times do
|
|
14
|
+
changed
|
|
15
|
+
notify_observers Time.now.to_s
|
|
16
|
+
notify :progress, Time.now.to_s
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
FRONT_OBJECT=TimeServer.new
|
|
22
|
+
|
|
23
|
+
$SAFE = 0
|
|
24
|
+
|
|
25
|
+
require 'drb/drb'
|
|
26
|
+
|
|
27
|
+
port = 9999
|
|
28
|
+
|
|
29
|
+
uri="druby://127.0.0.1:#{port}"
|
|
30
|
+
|
|
31
|
+
DRb.start_service(uri, FRONT_OBJECT)
|
|
32
|
+
|
|
33
|
+
puts "Server has started on port <#{port}>, process <#{$$}>"
|
|
34
|
+
|
|
35
|
+
Signal.trap("INT") do
|
|
36
|
+
puts "Stopping..."
|
|
37
|
+
|
|
38
|
+
Pidfile.delete
|
|
39
|
+
|
|
40
|
+
exit
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
Pidfile.new $$
|
|
44
|
+
|
|
45
45
|
DRb.thread.join
|
|
@@ -1,65 +1,65 @@
|
|
|
1
|
-
require "spec_helper"
|
|
2
|
-
require_relative File.join 'support', 'drb_server'
|
|
3
|
-
|
|
4
|
-
describe "Basic drb connections" do
|
|
5
|
-
before :all do
|
|
6
|
-
@server = DrbServer.new("druby://127.0.0.1:9999").tap {|server| server.start}
|
|
7
|
-
@timeserver = DRbObject.new_with_uri @server.url
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
after :all do
|
|
11
|
-
@server.kill
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
before do
|
|
15
|
-
@an_observer = Class.new do
|
|
16
|
-
def update(args)
|
|
17
|
-
@notified = true
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def notified?; @notified === true; end
|
|
21
|
-
|
|
22
|
-
def reset; @notified = false; end
|
|
23
|
-
end.new
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
it "tells me the time" do
|
|
27
|
-
expect(@timeserver.get_current_time.to_s).to match /^#{Time.now.year}/
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
it "can notify" do
|
|
31
|
-
@timeserver.add_observer @an_observer
|
|
32
|
-
|
|
33
|
-
@timeserver.progress
|
|
34
|
-
|
|
35
|
-
expect(@an_observer).to be_notified
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
it "can detach observer which stops notifications" do
|
|
39
|
-
@timeserver.add_observer @an_observer
|
|
40
|
-
|
|
41
|
-
@timeserver.progress
|
|
42
|
-
|
|
43
|
-
expect(@an_observer).to be_notified
|
|
44
|
-
|
|
45
|
-
@an_observer.reset
|
|
46
|
-
|
|
47
|
-
@timeserver.delete_observer @an_observer
|
|
48
|
-
|
|
49
|
-
@timeserver.progress
|
|
50
|
-
|
|
51
|
-
expect(@an_observer).to_not be_notified
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
it "can also get audible notifications" do
|
|
55
|
-
notified = false
|
|
56
|
-
|
|
57
|
-
@timeserver.on(:progress) do |e,args|
|
|
58
|
-
notified = true
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
@timeserver.progress
|
|
62
|
-
|
|
63
|
-
expect(notified).to be_true
|
|
64
|
-
end
|
|
65
|
-
end
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require_relative File.join 'support', 'drb_server'
|
|
3
|
+
|
|
4
|
+
describe "Basic drb connections" do
|
|
5
|
+
before :all do
|
|
6
|
+
@server = DrbServer.new("druby://127.0.0.1:9999").tap {|server| server.start}
|
|
7
|
+
@timeserver = DRbObject.new_with_uri @server.url
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
after :all do
|
|
11
|
+
@server.kill
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
before do
|
|
15
|
+
@an_observer = Class.new do
|
|
16
|
+
def update(args)
|
|
17
|
+
@notified = true
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def notified?; @notified === true; end
|
|
21
|
+
|
|
22
|
+
def reset; @notified = false; end
|
|
23
|
+
end.new
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "tells me the time" do
|
|
27
|
+
expect(@timeserver.get_current_time.to_s).to match /^#{Time.now.year}/
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "can notify" do
|
|
31
|
+
@timeserver.add_observer @an_observer
|
|
32
|
+
|
|
33
|
+
@timeserver.progress
|
|
34
|
+
|
|
35
|
+
expect(@an_observer).to be_notified
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "can detach observer which stops notifications" do
|
|
39
|
+
@timeserver.add_observer @an_observer
|
|
40
|
+
|
|
41
|
+
@timeserver.progress
|
|
42
|
+
|
|
43
|
+
expect(@an_observer).to be_notified
|
|
44
|
+
|
|
45
|
+
@an_observer.reset
|
|
46
|
+
|
|
47
|
+
@timeserver.delete_observer @an_observer
|
|
48
|
+
|
|
49
|
+
@timeserver.progress
|
|
50
|
+
|
|
51
|
+
expect(@an_observer).to_not be_notified
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "can also get audible notifications" do
|
|
55
|
+
notified = false
|
|
56
|
+
|
|
57
|
+
@timeserver.on(:progress) do |e,args|
|
|
58
|
+
notified = true
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
@timeserver.progress
|
|
62
|
+
|
|
63
|
+
expect(notified).to be_true
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
class DrbServer
|
|
2
|
-
attr_reader :url
|
|
3
|
-
|
|
4
|
-
def initialize(url)
|
|
5
|
-
@url = url
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
def start
|
|
9
|
-
exe = File.join(File.dirname(__FILE__), "..", "bin", "server")
|
|
10
|
-
|
|
11
|
-
@pid = Process.spawn "bundle exec ruby #{exe}", :err=>:out, :out => ".log"
|
|
12
|
-
|
|
13
|
-
while Pidfile.missing?
|
|
14
|
-
sleep 0.25
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
require 'drb/drb'
|
|
18
|
-
|
|
19
|
-
DRb.start_service
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def kill
|
|
23
|
-
Process.kill("INT", @pid)
|
|
24
|
-
Process.wait
|
|
25
|
-
end
|
|
26
|
-
end
|
|
1
|
+
class DrbServer
|
|
2
|
+
attr_reader :url
|
|
3
|
+
|
|
4
|
+
def initialize(url)
|
|
5
|
+
@url = url
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def start
|
|
9
|
+
exe = File.join(File.dirname(__FILE__), "..", "bin", "server")
|
|
10
|
+
|
|
11
|
+
@pid = Process.spawn "bundle exec ruby #{exe}", :err=>:out, :out => ".log"
|
|
12
|
+
|
|
13
|
+
while Pidfile.missing?
|
|
14
|
+
sleep 0.25
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
require 'drb/drb'
|
|
18
|
+
|
|
19
|
+
DRb.start_service
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def kill
|
|
23
|
+
Process.kill("INT", @pid)
|
|
24
|
+
Process.wait
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -1,101 +1,101 @@
|
|
|
1
|
-
require "spec_helper"
|
|
2
|
-
|
|
3
|
-
describe "Observable" do
|
|
4
|
-
let(:an_observable_object) do
|
|
5
|
-
Class.new do
|
|
6
|
-
require "observer"; include Observable
|
|
7
|
-
|
|
8
|
-
def poke
|
|
9
|
-
changed
|
|
10
|
-
notify_observers :poked
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def tap
|
|
14
|
-
changed
|
|
15
|
-
notify_observers :tapped
|
|
16
|
-
end
|
|
17
|
-
end.new
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
it "you can register for notifications" do
|
|
21
|
-
an_observer = Class.new do
|
|
22
|
-
def update(args)
|
|
23
|
-
@notified = true
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def notified?; @notified === true; end
|
|
27
|
-
end.new
|
|
28
|
-
|
|
29
|
-
an_observable_object.add_observer(an_observer)
|
|
30
|
-
|
|
31
|
-
an_observable_object.poke
|
|
32
|
-
|
|
33
|
-
an_observer.must be_notified
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
it "and you can send arguments with your notification" do
|
|
37
|
-
an_observer = Class.new do
|
|
38
|
-
def update(args)
|
|
39
|
-
@args = args
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def args; @args; end
|
|
43
|
-
end.new
|
|
44
|
-
|
|
45
|
-
an_observable_object.add_observer(an_observer)
|
|
46
|
-
|
|
47
|
-
an_observable_object.poke
|
|
48
|
-
|
|
49
|
-
an_observer.args.must === :poked
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
it "for multiple events the observer must decide for themselves" do
|
|
53
|
-
an_observer = Class.new do
|
|
54
|
-
def initialize
|
|
55
|
-
@poked,@tapped = 0,0
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def update(args)
|
|
59
|
-
@poked = true if args === :poked
|
|
60
|
-
@tapped = true if args === :tapped
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def poked?; @poked === true; end
|
|
64
|
-
def tapped?; @tapped === true; end
|
|
65
|
-
end.new
|
|
66
|
-
|
|
67
|
-
an_observable_object.add_observer(an_observer)
|
|
68
|
-
|
|
69
|
-
an_observable_object.poke
|
|
70
|
-
an_observable_object.tap
|
|
71
|
-
|
|
72
|
-
an_observer.must be_tapped
|
|
73
|
-
an_observer.must be_poked
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
it "notifications are not sent if `changed` not called" do
|
|
77
|
-
a_bung_observable_object_that_does_not_call_changed = Class.new do
|
|
78
|
-
require "observer"; include Observable
|
|
79
|
-
|
|
80
|
-
def poke
|
|
81
|
-
notify_observers :poked
|
|
82
|
-
end
|
|
83
|
-
end.new
|
|
84
|
-
|
|
85
|
-
an_observer = Class.new do
|
|
86
|
-
def update(args)
|
|
87
|
-
@notified = true
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def notified?; @notified === true; end
|
|
91
|
-
end.new
|
|
92
|
-
|
|
93
|
-
a_bung_observable_object_that_does_not_call_changed.add_observer an_observer
|
|
94
|
-
|
|
95
|
-
a_bung_observable_object_that_does_not_call_changed.poke
|
|
96
|
-
|
|
97
|
-
an_observer.must_not(be_notified,
|
|
98
|
-
"Even though `notify_observers` was called, no notification was sent because you have to call `changed` beforehand."
|
|
99
|
-
)
|
|
100
|
-
end
|
|
101
|
-
end
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe "Observable" do
|
|
4
|
+
let(:an_observable_object) do
|
|
5
|
+
Class.new do
|
|
6
|
+
require "observer"; include Observable
|
|
7
|
+
|
|
8
|
+
def poke
|
|
9
|
+
changed
|
|
10
|
+
notify_observers :poked
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def tap
|
|
14
|
+
changed
|
|
15
|
+
notify_observers :tapped
|
|
16
|
+
end
|
|
17
|
+
end.new
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "you can register for notifications" do
|
|
21
|
+
an_observer = Class.new do
|
|
22
|
+
def update(args)
|
|
23
|
+
@notified = true
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def notified?; @notified === true; end
|
|
27
|
+
end.new
|
|
28
|
+
|
|
29
|
+
an_observable_object.add_observer(an_observer)
|
|
30
|
+
|
|
31
|
+
an_observable_object.poke
|
|
32
|
+
|
|
33
|
+
an_observer.must be_notified
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "and you can send arguments with your notification" do
|
|
37
|
+
an_observer = Class.new do
|
|
38
|
+
def update(args)
|
|
39
|
+
@args = args
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def args; @args; end
|
|
43
|
+
end.new
|
|
44
|
+
|
|
45
|
+
an_observable_object.add_observer(an_observer)
|
|
46
|
+
|
|
47
|
+
an_observable_object.poke
|
|
48
|
+
|
|
49
|
+
an_observer.args.must === :poked
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "for multiple events the observer must decide for themselves" do
|
|
53
|
+
an_observer = Class.new do
|
|
54
|
+
def initialize
|
|
55
|
+
@poked,@tapped = 0,0
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def update(args)
|
|
59
|
+
@poked = true if args === :poked
|
|
60
|
+
@tapped = true if args === :tapped
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def poked?; @poked === true; end
|
|
64
|
+
def tapped?; @tapped === true; end
|
|
65
|
+
end.new
|
|
66
|
+
|
|
67
|
+
an_observable_object.add_observer(an_observer)
|
|
68
|
+
|
|
69
|
+
an_observable_object.poke
|
|
70
|
+
an_observable_object.tap
|
|
71
|
+
|
|
72
|
+
an_observer.must be_tapped
|
|
73
|
+
an_observer.must be_poked
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "notifications are not sent if `changed` not called" do
|
|
77
|
+
a_bung_observable_object_that_does_not_call_changed = Class.new do
|
|
78
|
+
require "observer"; include Observable
|
|
79
|
+
|
|
80
|
+
def poke
|
|
81
|
+
notify_observers :poked
|
|
82
|
+
end
|
|
83
|
+
end.new
|
|
84
|
+
|
|
85
|
+
an_observer = Class.new do
|
|
86
|
+
def update(args)
|
|
87
|
+
@notified = true
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def notified?; @notified === true; end
|
|
91
|
+
end.new
|
|
92
|
+
|
|
93
|
+
a_bung_observable_object_that_does_not_call_changed.add_observer an_observer
|
|
94
|
+
|
|
95
|
+
a_bung_observable_object_that_does_not_call_changed.poke
|
|
96
|
+
|
|
97
|
+
an_observer.must_not(be_notified,
|
|
98
|
+
"Even though `notify_observers` was called, no notification was sent because you have to call `changed` beforehand."
|
|
99
|
+
)
|
|
100
|
+
end
|
|
101
|
+
end
|