tavern 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,6 +1,9 @@
1
1
  # Tavern
2
2
 
3
- TODO: Write a gem description
3
+ Tavern is a simple implementation of Pub / Sub for Ruby applications, allowing one
4
+ to subscribe to topics (named by a:b:c) and to then publish events. It's designed
5
+ to have a minimal surface area for the api to make it simple to integrate into other
6
+ systems (e.g. so you can publish events over a network).
4
7
 
5
8
  ## Installation
6
9
 
@@ -18,7 +21,27 @@ Or install it yourself as:
18
21
 
19
22
  ## Usage
20
23
 
21
- TODO: Write usage instructions here
24
+
25
+ The core of Tavern is a `Tavern::Hub`, a default one which can be accessed at `Tavern.hub`.
26
+
27
+ The core methods on this object (and any new Taver Hub) are:
28
+
29
+ * `hub.subscribe(topic, callable = nil, &block)` - Creates a subscription for the given topic
30
+ using either a callable object or a block. Will return the instance of the subscription. Note
31
+ that this will also match any child notifications - e.g. publishing `a:b:c` will match subscriptions
32
+ for `a:b` and `a`. The callable should take one argument which includes an environment merged with
33
+ some extra details.
34
+ * `hub.publish(topic, context = {})` - Publishes an event with a given name, including the specified
35
+ context optionally passed into the callable. Topics should be of the form `a:b:c` with no limit on items.
36
+ Will return the full published metadata.
37
+ * `hub.unsubscribe(subscription)` - Given a return from `hub.subscribe`, will unsubscribe it and prevent
38
+ it from receiving any new messages.
39
+
40
+ The idea behind this decoupled architecture is that it doesn't matter how the middle layer is implemented,
41
+ you can just publish and receive messages with no worries. At the moment, subscriptions happen in app.
42
+
43
+ For conveinience sake, we also proxy `subscribe` and `publish` on the `Tavern` object to the default hub
44
+ at `Tavern.hub`.
22
45
 
23
46
  ## Contributing
24
47
 
@@ -2,6 +2,7 @@ require 'tavern/subscription'
2
2
  require 'tavern/subscriptions'
3
3
  require 'active_support/core_ext/module/delegation'
4
4
  require 'active_support/core_ext/object/blank'
5
+ require 'active_support/lazy_load_hooks'
5
6
 
6
7
  module Tavern
7
8
 
@@ -93,9 +94,9 @@ module Tavern
93
94
 
94
95
  def primary=(value)
95
96
  value = !!value
96
- if value != @value
97
- @value = value
98
- ActiveSupport.run_load_hooks :smeg_head_hub, self
97
+ if value != @primary
98
+ @primary = value
99
+ ActiveSupport.run_load_hooks :tavern_hub, self if @primary
99
100
  end
100
101
  end
101
102
 
@@ -1,3 +1,3 @@
1
1
  module Tavern
2
- VERSION = "0.0.1"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -15,6 +15,10 @@ describe Tavern::Hub do
15
15
  published << ctx
16
16
  end
17
17
 
18
+ def times_called
19
+ published.size
20
+ end
21
+
18
22
  end
19
23
  end
20
24
 
@@ -26,43 +30,125 @@ describe Tavern::Hub do
26
30
 
27
31
  describe 'the primary hub' do
28
32
 
29
- it 'should let you query if something is the primary hub'
33
+ after :each do
34
+ # Force a final reset
35
+ Tavern.hub = nil
36
+ end
30
37
 
31
- it 'should run the load hook when the hub is changed'
38
+ it 'should let you query if something is the primary hub' do
39
+ hub.should respond_to(:primary?)
40
+ hub.should_not be_primary
41
+ Tavern.hub.should_not == hub
42
+ Tavern.hub.should be_primary
43
+ end
32
44
 
33
- it 'should unset it when changing the hub'
45
+ it 'should run the load hook when the hub is changed' do
46
+ Tavern.hub # Force it to have loaded before hand.
47
+ called = 0
48
+ found_hub = nil
49
+ ActiveSupport.on_load(:tavern_hub) do |hub|
50
+ called += 1
51
+ found_hub = hub
52
+ end
53
+ called = 0
54
+ Tavern.hub = hub
55
+ called.should == 1
56
+ found_hub.should == hub
57
+ end
34
58
 
35
- it 'should set it to primary when setting it to the hub value'
59
+ it 'should unset it when changing the hub' do
60
+ hub = Tavern.hub
61
+ hub.should be_primary
62
+ Tavern.hub = Tavern::Hub.new
63
+ hub.should_not be_primary
64
+ end
36
65
 
