informator 0.1.0 → 1.0.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 +4 -4
- data/.travis.yml +6 -0
- data/CHANGELOG.md +31 -0
- data/README.md +114 -46
- data/Rakefile +1 -1
- data/config/metrics/metric_fu.yml +2 -2
- data/config/metrics/rubocop.yml +4 -0
- data/informator.gemspec +12 -9
- data/lib/informator.rb +3 -73
- data/lib/informator/event.rb +35 -30
- data/lib/informator/publisher.rb +103 -0
- data/lib/informator/rspec.rb +3 -0
- data/lib/informator/subscriber.rb +14 -28
- data/lib/informator/version.rb +1 -1
- data/lib/rspec/shared.rb +104 -0
- data/spec/integration/en.yml +6 -0
- data/spec/integration/fr.yml +6 -0
- data/spec/integration/i18n.rb +21 -0
- data/spec/integration/rspec_spec.rb +51 -0
- data/spec/unit/informator/event_spec.rb +82 -28
- data/spec/unit/informator/publisher_spec.rb +168 -0
- data/spec/unit/informator/subscriber_spec.rb +26 -40
- metadata +59 -11
- data/lib/informator/reporter.rb +0 -67
- data/spec/unit/informator/reporter_spec.rb +0 -75
- data/spec/unit/informator_spec.rb +0 -153
@@ -0,0 +1,168 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require "timecop"
|
4
|
+
|
5
|
+
describe Informator::Publisher do
|
6
|
+
|
7
|
+
before { Timecop.freeze } # to allow time-dependent events being equal
|
8
|
+
after { Timecop.return }
|
9
|
+
|
10
|
+
let(:pub_class) { Informator::Foo = Class.new(described_class) }
|
11
|
+
let(:publisher) { pub_class.new attributes }
|
12
|
+
let(:attributes) { { foo: :FOO, bar: :BAR } }
|
13
|
+
let(:listener) { double callback => nil, freeze: nil }
|
14
|
+
let(:callback) { :call }
|
15
|
+
let(:name) { :foo }
|
16
|
+
let(:subscriber) { Informator::Subscriber.new listener, callback }
|
17
|
+
let(:event) { Informator::Event.new publisher, name, attributes }
|
18
|
+
|
19
|
+
describe ".new" do
|
20
|
+
|
21
|
+
subject { publisher }
|
22
|
+
|
23
|
+
it { is_expected.to be_frozen }
|
24
|
+
|
25
|
+
it "doesn't freeze attirbutes" do
|
26
|
+
expect { subject }.not_to change { attributes.frozen? }
|
27
|
+
end
|
28
|
+
|
29
|
+
end # describe .new
|
30
|
+
|
31
|
+
describe "#attributes" do
|
32
|
+
|
33
|
+
subject { publisher.attributes }
|
34
|
+
|
35
|
+
it { is_expected.to be_frozen }
|
36
|
+
it { is_expected.to eql attributes }
|
37
|
+
|
38
|
+
context "by default" do
|
39
|
+
|
40
|
+
let(:publisher) { pub_class.new }
|
41
|
+
|
42
|
+
it { is_expected.to eql({}) }
|
43
|
+
|
44
|
+
end # context
|
45
|
+
|
46
|
+
end # describe #attributes
|
47
|
+
|
48
|
+
describe "#==" do
|
49
|
+
|
50
|
+
subject { publisher == other }
|
51
|
+
|
52
|
+
context "with the same types and attributes" do
|
53
|
+
|
54
|
+
let(:other) { publisher.subscribe(listener, callback) }
|
55
|
+
it { is_expected.to eql true }
|
56
|
+
|
57
|
+
end # context
|
58
|
+
|
59
|
+
context "with different types" do
|
60
|
+
|
61
|
+
let(:other) { described_class.new(attributes) }
|
62
|
+
it { is_expected.to eql false }
|
63
|
+
|
64
|
+
end # context
|
65
|
+
|
66
|
+
context "with different attributes" do
|
67
|
+
|
68
|
+
let(:other) { pub_class.new }
|
69
|
+
it { is_expected.to eql false }
|
70
|
+
|
71
|
+
end # context
|
72
|
+
|
73
|
+
end # describe #==
|
74
|
+
|
75
|
+
describe "#eql?" do
|
76
|
+
|
77
|
+
subject { publisher == other }
|
78
|
+
let(:other) { publisher.subscribe(listener, callback) }
|
79
|
+
|
80
|
+
it "aliases #==" do
|
81
|
+
expect(subject).to eql true
|
82
|
+
end
|
83
|
+
|
84
|
+
end # describe #==
|
85
|
+
|
86
|
+
describe "#inspect" do
|
87
|
+
|
88
|
+
subject { publisher.inspect }
|
89
|
+
it { is_expected.to eql "#<Informator::Foo @attributes=#{attributes}>" }
|
90
|
+
|
91
|
+
end # describe #inspect
|
92
|
+
|
93
|
+
describe "#to_s" do
|
94
|
+
|
95
|
+
subject { publisher.to_s }
|
96
|
+
it { is_expected.to eql publisher.inspect }
|
97
|
+
|
98
|
+
end # describe #to_s
|
99
|
+
|
100
|
+
describe "#subscribers" do
|
101
|
+
|
102
|
+
subject { publisher.subscribers }
|
103
|
+
|
104
|
+
it { is_expected.to eql Set.new }
|
105
|
+
it { is_expected.to be_frozen }
|
106
|
+
|
107
|
+
end # describe #attributes
|
108
|
+
|
109
|
+
describe "#subscribe" do
|
110
|
+
|
111
|
+
subject { publisher.subscribe(listener, callback) }
|
112
|
+
|
113
|
+
it { is_expected.to be_kind_of described_class }
|
114
|
+
|
115
|
+
it "preserves attributes" do
|
116
|
+
expect(subject.attributes).to eql attributes
|
117
|
+
end
|
118
|
+
|
119
|
+
it "registers new subscriber" do
|
120
|
+
other = Informator::Subscriber.new listener, "other"
|
121
|
+
|
122
|
+
updated = subject.subscribe(listener, "other")
|
123
|
+
expect(updated.subscribers).to contain_exactly subscriber, other
|
124
|
+
end
|
125
|
+
|
126
|
+
it "skips registered subscriber" do
|
127
|
+
updated = subject.subscribe(listener, callback)
|
128
|
+
expect(updated.subscribers).to contain_exactly subscriber
|
129
|
+
end
|
130
|
+
|
131
|
+
end # describe #subscribe
|
132
|
+
|
133
|
+
describe "#publish" do
|
134
|
+
|
135
|
+
subject { publisher.subscribe(listener, callback).publish name, attributes }
|
136
|
+
|
137
|
+
it "sends event to subscribers" do
|
138
|
+
expect(listener).to receive(callback).with(event)
|
139
|
+
subject
|
140
|
+
end
|
141
|
+
|
142
|
+
it { is_expected.to eql event }
|
143
|
+
|
144
|
+
end # describe #publish
|
145
|
+
|
146
|
+
describe "#publish!" do
|
147
|
+
|
148
|
+
let(:caller) { publisher.subscribe(listener, callback) }
|
149
|
+
subject { caller.publish! name, attributes }
|
150
|
+
|
151
|
+
it "sends event to subscribers" do
|
152
|
+
expect(listener).to receive(callback).with(event)
|
153
|
+
subject rescue nil
|
154
|
+
end
|
155
|
+
|
156
|
+
it "throws an exception" do
|
157
|
+
expect { subject }.to raise_error(ArgumentError)
|
158
|
+
end
|
159
|
+
|
160
|
+
it "carries the event" do
|
161
|
+
expect(catch(:published) { subject }).to eql event
|
162
|
+
end
|
163
|
+
|
164
|
+
end # describe #publish!
|
165
|
+
|
166
|
+
after { Informator.send :remove_const, :Foo }
|
167
|
+
|
168
|
+
end # describe Informator::Publisher
|
@@ -2,84 +2,70 @@
|
|
2
2
|
|
3
3
|
describe Informator::Subscriber do
|
4
4
|
|
5
|
-
let(:callback)
|
6
|
-
let(:event)
|
7
|
-
let(:
|
8
|
-
|
9
|
-
subject(:subscriber) { described_class.new object, callback }
|
5
|
+
let(:callback) { "foo" }
|
6
|
+
let(:event) { double }
|
7
|
+
let(:listener) { double callback => callback, freeze: nil }
|
8
|
+
let(:subscriber) { described_class.new listener, callback }
|
10
9
|
|
11
10
|
describe ".new" do
|
12
11
|
|
12
|
+
subject { subscriber }
|
13
13
|
it { is_expected.to be_frozen }
|
14
14
|
|
15
15
|
end # describe .new
|
16
16
|
|
17
|
-
describe "#
|
17
|
+
describe "#listener" do
|
18
18
|
|
19
|
-
subject { subscriber.
|
20
|
-
it { is_expected.to eql
|
19
|
+
subject { subscriber.listener }
|
20
|
+
it { is_expected.to eql listener }
|
21
21
|
|
22
|
-
end # describe #
|
22
|
+
end # describe #listener
|
23
23
|
|
24
24
|
describe "#callback" do
|
25
25
|
|
26
26
|
subject { subscriber.callback }
|
27
27
|
it { is_expected.to eql callback.to_sym }
|
28
28
|
|
29
|
-
context "when callback isn't defined" do
|
30
|
-
|
31
|
-
let(:subscriber) { described_class.new object }
|
32
|
-
it { is_expected.to eql :receive }
|
33
|
-
|
34
|
-
end # context
|
35
|
-
|
36
29
|
end # describe #callback
|
37
30
|
|
38
|
-
describe "#notify" do
|
39
|
-
|
40
|
-
subject { subscriber.notify event }
|
41
|
-
|
42
|
-
it "sends event to object via callback" do
|
43
|
-
expect(object).to receive(callback).with(event)
|
44
|
-
subject
|
45
|
-
end
|
46
|
-
|
47
|
-
it { is_expected.to eql event }
|
48
|
-
|
49
|
-
end # describe #notify
|
50
|
-
|
51
31
|
describe "#==" do
|
52
32
|
|
53
33
|
subject { subscriber == other }
|
54
34
|
|
55
|
-
context "
|
35
|
+
context "with the same listeners and callbacks" do
|
56
36
|
|
57
|
-
let(:other) {
|
37
|
+
let(:other) { described_class.new listener, callback }
|
58
38
|
it { is_expected.to eql true }
|
59
39
|
|
60
40
|
end # context
|
61
41
|
|
62
|
-
context "
|
42
|
+
context "with different listeners" do
|
63
43
|
|
64
|
-
let(:other) { double
|
44
|
+
let(:other) { described_class.new double(freeze: nil), callback }
|
65
45
|
it { is_expected.to eql false }
|
66
46
|
|
67
47
|
end # context
|
68
48
|
|
69
|
-
context "
|
49
|
+
context "with different callbacks" do
|
70
50
|
|
71
|
-
let(:other) { described_class.new
|
51
|
+
let(:other) { described_class.new listener, "other" }
|
72
52
|
it { is_expected.to eql false }
|
73
53
|
|
74
54
|
end # context
|
75
55
|
|
76
|
-
|
56
|
+
end # describe #==
|
77
57
|
|
78
|
-
|
79
|
-
it { is_expected.to eql false }
|
58
|
+
describe "#notify" do
|
80
59
|
|
81
|
-
|
60
|
+
subject { subscriber.notify event }
|
82
61
|
|
83
|
-
|
62
|
+
it "sends event to listener via callback" do
|
63
|
+
expect(listener).to receive(callback).with(event)
|
64
|
+
subject
|
65
|
+
end
|
66
|
+
|
67
|
+
it { is_expected.to eql event }
|
68
|
+
|
69
|
+
end # describe #notify
|
84
70
|
|
85
71
|
end # describe Informator::Subscriber
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: informator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kozin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-07-
|
11
|
+
date: 2015-07-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: i18n
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0.
|
19
|
+
version: '0.7'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0.
|
26
|
+
version: '0.7'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: ice_nine
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,6 +38,34 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0.11'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: inflecto
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: equalizer
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.0'
|
41
69
|
- !ruby/object:Gem::Dependency
|
42
70
|
name: hexx-rspec
|
43
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,6 +80,20 @@ dependencies:
|
|
52
80
|
- - "~>"
|
53
81
|
- !ruby/object:Gem::Version
|
54
82
|
version: '0.5'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: timecop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.7'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.7'
|
55
97
|
description:
|
56
98
|
email: andrew.kozin@gmail.com
|
57
99
|
executables: []
|
@@ -87,14 +129,19 @@ files:
|
|
87
129
|
- informator.gemspec
|
88
130
|
- lib/informator.rb
|
89
131
|
- lib/informator/event.rb
|
90
|
-
- lib/informator/
|
132
|
+
- lib/informator/publisher.rb
|
133
|
+
- lib/informator/rspec.rb
|
91
134
|
- lib/informator/subscriber.rb
|
92
135
|
- lib/informator/version.rb
|
136
|
+
- lib/rspec/shared.rb
|
137
|
+
- spec/integration/en.yml
|
138
|
+
- spec/integration/fr.yml
|
139
|
+
- spec/integration/i18n.rb
|
140
|
+
- spec/integration/rspec_spec.rb
|
93
141
|
- spec/spec_helper.rb
|
94
142
|
- spec/unit/informator/event_spec.rb
|
95
|
-
- spec/unit/informator/
|
143
|
+
- spec/unit/informator/publisher_spec.rb
|
96
144
|
- spec/unit/informator/subscriber_spec.rb
|
97
|
-
- spec/unit/informator_spec.rb
|
98
145
|
homepage: https://github.com/nepalez/informator
|
99
146
|
licenses:
|
100
147
|
- MIT
|
@@ -107,7 +154,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
107
154
|
requirements:
|
108
155
|
- - "~>"
|
109
156
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
157
|
+
version: 1.9.3
|
111
158
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
159
|
requirements:
|
113
160
|
- - ">="
|
@@ -121,8 +168,9 @@ specification_version: 4
|
|
121
168
|
summary: Implementation of publish/subscribe design pattern
|
122
169
|
test_files:
|
123
170
|
- spec/spec_helper.rb
|
124
|
-
- spec/
|
171
|
+
- spec/integration/i18n.rb
|
172
|
+
- spec/integration/rspec_spec.rb
|
125
173
|
- spec/unit/informator/event_spec.rb
|
126
|
-
- spec/unit/informator/
|
174
|
+
- spec/unit/informator/publisher_spec.rb
|
127
175
|
- spec/unit/informator/subscriber_spec.rb
|
128
176
|
has_rdoc:
|
data/lib/informator/reporter.rb
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Informator
|
4
|
-
|
5
|
-
# Builds, collects and publishes events to selected subscribers
|
6
|
-
#
|
7
|
-
# @example
|
8
|
-
# reporter = Reporter.new
|
9
|
-
# reporter.events # => []
|
10
|
-
#
|
11
|
-
# reporter.remember :success
|
12
|
-
# reporter.events # => [#<Event @type=:success @attributes={} @messages=[]>]
|
13
|
-
#
|
14
|
-
# # this will call subscriber.notify for any event
|
15
|
-
# reporter.notify subscriber
|
16
|
-
# reporter.events # => []
|
17
|
-
#
|
18
|
-
# @api private
|
19
|
-
#
|
20
|
-
class Reporter
|
21
|
-
|
22
|
-
# @private
|
23
|
-
def initialize
|
24
|
-
@events = []
|
25
|
-
freeze # freezes the instance, but left events mutable!
|
26
|
-
end
|
27
|
-
|
28
|
-
# @!attribute [r] events
|
29
|
-
# @return [Array<Informator::Event>]
|
30
|
-
# the list of registered events that havent'b been published yet
|
31
|
-
attr_reader :events
|
32
|
-
|
33
|
-
# @!method remember(type, messages, attributes)
|
34
|
-
# Registers the event to be published to subscribers
|
35
|
-
#
|
36
|
-
# @param (see Informator::Event.new)
|
37
|
-
#
|
38
|
-
# @return [self] itself
|
39
|
-
#
|
40
|
-
def remember(*args)
|
41
|
-
events << Event.new(*args)
|
42
|
-
|
43
|
-
self
|
44
|
-
end
|
45
|
-
|
46
|
-
# Notifies subscribers on events registered since the last notification
|
47
|
-
#
|
48
|
-
# Mutates [#events] by excluding all events having been published.
|
49
|
-
#
|
50
|
-
# @param [Informator::Subscriber, Array<Informator::Subscriber>] subscribers
|
51
|
-
# the list of subscribers to be notified
|
52
|
-
#
|
53
|
-
# @return [Array<Informator::Event>] the list of published events
|
54
|
-
def notify(*subscribers)
|
55
|
-
events.dup.each { publish subscribers.flatten }
|
56
|
-
end
|
57
|
-
|
58
|
-
private
|
59
|
-
|
60
|
-
def publish(subscribers)
|
61
|
-
event = events.shift
|
62
|
-
subscribers.each { |subscriber| subscriber.notify(event) }
|
63
|
-
end
|
64
|
-
|
65
|
-
end # class Reporter
|
66
|
-
|
67
|
-
end # module Informator
|