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.
@@ -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