untied-publisher 0.0.3 → 0.0.4
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/lib/untied-publisher/doorkeeper.rb +32 -14
- data/lib/untied-publisher/event.rb +11 -5
- data/lib/untied-publisher/observer.rb +9 -4
- data/lib/untied-publisher/version.rb +1 -1
- data/spec/doorkeeper_spec.rb +46 -1
- data/spec/event_spec.rb +3 -2
- data/spec/producer_spec.rb +2 -1
- data/spec/publisher_observer_spec.rb +17 -17
- data/spec/spec_helper.rb +7 -0
- data/untied-publisher.gemspec +1 -0
- metadata +19 -5
@@ -12,7 +12,7 @@ module Untied
|
|
12
12
|
# The following publisher watches the User after_create event:
|
13
13
|
#
|
14
14
|
# class MyDoorkeeper
|
15
|
-
# include Untied::Doorkeeper
|
15
|
+
# include Untied::Publisher::Doorkeeper
|
16
16
|
#
|
17
17
|
# def initialize
|
18
18
|
# watch User, :after_create
|
@@ -27,14 +27,15 @@ module Untied
|
|
27
27
|
# Watches ActiveRecord lifecycle callbacks for some Class
|
28
28
|
#
|
29
29
|
# class Doorkeeper
|
30
|
-
# include Untied::Doorkeeper
|
30
|
+
# include Untied::Publisher::Doorkeeper
|
31
31
|
# end
|
32
32
|
#
|
33
33
|
# pub.new.watch(User, :after_create)
|
34
34
|
# User.create # sends the user into the wire
|
35
35
|
def watch(*args)
|
36
36
|
entity = args.shift
|
37
|
-
|
37
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
38
|
+
observed << [entity, args, options]
|
38
39
|
end
|
39
40
|
|
40
41
|
# Returns the list of classes watched
|
@@ -46,7 +47,7 @@ module Untied
|
|
46
47
|
# For example, if the publisher is defined as follows:
|
47
48
|
#
|
48
49
|
# class MyDoorkeeper
|
49
|
-
# include Untided::Doorkeeper
|
50
|
+
# include Untided::Publisher::Doorkeeper
|
50
51
|
#
|
51
52
|
# def initialize
|
52
53
|
# watch User, :after_create
|
@@ -57,20 +58,37 @@ module Untied
|
|
57
58
|
# _notify_untied__publisher_observer_for_after_create is created on User's
|
58
59
|
# model. This method is called when the after_create callback is fired.
|
59
60
|
def define_callbacks
|
61
|
+
observed.each do |(klass, callbacks, options)|
|
62
|
+
ActiveRecord::Callbacks::CALLBACKS.each do |callback|
|
63
|
+
next unless callbacks.include?(callback)
|
64
|
+
setup_observer(klass, callback, options)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
protected
|
70
|
+
|
71
|
+
def setup_observer(klass, callback, options={})
|
60
72
|
observer = Untied::Publisher::Observer
|
61
73
|
observer_name = observer.name.underscore.gsub('/', '__')
|
74
|
+
notifier_meth = :"_notify_#{observer_name}_for_#{callback}"
|
62
75
|
|
63
|
-
|
64
|
-
|
65
|
-
next unless callbacks.include?(callback)
|
66
|
-
callback_meth = :"_notify_#{observer_name}_for_#{callback}"
|
67
|
-
unless klass.respond_to?(callback_meth)
|
68
|
-
klass.send(:define_method, callback_meth) do
|
69
|
-
observer.instance.send(callback, self)
|
70
|
-
end
|
71
|
-
klass.send(callback, callback_meth)
|
72
|
-
end
|
76
|
+
if define_notifier_method(klass, observer, callback, notifier_meth, options)
|
77
|
+
klass.send(callback, notifier_meth)
|
73
78
|
end
|
79
|
+
|
80
|
+
klass
|
81
|
+
end
|
82
|
+
|
83
|
+
def define_method_on(klass, method_name, &block)
|
84
|
+
unless klass.respond_to?(method_name)
|
85
|
+
klass.send(:define_method, method_name, &block)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def define_notifier_method(klass, observer, callback, method_name, options={})
|
90
|
+
define_method_on(klass, method_name) do
|
91
|
+
observer.instance.send(callback, self, options)
|
74
92
|
end
|
75
93
|
end
|
76
94
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
|
-
|
2
|
+
|
3
|
+
require 'representable/json'
|
3
4
|
|
4
5
|
module Untied
|
5
6
|
class Event
|
6
|
-
include ActiveModel::Serializers::JSON
|
7
7
|
attr_accessor :name, :payload, :origin
|
8
8
|
|
9
9
|
def initialize(attrs)
|
@@ -19,9 +19,15 @@ module Untied
|
|
19
19
|
@payload = @config.delete(:payload)
|
20
20
|
@origin = @config.delete(:origin)
|
21
21
|
end
|
22
|
+
end
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
module EventRepresenter
|
25
|
+
include Representable::JSON
|
26
|
+
|
27
|
+
self.representation_wrap = true
|
28
|
+
|
29
|
+
property :name
|
30
|
+
property :payload
|
31
|
+
property :origin
|
26
32
|
end
|
27
33
|
end
|
@@ -18,7 +18,8 @@ module Untied
|
|
18
18
|
|
19
19
|
def method_missing(name, model, *args, &block)
|
20
20
|
if ActiveRecord::Callbacks::CALLBACKS.include?(name)
|
21
|
-
|
21
|
+
options = args.first.is_a?(Hash) ? args.first : {}
|
22
|
+
produce_event(name, model, options)
|
22
23
|
else
|
23
24
|
super
|
24
25
|
end
|
@@ -26,9 +27,13 @@ module Untied
|
|
26
27
|
|
27
28
|
protected
|
28
29
|
|
29
|
-
def produce_event(callback, model)
|
30
|
-
|
31
|
-
|
30
|
+
def produce_event(callback, model, options={})
|
31
|
+
if representer = options[:with_representer]
|
32
|
+
model = model.extend(representer)
|
33
|
+
end
|
34
|
+
e = Event.new(:name => callback,
|
35
|
+
:payload => model, :origin => Publisher.config.service_name)
|
36
|
+
e.extend(EventRepresenter)
|
32
37
|
producer.publish(e)
|
33
38
|
end
|
34
39
|
|
data/spec/doorkeeper_spec.rb
CHANGED
@@ -8,13 +8,21 @@ module Untied
|
|
8
8
|
class ::Doorkeeper
|
9
9
|
include Untied::Publisher::Doorkeeper
|
10
10
|
end
|
11
|
+
|
12
|
+
module SomeRepresenter; end
|
11
13
|
end
|
12
14
|
let(:doorkeeper) { ::Doorkeeper.new }
|
13
15
|
|
14
16
|
context "#watch" do
|
15
17
|
it "should add observed classes to observed list" do
|
16
18
|
doorkeeper.watch(User, :after_create)
|
17
|
-
doorkeeper.observed.should == [[User, [:after_create]]]
|
19
|
+
doorkeeper.observed.should == [[User, [:after_create], {}]]
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should accept a constant" do
|
23
|
+
opts = { :represent_with => SomeRepresenter }
|
24
|
+
doorkeeper.watch(User, :after_create, opts)
|
25
|
+
doorkeeper.observed.should == [[User, [:after_create], opts]]
|
18
26
|
end
|
19
27
|
end
|
20
28
|
|
@@ -48,6 +56,43 @@ module Untied
|
|
48
56
|
Post.new.should \
|
49
57
|
respond_to(:_notify_untied__publisher__observer_for_after_create)
|
50
58
|
end
|
59
|
+
|
60
|
+
context "with :represent_with option" do
|
61
|
+
let(:observer) do
|
62
|
+
observer = double('Untied::Publisher::Observer')
|
63
|
+
observer.stub(:name).and_return("Untied::Publisher::Observer")
|
64
|
+
observer.stub(:after_create)
|
65
|
+
observer
|
66
|
+
end
|
67
|
+
before do
|
68
|
+
Observer.stub(:instance).and_return(observer)
|
69
|
+
doorkeeper.watch(Post, :after_create, :represent_with => SomeRepresenter)
|
70
|
+
doorkeeper.define_callbacks
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should extend the entity with the constant" do
|
74
|
+
observer.should_receive(:after_create).
|
75
|
+
with(an_instance_of(Post), { :represent_with => SomeRepresenter })
|
76
|
+
Post.create
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
context "Observed#_notify_untied__publisher__observer_for_[callback]" do
|
82
|
+
let(:observer) do
|
83
|
+
observer = double('Untied::Publisher::Observer')
|
84
|
+
observer.stub(:name).and_return("Untied::Publisher::Observer")
|
85
|
+
end
|
86
|
+
before do
|
87
|
+
doorkeeper.watch(User, :after_create)
|
88
|
+
Observer.stub(:instance).and_return(observer)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should invoke observer method" do
|
92
|
+
observer.should_receive(:after_create)
|
93
|
+
doorkeeper.define_callbacks
|
94
|
+
User.new.send(:_notify_untied__publisher__observer_for_after_create)
|
95
|
+
end
|
51
96
|
end
|
52
97
|
|
53
98
|
context "#observed_classes" do
|
data/spec/event_spec.rb
CHANGED
@@ -28,8 +28,9 @@ module Untied
|
|
28
28
|
end
|
29
29
|
|
30
30
|
it "should include the origin service name" do
|
31
|
-
|
32
|
-
|
31
|
+
e = Event.new(:name => :after_create,
|
32
|
+
:payload => person, :origin => "core")
|
33
|
+
e.origin.should == "core"
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
data/spec/producer_spec.rb
CHANGED
@@ -33,7 +33,8 @@ module Untied
|
|
33
33
|
context "#publish" do
|
34
34
|
it "should call Channel#publish" do
|
35
35
|
mock_reactor_and_amqp do |channel|
|
36
|
-
e = Event.new(:name => "create",
|
36
|
+
e = Event.new(:name => "create",
|
37
|
+
:payload => { :foo => 'bar' }, :origin => :core)
|
37
38
|
channel.topic.should_receive(:publish)
|
38
39
|
producer = Producer.new(:channel => channel, :deliver_messages => true)
|
39
40
|
producer.publish(e)
|
@@ -3,18 +3,16 @@ require 'spec_helper'
|
|
3
3
|
|
4
4
|
module Untied
|
5
5
|
module Publisher
|
6
|
-
describe
|
6
|
+
describe Observer do
|
7
7
|
before do
|
8
|
-
class
|
8
|
+
class ::FooDoorkeeper
|
9
9
|
include Untied::Publisher::Doorkeeper
|
10
|
-
def initialize
|
11
|
-
watch(User, :after_create)
|
12
|
-
watch(User, :after_update)
|
13
|
-
end
|
14
10
|
end
|
15
|
-
Untied::Publisher.config.doorkeeper =
|
11
|
+
Untied::Publisher.config.doorkeeper = ::FooDoorkeeper
|
12
|
+
module UserRepresenter
|
13
|
+
end
|
16
14
|
end
|
17
|
-
|
15
|
+
let(:doorkeeper) { ::FooDoorkeeper.new }
|
18
16
|
|
19
17
|
context ".instance" do
|
20
18
|
it "should raise a friendly error when no doorkeeper is defined" do
|
@@ -27,17 +25,19 @@ module Untied
|
|
27
25
|
end
|
28
26
|
|
29
27
|
context "ActiveRecord::Callbacks" do
|
30
|
-
|
31
|
-
Observer.instance.should_receive(:after_create)
|
32
|
-
User.create
|
33
|
-
end
|
28
|
+
let(:user) { User.create(:name => "Guila") }
|
34
29
|
|
35
|
-
it "should
|
36
|
-
Observer.instance.should_receive(:
|
37
|
-
Observer.instance.
|
30
|
+
it "should proxy #produce_event" do
|
31
|
+
Observer.instance.should_receive(:produce_event)
|
32
|
+
Observer.instance.send(:after_create, user)
|
33
|
+
end
|
38
34
|
|
39
|
-
|
40
|
-
user.
|
35
|
+
context "passing :with_representer" do
|
36
|
+
it "should call user.extend(UserRepresenter)" do
|
37
|
+
user.should_receive(:extend).with(UserRepresenter)
|
38
|
+
Observer.instance.
|
39
|
+
send(:after_create, user, :with_representer => UserRepresenter)
|
40
|
+
end
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
data/spec/spec_helper.rb
CHANGED
@@ -19,6 +19,13 @@ RSpec.configure do |config|
|
|
19
19
|
config.treat_symbols_as_metadata_keys_with_true_values = true
|
20
20
|
config.run_all_when_everything_filtered = true
|
21
21
|
config.filter_run :focus
|
22
|
+
config.before do
|
23
|
+
# Redefining models for each it
|
24
|
+
%w(User Post).each do |klass|
|
25
|
+
Object.send(:remove_const, :"#{klass}")
|
26
|
+
Object.const_set(klass, Class.new(ActiveRecord::Base))
|
27
|
+
end
|
28
|
+
end
|
22
29
|
|
23
30
|
# Run specs in random order to surface order dependencies. If you find an
|
24
31
|
# order dependency and want to debug it, you can fix the order by providing
|
data/untied-publisher.gemspec
CHANGED
@@ -25,6 +25,7 @@ Gem::Specification.new do |gem|
|
|
25
25
|
gem.add_runtime_dependency "amqp"
|
26
26
|
gem.add_runtime_dependency "configurable"
|
27
27
|
gem.add_runtime_dependency "json"
|
28
|
+
gem.add_runtime_dependency "representable"
|
28
29
|
|
29
30
|
if RUBY_VERSION < "1.9"
|
30
31
|
gem.add_development_dependency "ruby-debug"
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: untied-publisher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 4
|
10
|
+
version: 0.0.4
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Guilherme Cavalcanti
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-
|
18
|
+
date: 2012-11-06 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
version_requirements: &id001 !ruby/object:Gem::Requirement
|
@@ -126,9 +126,23 @@ dependencies:
|
|
126
126
|
- 0
|
127
127
|
version: "0"
|
128
128
|
prerelease: false
|
129
|
+
type: :runtime
|
130
|
+
name: representable
|
131
|
+
requirement: *id008
|
132
|
+
- !ruby/object:Gem::Dependency
|
133
|
+
version_requirements: &id009 !ruby/object:Gem::Requirement
|
134
|
+
none: false
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
hash: 3
|
139
|
+
segments:
|
140
|
+
- 0
|
141
|
+
version: "0"
|
142
|
+
prerelease: false
|
129
143
|
type: :development
|
130
144
|
name: ruby-debug
|
131
|
-
requirement: *
|
145
|
+
requirement: *id009
|
132
146
|
description: Provides the Publisher part of the Untied gem.
|
133
147
|
email:
|
134
148
|
- guiocavalcanti@gmail.com
|