sub_pub 0.0.3 → 0.0.6
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/Gemfile.lock +1 -1
- data/README.md +8 -0
- data/Rakefile +11 -0
- data/lib/sub_pub/active_record_extensions.rb +13 -29
- data/lib/sub_pub/active_record_subscriber.rb +13 -0
- data/lib/sub_pub/railtie.rb +15 -0
- data/lib/sub_pub/register.rb +43 -4
- data/lib/sub_pub/scoped_topic.rb +16 -0
- data/lib/sub_pub/subscriber.rb +1 -1
- data/lib/sub_pub/subscription.rb +26 -0
- data/lib/sub_pub/version.rb +1 -1
- data/lib/sub_pub.rb +15 -3
- data/pkg/sub_pub-0.0.4.gem +0 -0
- data/spec/integration/sub_pub_spec.rb +177 -0
- data/spec/spec_helper.rb +4 -2
- data/spec/unit/register_spec.rb +5 -0
- metadata +12 -10
- data/spec/integration/pub_sub_spec.rb +0 -66
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -92,6 +92,14 @@ Or install it yourself as:
|
|
92
92
|
User.create(name: 'John Doe')
|
93
93
|
=> SubPub.publish("active_record::user::after_create")
|
94
94
|
|
95
|
+
|
96
|
+
## Supported Active Record Callbacks
|
97
|
+
|
98
|
+
* before_create
|
99
|
+
* after_create
|
100
|
+
* after_commit
|
101
|
+
|
102
|
+
|
95
103
|
## Backlog / To Do
|
96
104
|
|
97
105
|
http://www.pivotaltracker.com/projects/705655
|
data/Rakefile
CHANGED
@@ -1,38 +1,22 @@
|
|
1
1
|
module SubPub
|
2
|
-
|
3
|
-
|
4
|
-
class ::ActiveRecord::Base
|
5
|
-
after_create :notify_of_after_create
|
2
|
+
module ActiveRecordExtensions
|
3
|
+
extend ActiveSupport::Concern
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
message = "active_record::#{self.class.to_s.underscore}::#{callback}"
|
15
|
-
SubPub.publish(message, record: self)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
config.after_initialize do
|
20
|
-
Dir[
|
21
|
-
File.expand_path("app/models/pub_sub/*.rb", Rails.root)
|
22
|
-
].each { |file| require file }
|
5
|
+
included do
|
6
|
+
['before_create', 'after_create', 'after_commit'].each do |callback|
|
7
|
+
class_eval "
|
8
|
+
#{callback} do
|
9
|
+
notify_pub_sub_of_active_record_callback('#{callback}')
|
10
|
+
end
|
11
|
+
"
|
23
12
|
end
|
24
13
|
end
|
25
|
-
end
|
26
14
|
|
27
|
-
|
28
|
-
class Subscriber < SubPub::Subscriber
|
29
|
-
def self.subscribe_to(class_instance, callback)
|
30
|
-
super("active_record::#{class_instance.to_s.underscore}::#{callback}")
|
31
|
-
end
|
15
|
+
private
|
32
16
|
|
33
|
-
|
34
|
-
|
35
|
-
|
17
|
+
def notify_pub_sub_of_active_record_callback(callback)
|
18
|
+
message = "active_record::#{self.class.to_s.underscore}::#{callback}"
|
19
|
+
SubPub.publish(message, record: self)
|
36
20
|
end
|
37
21
|
end
|
38
22
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module SubPub
|
2
|
+
module ActiveRecord
|
3
|
+
class Subscriber < SubPub::Subscriber
|
4
|
+
def self.subscribe_to(class_instance, callback)
|
5
|
+
super("active_record::#{class_instance.to_s.underscore}::#{callback}")
|
6
|
+
end
|
7
|
+
|
8
|
+
def record
|
9
|
+
options[:record]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module SubPub
|
2
|
+
class Railtie < Rails::Railtie
|
3
|
+
initializer "pub sub configuration of active record extensions" do
|
4
|
+
class ::ActiveRecord::Base
|
5
|
+
include SubPub::ActiveRecordExtensions
|
6
|
+
end
|
7
|
+
|
8
|
+
config.after_initialize do
|
9
|
+
Dir[
|
10
|
+
File.expand_path("app/models/pub_sub/*.rb", Rails.root)
|
11
|
+
].each { |file| require file }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/sub_pub/register.rb
CHANGED
@@ -4,14 +4,28 @@ module SubPub
|
|
4
4
|
class Register
|
5
5
|
include Singleton
|
6
6
|
|
7
|
-
attr_accessor :enabled
|
7
|
+
attr_accessor :enabled, :scope, :subscriptions
|
8
8
|
|
9
9
|
def initialize
|
10
|
-
@enabled =
|
10
|
+
@enabled = default_enabled_state
|
11
|
+
@scope = default_scope
|
12
|
+
@subscriptions = []
|
11
13
|
super
|
12
14
|
end
|
13
15
|
|
16
|
+
def default_enabled_state
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
def default_scope
|
21
|
+
"sub_pub"
|
22
|
+
end
|
23
|
+
|
14
24
|
class << self
|
25
|
+
def scope=(new_scope)
|
26
|
+
instance.scope = new_scope
|
27
|
+
end
|
28
|
+
|
15
29
|
def enable
|
16
30
|
instance.enabled = true
|
17
31
|
end
|
@@ -35,11 +49,36 @@ module SubPub
|
|
35
49
|
def publish(*args, &block)
|
36
50
|
return if disabled?
|
37
51
|
|
38
|
-
|
52
|
+
topic = args.shift
|
53
|
+
payload = args.last
|
54
|
+
full_topic = scoped(topic).full_topic
|
55
|
+
|
56
|
+
ActiveSupport::Notifications.publish(full_topic, payload, &block)
|
57
|
+
end
|
58
|
+
|
59
|
+
def scoped(topic)
|
60
|
+
ScopedTopic.new(topic, instance.scope)
|
39
61
|
end
|
40
62
|
|
41
63
|
def subscribe(*args, &block)
|
42
|
-
|
64
|
+
topic = args.first
|
65
|
+
|
66
|
+
options = {
|
67
|
+
scoped_topic: ScopedTopic.new(topic, instance.scope),
|
68
|
+
action: block
|
69
|
+
}
|
70
|
+
|
71
|
+
Subscription.subscribe(options).tap do |subscription|
|
72
|
+
instance.subscriptions << subscription
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def unsubscribe_all
|
77
|
+
instance.subscriptions.each do |subscription|
|
78
|
+
subscription.unsubscribe
|
79
|
+
end
|
80
|
+
|
81
|
+
instance.subscriptions = []
|
43
82
|
end
|
44
83
|
end
|
45
84
|
end
|
data/lib/sub_pub/subscriber.rb
CHANGED
@@ -0,0 +1,26 @@
|
|
1
|
+
module SubPub
|
2
|
+
class Subscription
|
3
|
+
def initialize(options)
|
4
|
+
@scoped_topic = options[:scoped_topic]
|
5
|
+
@action = options[:action]
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.subscribe(options)
|
9
|
+
subscription = new(options)
|
10
|
+
subscription.subscribe
|
11
|
+
subscription
|
12
|
+
end
|
13
|
+
|
14
|
+
def subscribe
|
15
|
+
@subscription = ActiveSupport::Notifications.subscribe(@scoped_topic.full_topic, @action)
|
16
|
+
end
|
17
|
+
|
18
|
+
def unsubscribe
|
19
|
+
ActiveSupport::Notifications.unsubscribe(@scoped_topic.full_topic)
|
20
|
+
end
|
21
|
+
|
22
|
+
def topic
|
23
|
+
@scoped_topic.topic
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/sub_pub/version.rb
CHANGED
data/lib/sub_pub.rb
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
module SubPub
|
2
2
|
class << self
|
3
|
+
def scope=(new_scope)
|
4
|
+
Register.scope = new_scope
|
5
|
+
end
|
6
|
+
|
3
7
|
def enable
|
4
8
|
Register.enable
|
5
9
|
end
|
@@ -26,14 +30,22 @@ module SubPub
|
|
26
30
|
def subscribe(*args, &block)
|
27
31
|
Register.subscribe(*args, &block)
|
28
32
|
end
|
33
|
+
|
34
|
+
def unsubscribe_all
|
35
|
+
Register.unsubscribe_all
|
36
|
+
end
|
29
37
|
end
|
30
38
|
end
|
31
39
|
|
32
40
|
require "sub_pub/version"
|
33
41
|
require "sub_pub/subscriber"
|
34
42
|
require "sub_pub/register"
|
43
|
+
require "sub_pub/subscription"
|
44
|
+
require "sub_pub/scoped_topic"
|
35
45
|
|
36
|
-
require
|
37
|
-
require
|
46
|
+
require "rails"
|
47
|
+
require "active_record"
|
38
48
|
|
39
|
-
|
49
|
+
require "sub_pub/active_record_subscriber"
|
50
|
+
require "sub_pub/active_record_extensions"
|
51
|
+
require "sub_pub/railtie"
|
Binary file
|
@@ -0,0 +1,177 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SubPub do
|
4
|
+
with_model :FakeActiveRecordUser do
|
5
|
+
table do |t|
|
6
|
+
t.string :title
|
7
|
+
end
|
8
|
+
|
9
|
+
model do
|
10
|
+
has_many :fake_active_record_results
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
with_model :FakeActiveRecordResult do
|
15
|
+
table do |t|
|
16
|
+
t.string :title
|
17
|
+
t.integer :fake_active_record_user_id
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "initial state" do
|
22
|
+
it "defaults enabled to true" do
|
23
|
+
SubPub::Register.instance.enabled = nil
|
24
|
+
SubPub.enabled?.should be_true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#enable" do
|
29
|
+
it "enables SubPub" do
|
30
|
+
SubPub.disable
|
31
|
+
SubPub.enable
|
32
|
+
SubPub.enabled?.should be_true
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#disable" do
|
37
|
+
it "disables SubPub" do
|
38
|
+
SubPub.disable
|
39
|
+
SubPub.enabled?.should be_false
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#publish" do
|
44
|
+
context "when disabled" do
|
45
|
+
before { SubPub.disable }
|
46
|
+
|
47
|
+
it "does not publish" do
|
48
|
+
ActiveSupport::Notifications.should_receive(:publish).never
|
49
|
+
SubPub.publish
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "with a set scope" do
|
54
|
+
it "uses the configured scope" do
|
55
|
+
payload = { :payload => 'here' }
|
56
|
+
|
57
|
+
SubPub.scope = 'rails'
|
58
|
+
|
59
|
+
ActiveSupport::Notifications.should_receive(:publish).with(
|
60
|
+
"rails::my-message",
|
61
|
+
payload
|
62
|
+
)
|
63
|
+
|
64
|
+
SubPub.publish("my-message", payload)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context "when using the default scope" do
|
69
|
+
it "publishes to active support using the default scope" do
|
70
|
+
payload = { :payload => 'here' }
|
71
|
+
|
72
|
+
ActiveSupport::Notifications.should_receive(:publish).with(
|
73
|
+
"sub_pub::my-message",
|
74
|
+
payload
|
75
|
+
)
|
76
|
+
|
77
|
+
SubPub.publish("my-message", payload)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "normal pubsub" do
|
83
|
+
before do
|
84
|
+
class CreateAccountSubscriber < SubPub::Subscriber
|
85
|
+
subscribe_to("new_account_posted")
|
86
|
+
|
87
|
+
def on_publish
|
88
|
+
FakeActiveRecordUser.create(title: options[:title])
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
it "calls the subscriber properly" do
|
94
|
+
FakeActiveRecordUser.all.size.should == 0
|
95
|
+
SubPub.publish("new_account_posted", {title: 'foo'})
|
96
|
+
FakeActiveRecordUser.all.size.should == 1
|
97
|
+
FakeActiveRecordUser.all.first.title.should == 'foo'
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "normal pubsub with a configured scope" do
|
102
|
+
before do
|
103
|
+
SubPub.scope = 'foo-bar'
|
104
|
+
|
105
|
+
class CreateAccountSubscriber < SubPub::Subscriber
|
106
|
+
subscribe_to("new_account_posted")
|
107
|
+
|
108
|
+
def on_publish
|
109
|
+
FakeActiveRecordUser.create(title: options[:title])
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
it "calls the subscriber properly" do
|
115
|
+
FakeActiveRecordUser.all.size.should == 0
|
116
|
+
SubPub.publish("new_account_posted", {title: 'foo'})
|
117
|
+
FakeActiveRecordUser.all.size.should == 1
|
118
|
+
FakeActiveRecordUser.all.first.title.should == 'foo'
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "active record configuration" do
|
123
|
+
describe "after create" do
|
124
|
+
before do
|
125
|
+
class FakeActiveRecordUserSubscriber < SubPub::ActiveRecord::Subscriber
|
126
|
+
subscribe_to(FakeActiveRecordUser, 'after_create')
|
127
|
+
|
128
|
+
def on_publish
|
129
|
+
FakeActiveRecordResult.create
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
it "successfully calls through to the subscriber" do
|
135
|
+
FakeActiveRecordResult.all.size.should == 0
|
136
|
+
FakeActiveRecordUser.create
|
137
|
+
FakeActiveRecordResult.all.size.should == 1
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe "after commit" do
|
142
|
+
before do
|
143
|
+
class FakeActiveRecordUserSubscriber < SubPub::ActiveRecord::Subscriber
|
144
|
+
subscribe_to(FakeActiveRecordUser, 'after_commit')
|
145
|
+
|
146
|
+
def on_publish
|
147
|
+
FakeActiveRecordResult.create
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
it "successfully calls through to the subscriber" do
|
153
|
+
FakeActiveRecordResult.all.size.should == 0
|
154
|
+
FakeActiveRecordUser.create
|
155
|
+
FakeActiveRecordResult.all.size.should == 1
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe "before create" do
|
160
|
+
before do
|
161
|
+
class FakeActiveRecordUserSubscriber < SubPub::ActiveRecord::Subscriber
|
162
|
+
subscribe_to(FakeActiveRecordUser, 'before_create')
|
163
|
+
|
164
|
+
def on_publish
|
165
|
+
record.fake_active_record_results.build(title: 'fooz')
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
it "successfully calls through to the subscriber" do
|
171
|
+
FakeActiveRecordResult.all.size.should == 0
|
172
|
+
FakeActiveRecordUser.create
|
173
|
+
FakeActiveRecordResult.all.size.should == 1
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -24,7 +24,7 @@ RSpec.configure do |config|
|
|
24
24
|
#
|
25
25
|
# Rails loads this during its setup
|
26
26
|
#
|
27
|
-
SubPub::
|
27
|
+
SubPub::Railtie.run_initializers
|
28
28
|
|
29
29
|
#
|
30
30
|
# Test database
|
@@ -44,7 +44,9 @@ RSpec.configure do |config|
|
|
44
44
|
#
|
45
45
|
# Ensure pubsub is enabled
|
46
46
|
#
|
47
|
-
config.before do
|
47
|
+
config.before(:each) do
|
48
48
|
SubPub.enable
|
49
|
+
SubPub.scope = 'sub_pub'
|
50
|
+
SubPub.unsubscribe_all
|
49
51
|
end
|
50
52
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sub_pub
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
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-17 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: In process publish/subscribe for Ruby
|
15
15
|
email:
|
@@ -28,12 +28,18 @@ files:
|
|
28
28
|
- db/.gitkeep
|
29
29
|
- lib/sub_pub.rb
|
30
30
|
- lib/sub_pub/active_record_extensions.rb
|
31
|
+
- lib/sub_pub/active_record_subscriber.rb
|
32
|
+
- lib/sub_pub/railtie.rb
|
31
33
|
- lib/sub_pub/register.rb
|
34
|
+
- lib/sub_pub/scoped_topic.rb
|
32
35
|
- lib/sub_pub/subscriber.rb
|
36
|
+
- lib/sub_pub/subscription.rb
|
33
37
|
- lib/sub_pub/version.rb
|
34
38
|
- pkg/sub_pub-0.0.3.gem
|
35
|
-
-
|
39
|
+
- pkg/sub_pub-0.0.4.gem
|
40
|
+
- spec/integration/sub_pub_spec.rb
|
36
41
|
- spec/spec_helper.rb
|
42
|
+
- spec/unit/register_spec.rb
|
37
43
|
- spec/unit/subscriber_spec.rb
|
38
44
|
- sub_pub.gemspec
|
39
45
|
homepage: ''
|
@@ -48,18 +54,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
48
54
|
- - ! '>='
|
49
55
|
- !ruby/object:Gem::Version
|
50
56
|
version: '0'
|
51
|
-
segments:
|
52
|
-
- 0
|
53
|
-
hash: -923795167419613194
|
54
57
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
58
|
none: false
|
56
59
|
requirements:
|
57
60
|
- - ! '>='
|
58
61
|
- !ruby/object:Gem::Version
|
59
62
|
version: '0'
|
60
|
-
segments:
|
61
|
-
- 0
|
62
|
-
hash: -923795167419613194
|
63
63
|
requirements: []
|
64
64
|
rubyforge_project:
|
65
65
|
rubygems_version: 1.8.24
|
@@ -68,6 +68,8 @@ specification_version: 3
|
|
68
68
|
summary: SubPub is a thin wrapper around ActiveSupport::Notifications, which provides
|
69
69
|
an implementation of the Publish/Subscribe pattern.
|
70
70
|
test_files:
|
71
|
-
- spec/integration/
|
71
|
+
- spec/integration/sub_pub_spec.rb
|
72
72
|
- spec/spec_helper.rb
|
73
|
+
- spec/unit/register_spec.rb
|
73
74
|
- spec/unit/subscriber_spec.rb
|
75
|
+
has_rdoc:
|
@@ -1,66 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe SubPub do
|
4
|
-
describe "initial state" do
|
5
|
-
it "defaults enabled to true" do
|
6
|
-
SubPub::Register.instance.enabled = nil
|
7
|
-
SubPub.enabled?.should be_true
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
describe "#enable" do
|
12
|
-
it "enables SubPub" do
|
13
|
-
SubPub.disable
|
14
|
-
SubPub.enable
|
15
|
-
SubPub.enabled?.should be_true
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
describe "#disable" do
|
20
|
-
it "disables SubPub" do
|
21
|
-
SubPub.disable
|
22
|
-
SubPub.enabled?.should be_false
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
describe "#publish" do
|
27
|
-
context "when disabled" do
|
28
|
-
before { SubPub.disable }
|
29
|
-
|
30
|
-
it "does not publish" do
|
31
|
-
ActiveSupport::Notifications.should_receive(:publish).never
|
32
|
-
SubPub.publish
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
describe "active record configuration" do
|
38
|
-
with_model :FakeActiveRecordUser do
|
39
|
-
table do |t|
|
40
|
-
t.string :title
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
with_model :FakeActiveRecordResult do
|
45
|
-
table do |t|
|
46
|
-
t.string :title
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
before do
|
51
|
-
class FakeActiveRecordUserSubscriber < SubPub::ActiveRecord::Subscriber
|
52
|
-
subscribe_to(FakeActiveRecordUser, 'after_create')
|
53
|
-
|
54
|
-
def on_publish
|
55
|
-
FakeActiveRecordResult.create
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
it "successfully calls through to the subscriber" do
|
61
|
-
FakeActiveRecordResult.all.size.should == 0
|
62
|
-
FakeActiveRecordUser.create
|
63
|
-
FakeActiveRecordResult.all.size.should == 1
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|