untied-publisher 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- observed << [entity, args]
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
- observed.each do |(klass, callbacks)|
64
- ActiveRecord::Callbacks::CALLBACKS.each do |callback|
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
- require 'active_model'
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
- def attributes
24
- { "name" => @name, "origin" => @origin, "payload" => @payload }
25
- end
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
- produce_event(name, model)
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
- e = Event.new(:name => callback, :payload => model,
31
- :origin => Publisher.config.service_name)
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
 
@@ -1,5 +1,5 @@
1
1
  module Untied
2
2
  module Publisher
3
- VERSION = "0.0.3"
3
+ VERSION = "0.0.4"
4
4
  end
5
5
  end
@@ -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
- Event.new(:name => :after_create, :payload => person, :origin => "core").
32
- origin.should == "core"
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
 
@@ -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", :payload => { :foo => 'bar' }, :origin => :core)
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 Publisher do
6
+ describe Observer do
7
7
  before do
8
- class MyDoorkeeper
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 = MyDoorkeeper
11
+ Untied::Publisher.config.doorkeeper = ::FooDoorkeeper
12
+ module UserRepresenter
13
+ end
16
14
  end
17
- after { Untied::Publisher.config.doorkeeper = MyDoorkeeper }
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
- it "should call the observer when the callback is fired" do
31
- Observer.instance.should_receive(:after_create)
32
- User.create
33
- end
28
+ let(:user) { User.create(:name => "Guila") }
34
29
 
35
- it "should accept multiple callbacks even in different #watch" do
36
- Observer.instance.should_receive(:after_create)
37
- Observer.instance.should_receive(:after_update)
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
- user = User.create(:name => "yo")
40
- user.update_attributes({:name => "Ops!"})
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
@@ -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: 25
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 3
10
- version: 0.0.3
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-10-23 00:00:00 Z
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: *id008
145
+ requirement: *id009
132
146
  description: Provides the Publisher part of the Untied gem.
133
147
  email:
134
148
  - guiocavalcanti@gmail.com