37
- it 'always set the default to be primary'
66
+ it 'should set it to primary when setting it to the hub value' do
67
+ hub = Tavern::Hub.new
68
+ hub.should_not be_primary
69
+ Tavern.hub = hub
70
+ hub.should be_primary
71
+ end
72
+
73
+ it 'always set the default to be primary' do
74
+ # Force a recet to nil
75
+ Tavern.hub = nil
76
+ Tavern.hub.should be_primary
77
+ end
38
78
 
39
79
  end
40
80
 
41
81
  describe '#subscribe' do
42
82
 
43
- it 'should let you subscribe to a top level item'
83
+ let(:tracker) { Struct.new(:called).new(0) }
84
+ let(:callback) { lambda { |e| tracker.called += 1 } }
44
85
 
45
- it 'should let you subscribe to a nested item'
46
-
47
- it 'should let you pass an object'
86
+ it 'should let you subscribe to a top level item' do
87
+ hub.subscribe('x', &callback)
88
+ expect { hub.publish('x') }.to change tracker, :called
89
+ expect { hub.publish('x:y') }.to change tracker, :called
90
+ expect { hub.publish('x:y:z') }.to change tracker, :called
91
+ end
48
92
 
49
- it 'should let you pass a block'
93
+ it 'should let you subscribe to a nested item' do
94
+ hub.subscribe('x:y:z', &callback)
95
+ expect { hub.publish('x:y:z') }.to change tracker, :called
96
+ expect { hub.publish('x:y') }.to_not change tracker, :called
97
+ expect { hub.publish('x') }.to_not change tracker, :called
98
+ end
99
+
100
+ it 'should let you pass an object' do
101
+ callback = Struct.new(:tracker).new(tracker)
102
+ def callback.call(e); tracker.called += 1; end
103
+ hub.subscribe('x', callback)
104
+ expect { hub.publish('x') }.to change tracker, :called
105
+ end
50
106
 
51
- it 'should return a subscription'
107
+ it 'should let you pass a block' do
108
+ hub.subscribe('x') { |e| tracker.called += 1 }
109
+ expect { hub.publish('x') }.to change tracker, :called
110
+ end
52
111
 
53
- it 'should automatically subscribe to lower level nested events'
112
+ it 'should return a subscription' do
113
+ subscription = hub.subscribe('x', &callback)
114
+ subscription.should be_present
115
+ subscription.should be_a Tavern::Subscription
116
+ end
54
117
 
55
- it 'should raise an error when subscribing with an object that does not provide call'
118
+ it 'should raise an error when subscribing with an object that does not provide call' do
119
+ expect do
120
+ hub.subscribe 'test', Object.new
121
+ end.to raise_error ArgumentError
122
+ end
56
123
 
57
124
  end
58
125
 
59
126
  describe '#unsubscribe' do
60
127
 
61
- it 'should remove an object from the subscription pool'
128
+ let(:tracker) { Struct.new(:count, :calls).new(0, []) }
62
129
 
63
- it 'should return the subscription'
130
+ let!(:subscription) do
131
+ t = tracker
132
+ hub.subscribe 'test' do |e|
133
+ t.count += 1
134
+ t.calls << e
135
+ end
136
+ end
64
137
 
65
- it 'should do nothing with a blank item'
138
+ it 'should remove an object from the subscription pool' do
139
+ expect { hub.publish 'test' }.to change tracker, :count
140
+ hub.unsubscribe subscription
141
+ expect { hub.publish 'test' }.to_not change tracker, :count
142
+ end
143
+
144
+ it 'should return the subscription' do
145
+ hub.unsubscribe(subscription).should == subscription
146
+ end
147
+
148
+ it 'should do nothing with a blank item' do
149
+ hub.unsubscribe(nil).should be_nil
150
+ hub.unsubscribe('').should be_nil
151
+ end
66
152
 
67
153
  end
68
154
 
@@ -104,11 +190,12 @@ describe Tavern::Hub do
104
190
  hub.publish 'hello:world', {}
105
191
  end
106
192
 
107
- it 'should notify all subscriptions under the path'
108
-
109
- it 'should not notify unmatched subscriptions on a simple case'
110
-
111
- it 'should not notify unmatched subscriptions on a nested case'
193
+ it 'should notify all subscriptions under the path' do
194
+ expect { hub.publish 'hello:world' }.to change top_level_a, :times_called
195
+ expect { hub.publish 'hello:world' }.to change nested_a, :times_called
196
+ expect { hub.publish 'foo' }.to change top_level_b, :times_called
197
+ expect { hub.publish 'foo' }.to_not change nested_b, :times_called
198
+ end
112
199
 
113
200
  end
114
201
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tavern
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors: