active_pubsub 0.0.6 → 0.0.7
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/README.md +18 -0
- data/lib/active_pubsub.rb +7 -2
- data/lib/active_pubsub/publish_with_serializer.rb +5 -2
- data/lib/active_pubsub/publishable.rb +1 -0
- data/lib/active_pubsub/subscribe_to_changes.rb +26 -0
- data/lib/active_pubsub/subscriber.rb +16 -3
- data/lib/active_pubsub/version.rb +1 -1
- data/spec/active_pubsub/publishable_spec.rb +1 -1
- data/spec/active_pubsub/subscribe_to_changes_spec.rb +42 -0
- data/spec/active_pubsub/subscriber_spec.rb +51 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/support/db/setup.rb +6 -2
- data/spec/support/models/author.rb +2 -0
- data/spec/support/models/author_post_report.rb +9 -0
- data/spec/support/models/post.rb +2 -0
- data/spec/support/subscribers/author_subscriber.rb +16 -0
- data/spec/support/subscribers/post_subscriber.rb +30 -0
- data/spec/test.db +0 -0
- metadata +13 -6
- data/spec/support/models.rb +0 -1
- data/spec/support/serializers.rb +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4c4e0a20248f5de90d821e8e07db538c76dd121c
|
4
|
+
data.tar.gz: c3e9ffbf7d9faef44bf37393f38b39cfd3bfd806
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 56af865a31f3bc9939f079c800191f9976a04d5039556d3e7721d74a9a59cda5e9d9560f439ec91fbaec689e0c5ae2f2ad09f5002ccf1cc529c525e009d560fb
|
7
|
+
data.tar.gz: 0604dcb58eec116f71ae5c964d87f5a455c5aae35a2d1708ab5fdeae84aa36028efc45f2557dc2910e10dddc4a5547756f5b30be0aae13e8fe049d210ad63f4b
|
data/README.md
CHANGED
@@ -39,6 +39,24 @@ class PostSubscriber < ::ActivePubsub::Subscriber
|
|
39
39
|
end
|
40
40
|
```
|
41
41
|
|
42
|
+
### Subscribe to individual attribute changes
|
43
|
+
|
44
|
+
``` ruby
|
45
|
+
class PostSubscriber < ::ActivePubsub::Subscriber
|
46
|
+
include ::ActivePubsub::SubscribeToChanges
|
47
|
+
|
48
|
+
# Note: Do NOT define updated as an event, as on_change
|
49
|
+
# uses updated event so latter event will override former
|
50
|
+
observes "cms"
|
51
|
+
as "aggregator"
|
52
|
+
|
53
|
+
on_change :title do |new_value, old_value|
|
54
|
+
puts record.inspect
|
55
|
+
puts new_value
|
56
|
+
end
|
57
|
+
end
|
58
|
+
```
|
59
|
+
|
42
60
|
## Publishing events
|
43
61
|
|
44
62
|
Just include ::ActivePubsub::Publishable module into an active record class whose events you want to publish.
|
data/lib/active_pubsub.rb
CHANGED
@@ -37,8 +37,12 @@ module ActivePubsub
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def self.start_subscribers
|
40
|
-
|
40
|
+
|
41
41
|
::ActivePubsub::Subscriber.subclasses.each do |subscriber|
|
42
|
+
next if subscriber.started?
|
43
|
+
|
44
|
+
puts "Starting #{subscriber.name}"
|
45
|
+
|
42
46
|
subscriber.bind_subscriptions!
|
43
47
|
subscriber.print_subscriptions!
|
44
48
|
end
|
@@ -55,6 +59,7 @@ require "active_pubsub/config"
|
|
55
59
|
require "active_pubsub/event"
|
56
60
|
require "active_pubsub/publisher"
|
57
61
|
require "active_pubsub/publishable"
|
58
|
-
require "active_pubsub/subscriber"
|
59
62
|
require "active_pubsub/publish_with_serializer"
|
63
|
+
require "active_pubsub/subscriber"
|
64
|
+
require "active_pubsub/subscribe_to_changes"
|
60
65
|
require 'active_pubsub/railtie' if defined?(Rails)
|
@@ -9,13 +9,16 @@ module ActivePubsub
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def serialized_resource
|
12
|
-
|
12
|
+
serialized_resource_attributes.merge!(:changes => previous_changes) if previous_changes
|
13
13
|
|
14
14
|
::Marshal.dump(serialized_resource_attributes)
|
15
15
|
end
|
16
16
|
|
17
17
|
def serialized_resource_attributes
|
18
|
-
@serialized_resource_attributes ||= self.class
|
18
|
+
@serialized_resource_attributes ||= self.class
|
19
|
+
.publish_serializer.new(self)
|
20
|
+
.attributes
|
21
|
+
.symbolize_keys!
|
19
22
|
end
|
20
23
|
|
21
24
|
module ClassMethods
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ActivePubsub
|
2
|
+
module SubscribeToChanges
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
class_attribute :attributes_to_watch_for_changes
|
7
|
+
self.attributes_to_watch_for_changes = {}
|
8
|
+
|
9
|
+
on :updated do |changed_record|
|
10
|
+
attributes_to_watch_for_changes.each_pair do |field, block|
|
11
|
+
if changed_record[:changes].with_indifferent_access.has_key?(field)
|
12
|
+
old_value = changed_record[:changes][field][0]
|
13
|
+
new_value = changed_record[:changes][field][1]
|
14
|
+
instance_exec(new_value, old_value, &block)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module ClassMethods
|
21
|
+
def on_change(attribute_name, &block)
|
22
|
+
attributes_to_watch_for_changes[attribute_name] = block
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -8,11 +8,16 @@ module ActivePubsub
|
|
8
8
|
class_attribute :exchange_name
|
9
9
|
class_attribute :connection
|
10
10
|
class_attribute :local_service_namespace
|
11
|
+
class_attribute :started
|
11
12
|
|
12
|
-
self.events = {}
|
13
13
|
self.connection = ::ActivePubsub::Connection.new
|
14
|
+
self.started = false
|
14
15
|
|
15
16
|
### Class Methods ###
|
17
|
+
def self.as(service_namespace)
|
18
|
+
self.local_service_namespace = service_namespace
|
19
|
+
end
|
20
|
+
|
16
21
|
def self.channel
|
17
22
|
connection.channel
|
18
23
|
end
|
@@ -21,8 +26,8 @@ module ActivePubsub
|
|
21
26
|
channel.topic(exchange_name, :auto_delete => true)
|
22
27
|
end
|
23
28
|
|
24
|
-
def self.
|
25
|
-
|
29
|
+
def self.inherited(klass)
|
30
|
+
klass.events = {}
|
26
31
|
end
|
27
32
|
|
28
33
|
def self.on(event_name, &block)
|
@@ -30,6 +35,8 @@ module ActivePubsub
|
|
30
35
|
end
|
31
36
|
|
32
37
|
def self.bind_subscriptions!
|
38
|
+
return if started?
|
39
|
+
|
33
40
|
events.each_pair do |event_name, block|
|
34
41
|
channel.queue(queue_for_event(event_name.to_s))
|
35
42
|
.bind(exchange, :routing_key => routing_key_for_event(event_name))
|
@@ -41,6 +48,8 @@ module ActivePubsub
|
|
41
48
|
subscriber_instance.instance_exec(deserialized_record, &block)
|
42
49
|
end
|
43
50
|
end
|
51
|
+
|
52
|
+
self.started = true
|
44
53
|
end
|
45
54
|
|
46
55
|
def self.deserialize_event(event)
|
@@ -74,6 +83,10 @@ module ActivePubsub
|
|
74
83
|
puts message
|
75
84
|
end
|
76
85
|
|
86
|
+
def self.started?
|
87
|
+
self.started
|
88
|
+
end
|
89
|
+
|
77
90
|
### Instance Methods ###
|
78
91
|
attr_accessor :record
|
79
92
|
|
@@ -24,7 +24,7 @@ describe ::ActivePubsub::Publishable do
|
|
24
24
|
let(:created_record) { ::Fake::Blog::Post.create!(:title => "Post about nothing") }
|
25
25
|
|
26
26
|
it "should merge previous changes" do
|
27
|
-
expect(created_record.attributes_hash).to have_key(
|
27
|
+
expect(created_record.attributes_hash).to have_key(:title)
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'support/subscribers/author_subscriber'
|
3
|
+
|
4
|
+
describe ::ActivePubsub::SubscribeToChanges do
|
5
|
+
before do
|
6
|
+
::ActivePubsub.start_subscribers
|
7
|
+
end
|
8
|
+
|
9
|
+
subject { ::AuthorSubscriber }
|
10
|
+
|
11
|
+
let(:fake_author) { ::Fake::Blog::Author.create!(:first_name => "Bill", :last_name => "Lumberg") }
|
12
|
+
let(:fake_post) { ::Fake::Blog::Post.create!(:title => "Fake post by #{fake_author.first_name}", :author_id => fake_author.id) }
|
13
|
+
|
14
|
+
its(:attributes_to_watch_for_changes) {
|
15
|
+
should have_key(:first_name)
|
16
|
+
}
|
17
|
+
|
18
|
+
describe "#on_change" do
|
19
|
+
context "when author last name is changed" do
|
20
|
+
it "does not update titles" do
|
21
|
+
fake_post
|
22
|
+
|
23
|
+
fake_author.last_name = "Bolton"
|
24
|
+
fake_author.save
|
25
|
+
|
26
|
+
fake_author.posts.last.title.should eq "Fake post by Bill"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context "when author first name is changed" do
|
31
|
+
# ghetto, but since its async we need to sleep to see update
|
32
|
+
it "updates all titles with new author name" do
|
33
|
+
fake_post
|
34
|
+
|
35
|
+
fake_author.first_name = "Michael"
|
36
|
+
fake_author.save
|
37
|
+
sleep(0.5)
|
38
|
+
fake_author.posts.last.title.should eq "Fake post by Michael"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActivePubsub::Subscriber do
|
4
|
+
|
5
|
+
subject { ::PostSubscriber }
|
6
|
+
|
7
|
+
its(:events) { should have_key(:created) }
|
8
|
+
its(:events) { should have_key(:destroyed) }
|
9
|
+
its(:events) { should have_key(:updated) }
|
10
|
+
its(:exchange_name) { should eq "test.post" }
|
11
|
+
its(:local_service_namespace) { should eq "test" }
|
12
|
+
its(:started) { should be true }
|
13
|
+
its(:connection) { should be_a(ActivePubsub::Connection) }
|
14
|
+
|
15
|
+
describe ".on" do
|
16
|
+
context ":created" do
|
17
|
+
let!(:fake_author) { ::Fake::Blog::Author.create!(:first_name => "Samir", :last_name => "Nyininejad") }
|
18
|
+
let!(:fake_post) { ::Fake::Blog::Post.create!(:title => "myblogpost", :author_id => fake_author.id) }
|
19
|
+
|
20
|
+
it "should increment post_count" do
|
21
|
+
sleep(0.1)
|
22
|
+
::Fake::Blog::AuthorPostReport.find_by(:author_id => fake_author.id).post_count.should eq 1
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context ":destroyed" do
|
27
|
+
let!(:fake_author) { ::Fake::Blog::Author.create!(:first_name => "Samir", :last_name => "Nyininejad") }
|
28
|
+
let!(:fake_post) { ::Fake::Blog::Post.create!(:title => "myblogpost", :author_id => fake_author.id) }
|
29
|
+
|
30
|
+
it "should destroy author post report" do
|
31
|
+
fake_post.destroy
|
32
|
+
sleep(0.1)
|
33
|
+
::Fake::Blog::AuthorPostReport.where(:author_id => fake_author.id).first.should be_nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context ":updated" do
|
38
|
+
let!(:fake_author) { ::Fake::Blog::Author.create!(:first_name => "Samir", :last_name => "Nyininejad") }
|
39
|
+
let!(:fake_post) { ::Fake::Blog::Post.create!(:title => "myblogpost", :author_id => fake_author.id) }
|
40
|
+
|
41
|
+
it "should update author last name with author_id" do
|
42
|
+
fake_post.title = "Asdfg"
|
43
|
+
fake_post.save
|
44
|
+
|
45
|
+
sleep(0.1)
|
46
|
+
|
47
|
+
fake_author.reload.last_name.should eq "author_#{fake_author.id}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/spec/spec_helper.rb
CHANGED
data/spec/support/db/setup.rb
CHANGED
@@ -14,16 +14,20 @@ ActiveRecord::Schema.define(:version => 1) do
|
|
14
14
|
t.string :body
|
15
15
|
t.string :title
|
16
16
|
t.string :slug
|
17
|
-
t.integer :
|
17
|
+
t.integer :author_id
|
18
18
|
|
19
19
|
t.timestamps
|
20
20
|
end
|
21
21
|
|
22
|
+
create_table :author_post_reports do |t|
|
23
|
+
t.integer :author_id
|
24
|
+
t.integer :post_count
|
25
|
+
end
|
26
|
+
|
22
27
|
create_table :authors do |t|
|
23
28
|
t.string :first_name
|
24
29
|
t.string :last_name
|
25
30
|
t.string :slug
|
26
|
-
t.integer :user_id
|
27
31
|
|
28
32
|
t.timestamps
|
29
33
|
end
|
data/spec/support/models/post.rb
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
class AuthorSubscriber < ::ActivePubsub::Subscriber
|
2
|
+
include ::ActivePubsub::SubscribeToChanges
|
3
|
+
|
4
|
+
observes "test.author"
|
5
|
+
as "test"
|
6
|
+
|
7
|
+
on_change :first_name do |new_value, old_value|
|
8
|
+
author.posts.update_all(:title => "Fake post by #{new_value}")
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def author
|
14
|
+
@author ||= ::Fake::Blog::Author.find(record[:id])
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class PostSubscriber < ::ActivePubsub::Subscriber
|
2
|
+
|
3
|
+
observes "test.post"
|
4
|
+
as "test"
|
5
|
+
|
6
|
+
# Pointless as examples, but being used for integration testing
|
7
|
+
|
8
|
+
on :created do
|
9
|
+
author_post_report.increment!(:post_count) if record.has_key?(:author_id)
|
10
|
+
end
|
11
|
+
|
12
|
+
on :updated do
|
13
|
+
author.last_name = "author_#{record[:author_id]}"
|
14
|
+
author.save
|
15
|
+
end
|
16
|
+
|
17
|
+
on :destroyed do
|
18
|
+
author_post_report.destroy
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def author
|
24
|
+
@author ||= ::Fake::Blog::Author.find(record[:author_id])
|
25
|
+
end
|
26
|
+
|
27
|
+
def author_post_report
|
28
|
+
@author_post_report ||= ::Fake::Blog::AuthorPostReport.where(:author_id => record[:author_id]).first_or_create
|
29
|
+
end
|
30
|
+
end
|
data/spec/test.db
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_pubsub
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jason Ayre
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-10-
|
11
|
+
date: 2014-10-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: active_attr
|
@@ -318,6 +318,7 @@ files:
|
|
318
318
|
- lib/active_pubsub/publishable.rb
|
319
319
|
- lib/active_pubsub/publisher.rb
|
320
320
|
- lib/active_pubsub/railtie.rb
|
321
|
+
- lib/active_pubsub/subscribe_to_changes.rb
|
321
322
|
- lib/active_pubsub/subscriber.rb
|
322
323
|
- lib/active_pubsub/version.rb
|
323
324
|
- spec/active_pubsub/config_spec.rb
|
@@ -325,13 +326,16 @@ files:
|
|
325
326
|
- spec/active_pubsub/publish_with_serializer_spec.rb
|
326
327
|
- spec/active_pubsub/publishable_spec.rb
|
327
328
|
- spec/active_pubsub/publisher_spec.rb
|
329
|
+
- spec/active_pubsub/subscribe_to_changes_spec.rb
|
330
|
+
- spec/active_pubsub/subscriber_spec.rb
|
328
331
|
- spec/spec_helper.rb
|
329
332
|
- spec/support/db/setup.rb
|
330
|
-
- spec/support/models.rb
|
331
333
|
- spec/support/models/author.rb
|
334
|
+
- spec/support/models/author_post_report.rb
|
332
335
|
- spec/support/models/post.rb
|
333
|
-
- spec/support/serializers.rb
|
334
336
|
- spec/support/serializers/author_serializer.rb
|
337
|
+
- spec/support/subscribers/author_subscriber.rb
|
338
|
+
- spec/support/subscribers/post_subscriber.rb
|
335
339
|
- spec/test.db
|
336
340
|
homepage: https://github.com/jasonayre/active_pubsub
|
337
341
|
licenses:
|
@@ -364,11 +368,14 @@ test_files:
|
|
364
368
|
- spec/active_pubsub/publish_with_serializer_spec.rb
|
365
369
|
- spec/active_pubsub/publishable_spec.rb
|
366
370
|
- spec/active_pubsub/publisher_spec.rb
|
371
|
+
- spec/active_pubsub/subscribe_to_changes_spec.rb
|
372
|
+
- spec/active_pubsub/subscriber_spec.rb
|
367
373
|
- spec/spec_helper.rb
|
368
374
|
- spec/support/db/setup.rb
|
369
|
-
- spec/support/models.rb
|
370
375
|
- spec/support/models/author.rb
|
376
|
+
- spec/support/models/author_post_report.rb
|
371
377
|
- spec/support/models/post.rb
|
372
|
-
- spec/support/serializers.rb
|
373
378
|
- spec/support/serializers/author_serializer.rb
|
379
|
+
- spec/support/subscribers/author_subscriber.rb
|
380
|
+
- spec/support/subscribers/post_subscriber.rb
|
374
381
|
- spec/test.db
|
data/spec/support/models.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'support/models/post'
|
data/spec/support/serializers.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require 'support/serializers/author_serializer'
|