event_aggregator 0.0.2 → 1.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,10 +1,8 @@
1
1
  # EventAggregator
2
2
 
3
- #### Note: This is a very early release and subject to many changes. It is currently not tested propperly, and there are several issues ranging from potential dead-locks to upcoming refactoring.
3
+ The gem 'event_aggregator' is designed for usie with the event aggregator pattern in Ruby.
4
4
 
5
- The 'event_aggregator' gem is a gem for using the event aggregator pattern in Ruby.
6
-
7
- An event aggregator is essentially a message passing service that aims at decoupeling object communication and that lets
5
+ An event aggregator is essentially a message passing service that aims at decoupeling objects in your code. This is achieved with messages that has a type and some data. A message might be produced when an event, or other condition, occurs within one object or class that might be of interest to thers. This object or class then put all relevant data into the message and publishes it. This message will then be distributed to all other objects that want to recieve this message type. This way the object or class that first got knowledge of the condition do not need to be aware of every other object that might be interested in knowing about this. It also removes the need for this class to implement any listeners and so forth. This way the listener, the receiver of the message, does not need to know that the sender even exists. This will help your code be a lot cleaner and remove a lot of bug-producing couplings between objects.
8
6
 
9
7
  ## Installation
10
8
 
@@ -30,9 +28,9 @@ Or install it yourself as:
30
28
  class Foo
31
29
  include EventAggregator::Listener
32
30
  def initialize()
33
- message_type_to_receive_add( "foo", lambda{|data| puts "bar" } )
31
+ message_type_register( "foo", lambda{|data| puts "bar" } )
34
32
 
35
- message_type_to_receive_add( "foo2", method(:handle_message) )
33
+ message_type_register( "foo2", method(:handle_message) )
36
34
  end
37
35
 
38
36
  def handle_message(data)
@@ -48,6 +46,47 @@ Or install it yourself as:
48
46
  #=> data
49
47
  EventAggregator::Message.new("foo3", "data").publish
50
48
  #=>
49
+ f.message_type_unregister("foo2")
50
+ EventAggregator::Message.new("foo2", "data").publish
51
+ #=>
52
+
53
+ EventAggregator::Message.new("foo2", "data").publish
54
+ EventAggregator::Message.new("foo2", "data2").publish
55
+ #=> data2
56
+ #=> data
57
+
58
+ Message.publish is async by default. To make it synchroneus (not recommended) use the following:
59
+
60
+ EventAggregator::Message.new("foo2", "data", false).publish
61
+ #=> data
62
+
63
+ The message data is duplicated by default for each of the receiving listeners. To force the same object for all listeners, set the consisten_data property.
64
+
65
+ EventAggregator::Message.new("foo2", "data", true, true).publish
66
+
67
+ This enables you to do the following:
68
+
69
+ class Foo
70
+ include EventAggregator::Listener
71
+ def initialize()
72
+ message_type_register( "foo", lambda{|data| data = data + " bar" } )
73
+ end
74
+ end
75
+
76
+ f1 = Foo.new
77
+ f2 = Foo.new
78
+ data = "foo"
79
+
80
+ EventAggregator::Message.new("foo", data).publish
81
+
82
+ puts data
83
+ #=> "foo bar bar"
84
+
85
+
86
+ ## Usage Considerations
87
+ All messages are processed async by default. This means that there might be raise conditions in your code.
88
+
89
+ If you force synchroneus message publishing you should take extra care of where in your code you produce new messages. You can very easily create infinite loops where messages are published and consumed by the same listener. Because of this it is adivised not to produce messages within the callback for the listener, even when using async message publishing. Another good rule is never to produce messages of the same type as those you listen to. This does not completely guard you, as there can still exist loops between two or more listeners.
51
90
 
52
91
  ## Contributing
53
92
 
@@ -58,7 +97,16 @@ Or install it yourself as:
58
97
  5. Create new Pull Request
59
98
 
60
99
  ## Todo:
61
-
62
- - Adding tests
63
- - Enable threaded message passing for higher performance.
64
100
  - Improving the readme and documentation in the gem.
101
+
102
+ ## Versioning Standard:
103
+ Using Semantic Versioning - http://semver.org/
104
+ ### Versioning Summary
105
+ Given a version number MAJOR.MINOR.PATCH, increment the:
106
+
107
+ ### 0.0.X - Patch
108
+ Small updates and patches that are backwards-compatible. Updating from 0.0.X -> 0.0.Y should not break your code.
109
+ ### 0.X - Minor
110
+ Adding functionality and changes that are backwards-compatible. Updating from 0.X -> 0.Y should not break your code.
111
+ ### X - Major
112
+ Architectural changes and other major changes that alter the API. Updating from X -> Y will most likely break your code.
@@ -23,4 +23,6 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency 'guard-rspec'
24
24
  spec.add_development_dependency 'factory_girl'
25
25
  spec.add_development_dependency 'faker'
26
+
27
+ spec.add_runtime_dependency 'sucker_punch', "~> 1.0"
26
28
  end
@@ -2,6 +2,7 @@ require "event_aggregator/version"
2
2
  require "event_aggregator/aggregator"
3
3
  require "event_aggregator/listener"
4
4
  require "event_aggregator/message"
5
+ require "event_aggregator/message_job"
5
6
 
6
7
  module EventAggregator
7
8
 
@@ -1,5 +1,3 @@
1
- #require 'singleton'
2
-
3
1
  module EventAggregator
4
2
 
5
3
  # Public: TODO: Could potentially turn this into a module.
@@ -12,29 +10,59 @@ module EventAggregator
12
10
  # end
13
11
  # end
14
12
  class Aggregator
15
- #include Singleton
16
13
  class <<self; private :new; end
17
- #TODO: Figure out how to do singleton pattern properly
18
14
 
19
15
  @@listeners = Hash.new{|h, k| h[k] = []}
20
16
 
21
- def self.register( listener, message_type )
22
- @@listeners[message_type] << listener unless ! (listener.class < EventAggregator::Listener) || @@listeners[message_type].include?(listener)
17
+ # Public: Register an EventAggregator::Listener to recieve
18
+ # a specified message type
19
+ #
20
+ # listener - An EventAggregator::Listener which should recieve
21
+ # the messages.
22
+ # message_type - The message type to recieve. Can be anything except nil.
23
+ # Often it is preferable to use a string eg. "Message Type".
24
+ def self.register( listener, message_type, callback )
25
+ @@listeners[message_type] << [listener, callback] unless ! (listener.class < EventAggregator::Listener) || @@listeners[message_type].include?(listener)
23
26
  end
24
27
 
28
+ # Public: Unegister an EventAggregator::Listener to a
29
+ # specified message type. The listener will no
30
+ # longer get messages of this type.
31
+ #
32
+ # listener - The EventAggregator::Listener which should no longer recieve
33
+ # the messages.
34
+ # message_type - The message type to unregister for.
25
35
  def self.unregister( listener, message_type )
26
- @@listeners[message_type].delete listener
36
+ @@listeners[message_type].delete_if{|value| value[0] == listener}
27
37
  end
38
+
39
+ # Public: As Unregister, but will unregister listener from all message types.
40
+ #
41
+ # listener - The listener who should no longer get any messages at all,
42
+ # regardless of type.
28
43
  def self.unregister_all( listener )
29
44
  @@listeners.each do |e|
30
- e[1].delete(listener)
45
+ e[1].delete_if{|value| value[0] == listener}
31
46
  end
32
47
  end
33
- def self.message_publish ( message )
34
- raise "Invalid message" unless message.is_a? EventAggregator::Message
35
48
 
49
+ # Public: Will publish the specified message to all listeners
50
+ # who has registered for this message type.
51
+ #
52
+ # message - The message to be distributed to the listeners.
53
+ # async - true => message will be sent async. Default true
54
+ # consisten_data - true => the same object will be sent to all recievers. Default false
55
+ def self.message_publish ( message, async = true, consisten_data = false )
56
+ raise "Invalid message" unless message.respond_to?(:message_type) && message.respond_to?(:data)
36
57
  @@listeners[message.message_type].each do |l|
37
- l.receive_message message
58
+ if l[1].respond_to? :call
59
+ case [async, consisten_data]
60
+ when [true, true] then EventAggregator::MessageJob.new.async.perform(message.data, l[1])
61
+ when [true, false] then EventAggregator::MessageJob.new.async.perform(message.data.clone, l[1])
62
+ when [false, true] then EventAggregator::MessageJob.new.perform( message.data, l[1])
63
+ when [false, false] then EventAggregator::MessageJob.new.perform( message.data.clone, l[1])
64
+ end
65
+ end
38
66
  end
39
67
  end
40
68
  end
@@ -9,69 +9,13 @@ module EventAggregator
9
9
  # ...
10
10
  # def initialize()
11
11
  # ...
12
- # message_type_to_receive_add( "foo", lambda{ puts "bar" } )
12
+ # message_type_register( "foo", lambda{ puts "bar" } )
13
13
  # end
14
14
  # ...
15
15
  # end
16
16
  #
17
17
  module Listener
18
-
19
- #event_listener_listens_to = Hash.new() #This actually sets Listener.event_listener_listens_to = Hash.new, not the instance
20
-
21
-
22
- # Public: This is the callback method when the module is extended.
23
- # Using this to setup the last few things before the event listener can start.
24
- #
25
- # base - The class object for the class extening the Listener module
26
- #
27
- # Returns nil
28
- def self.extended(base)
29
- # Initialize module.
30
- # add_auto_register_procedure(base) #Depricated now, but it is utterly awesome that you can do this.
31
- end
32
-
33
- # Public: This is the callback method when the module is included.
34
- # Using this to setup the last few things before the event listener can start.
35
- #
36
- # base - The class object for the class including the Listener module
37
- #
38
- # Returns nil
39
- def self.included(base)
40
- # Initialize module.
41
- # add_auto_register_procedure(base) #Depricated now, but it is utterly awesome that you can do this.
42
- end
43
-
44
-
45
- # Public: DEPRICATED: Adding extra initialize to the class so that we make sure new objects are added to the EventAggregators registry.
46
- # This whole hack-deal is possibly not nescessary. Can be omited with a simple "register" when you add a new "receive message_type"
47
- #
48
- # base - The class object for the class including the Listener module
49
- #
50
- # Returns nil
51
- def self.add_auto_register_procedure(base)
52
- base.class_eval do
53
- # back up method's name
54
- alias_method :old_initialize, :initialize
55
-
56
- # replace the old method with a new version which adds the Aggregator registry
57
- def initialize(*args)
58
- Aggregator.register self
59
- old_initialize(*args)
60
- end
61
- end
62
- end
63
-
64
- def receive_message( message )
65
- m = event_listener_listens_to[message.message_type]
66
-
67
- m.call(message.data) if m.respond_to? :call #Should not need the check here, however who knows what kind of conurrency issues we might have.
68
- #This will probably become hotpath, so having the extra check can be problematic.
69
- end
70
-
71
18
  private
72
- def event_listener_listens_to
73
- @event_listener_listens_to ||= Hash.new
74
- end
75
19
  # public: Use to add message types you want to receive. Overwirte existing callback when existing message type is given.
76
20
  #
77
21
  # message_type - A string indicating the message type you want to receive from the event aggregrator. Can actually be anything.
@@ -79,13 +23,12 @@ module EventAggregator
79
23
  #
80
24
  # Examples
81
25
  #
82
- # message_type_to_receive_add("foo", method(:my_class_method))
83
- # message_type_to_receive_add("foo", lambda { puts "foo" })
84
- # message_type_to_receive_add("foo", Proc.new { puts "foo" })
26
+ # message_type_register("foo", method(:my_class_method))
27
+ # message_type_register("foo", lambda { puts "foo" })
28
+ # message_type_register("foo", Proc.new { puts "foo" })
85
29
  #
86
- def message_type_to_receive_add( message_type, callback )
87
- event_listener_listens_to[message_type] = callback #unless event_listener_listens_to[message_type] #It makes more sence to overwrite in the case it already exists.
88
- Aggregator.register( self, message_type )
30
+ def message_type_register( message_type, callback )
31
+ Aggregator.register( self, message_type, callback)
89
32
  end
90
33
 
91
34
  # Public: Used to remove a certain type of message from your listening types. Messages of this specific type will no longer
@@ -95,10 +38,9 @@ module EventAggregator
95
38
  #
96
39
  # Examples
97
40
  #
98
- # message_type_to_receive_remove("foo")
41
+ # message_type_unregister("foo")
99
42
  #
100
- def message_type_to_receive_remove( message_type )
101
- event_listener_listens_to[message_type] = nil
43
+ def message_type_unregister( message_type )
102
44
  Aggregator.unregister(self, message_type)
103
45
  end
104
46
  end
@@ -3,15 +3,31 @@ module EventAggregator
3
3
  attr_accessor :message_type, :data
4
4
  @message_type = nil
5
5
  @data = nil
6
- def initialize(message_type, data)
7
- raise "Illegal Message Type" if !message_type
6
+ @async = nil
7
+ @consisten_data = nil
8
+
9
+
10
+ # Public: Initialize the Message
11
+ #
12
+ # message_type - The type of the message which determine
13
+ # which listeners will recieve the message
14
+ # data -
15
+ # async = true - Indicates if message should be published async or not
16
+ # consisten_data = false - Indicates if message listeners should recieve
17
+ # the same object reference
18
+ def initialize(message_type, data, async = true, consisten_data = false)
19
+ raise "Illegal Message Type" if message_type == nil
8
20
 
9
21
  @message_type = message_type
10
22
  @data = data
23
+ @async = async
24
+ @consisten_data = consisten_data
11
25
  end
12
-
26
+
27
+ # Public: Will publish the message to all that
28
+ # listens of this message_type
13
29
  def publish
14
- Aggregator.message_publish( self )
30
+ Aggregator.message_publish( self, async, consisten_data )
15
31
  end
16
32
  end
17
33
  end
@@ -0,0 +1,9 @@
1
+ module EventAggregator
2
+ class MessageJob
3
+ include SuckerPunch::Job
4
+
5
+ def perform(data, callback)
6
+ callback.call(data)
7
+ end
8
+ end
9
+ end
@@ -1,3 +1,3 @@
1
1
  module EventAggregator
2
- VERSION = "0.0.2"
2
+ VERSION = "1.0.0.pre"
3
3
  end
data/spec/factories.rb CHANGED
@@ -2,7 +2,7 @@ require 'factory_girl'
2
2
  require 'faker'
3
3
  require 'event_aggregator'
4
4
 
5
-
5
+
6
6
  # Public: Not really used. Might not be needed at all. The same
7
7
  # goes for FactoryGirl in general. Might not be needed.
8
8
  #
@@ -16,7 +16,7 @@ FactoryGirl.define do
16
16
  end
17
17
  factory :message do
18
18
  message_type { Faker::Name.name }
19
- data { Faker::Commerce.product_name } #TODO: This bracket should be unnescecary
19
+ data { Faker::Commerce.product_name }
20
20
  #initialize_with(Faker::Name.name, Faker::Name.name)
21
21
  end
22
22
  end
@@ -4,7 +4,8 @@ describe EventAggregator::Aggregator do
4
4
  let(:listener) { (Class.new { include EventAggregator::Listener }).new }
5
5
  let(:listener_class) { Class.new { include EventAggregator::Listener }}
6
6
  let(:message_type) { Faker::Name.name }
7
- let(:data) { Faker::Name.name }
7
+ let(:data) { Faker::Name.name }
8
+ let(:callback) { lambda{ |data| } }
8
9
 
9
10
  before(:each) do
10
11
  EventAggregator::Aggregator.class_variable_set :@@listener, Hash.new{|h, k| h[k] = []}
@@ -12,58 +13,58 @@ describe EventAggregator::Aggregator do
12
13
  describe "self.register" do
13
14
  describe 'legal parameters' do
14
15
  it 'registered at correct place' do
15
- EventAggregator::Aggregator.register(listener, message_type)
16
- expect(EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type]).to include(listener)
16
+ EventAggregator::Aggregator.register(listener, message_type, callback)
17
+ expect(EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type]).to include([listener, callback])
17
18
  end
18
19
 
19
- it 'should not be registered in wrong place' do
20
- EventAggregator::Aggregator.register(listener, message_type)
20
+ it 'not be registered in wrong place' do
21
+ EventAggregator::Aggregator.register(listener, message_type, callback)
21
22
  EventAggregator::Aggregator.class_variable_get(:@@listeners).each do |e|
22
23
  if e[0] == message_type
23
- expect(e[1]).to include(listener)
24
+ expect(e[1]).to include([listener, callback])
24
25
  else
25
- expect(e[1]).to_not include(listener)
26
+ expect(e[1]).to_not include([listener, callback])
26
27
  end
27
28
  end
28
29
  end
29
30
  end
30
31
  describe 'illegal parameters' do
31
- it 'should not allow nil as message type' do
32
- expect{EventAggregator::Aggregator.register(nil, message_type)}.to_not change{EventAggregator::Aggregator.class_variable_get(:@@listeners)}
32
+ it 'not allow nil as message type' do
33
+ expect{EventAggregator::Aggregator.register(nil, message_type, callback)}.to_not change{EventAggregator::Aggregator.class_variable_get(:@@listeners)}
33
34
  end
34
- it 'should not allow non-listener to register' do
35
- expect{EventAggregator::Aggregator.register(EventAggregator::Message.new("a","b"), message_type)}.to_not change{EventAggregator::Aggregator.class_variable_get(:@@listeners)}
36
- expect{EventAggregator::Aggregator.register("string", message_type)}.to_not change{EventAggregator::Aggregator.class_variable_get(:@@listeners)}
37
- expect{EventAggregator::Aggregator.register(1, message_type)}.to_not change{EventAggregator::Aggregator.class_variable_get(:@@listeners)}
38
- expect{EventAggregator::Aggregator.register(2.0, message_type)}.to_not change{EventAggregator::Aggregator.class_variable_get(:@@listeners)}
35
+ it 'not allow non-listener to register' do
36
+ expect{EventAggregator::Aggregator.register(EventAggregator::Message.new("a","b"), message_type, callback)}.to_not change{EventAggregator::Aggregator.class_variable_get(:@@listeners)}
37
+ expect{EventAggregator::Aggregator.register("string", message_type, callback)}.to_not change{EventAggregator::Aggregator.class_variable_get(:@@listeners)}
38
+ expect{EventAggregator::Aggregator.register(1, message_type, callback)}.to_not change{EventAggregator::Aggregator.class_variable_get(:@@listeners)}
39
+ expect{EventAggregator::Aggregator.register(2.0, message_type, callback)}.to_not change{EventAggregator::Aggregator.class_variable_get(:@@listeners)}
39
40
  end
40
41
  end
41
42
  end
42
43
 
43
44
  describe "self.unregister" do
44
45
  describe 'legal parameters' do
45
- it 'should decrease count by 1' do
46
- EventAggregator::Aggregator.register(listener, message_type)
46
+ it 'decrease count by 1' do
47
+ EventAggregator::Aggregator.register(listener, message_type, callback)
47
48
  expect{EventAggregator::Aggregator.unregister(listener, message_type)}.to change{EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type].length}.by(-1)
48
49
  end
49
- it 'should be remove from list' do
50
- EventAggregator::Aggregator.register(listener, message_type)
50
+ it 'be remove from list' do
51
+ EventAggregator::Aggregator.register(listener, message_type, callback)
51
52
  EventAggregator::Aggregator.unregister(listener, message_type)
52
- expect(EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type]).to_not include(listener)
53
+ expect(EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type]).to_not include([listener, callback])
53
54
  end
54
- it 'should keep listener in unrelated lists' do
55
+ it 'keep listener in unrelated lists' do
55
56
  message_type2 = message_type + " different"
56
57
 
57
- EventAggregator::Aggregator.register(listener, message_type)
58
- EventAggregator::Aggregator.register(listener, message_type2)
58
+ EventAggregator::Aggregator.register(listener, message_type, callback)
59
+ EventAggregator::Aggregator.register(listener, message_type2, callback)
59
60
 
60
61
  EventAggregator::Aggregator.unregister(listener, message_type)
61
62
 
62
- expect(EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type2]).to include(listener)
63
+ expect(EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type2]).to include([listener, callback])
63
64
  end
64
65
  end
65
66
  describe 'unregitering nonregisterd listener' do
66
- it 'should not change list' do
67
+ it 'not change list' do
67
68
  message_type1 = message_type + " different 1"
68
69
  message_type2 = message_type + " different 2"
69
70
  message_type3 = message_type + " different 3"
@@ -71,9 +72,9 @@ describe EventAggregator::Aggregator do
71
72
  listener2 = listener_class.new
72
73
  listener3 = listener_class.new
73
74
 
74
- EventAggregator::Aggregator.register(listener1, message_type1)
75
- EventAggregator::Aggregator.register(listener2, message_type2)
76
- EventAggregator::Aggregator.register(listener3, message_type3)
75
+ EventAggregator::Aggregator.register(listener1, message_type1, callback)
76
+ EventAggregator::Aggregator.register(listener2, message_type2, callback)
77
+ EventAggregator::Aggregator.register(listener3, message_type3, callback)
77
78
 
78
79
  #Touching hash
79
80
  EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type]
@@ -82,22 +83,22 @@ describe EventAggregator::Aggregator do
82
83
  expect{EventAggregator::Aggregator.unregister(listener2, message_type)}.to_not change{EventAggregator::Aggregator.class_variable_get(:@@listeners)}
83
84
  expect{EventAggregator::Aggregator.unregister(listener3, message_type)}.to_not change{EventAggregator::Aggregator.class_variable_get(:@@listeners)}
84
85
 
85
- expect(EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type1]).to include(listener1)
86
- expect(EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type2]).to include(listener2)
87
- expect(EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type3]).to include(listener3)
86
+ expect(EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type1]).to include([listener1, callback])
87
+ expect(EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type2]).to include([listener2, callback])
88
+ expect(EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type3]).to include([listener3, callback])
88
89
  end
89
90
  end
90
91
  describe 'unregitering listener from wrong message type' do
91
- it 'should not change list' do
92
+ it 'not change list' do
92
93
  message_type2 = message_type + " different"
93
94
 
94
- EventAggregator::Aggregator.register(listener, message_type)
95
+ EventAggregator::Aggregator.register(listener, message_type, callback)
95
96
 
96
97
  expect{EventAggregator::Aggregator.unregister(listener, message_type2)}.to_not change{EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type]}
97
98
  end
98
99
  end
99
100
  describe 'unregitering non-listener class' do
100
- it 'should not change register list' do
101
+ it 'not change register list' do
101
102
  #Touching hash
102
103
  EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type]
103
104
 
@@ -111,14 +112,14 @@ describe EventAggregator::Aggregator do
111
112
 
112
113
  describe "self.unregister_all" do
113
114
  describe "unregistering listener registered to one message type" do
114
- it "should unregister from list" do
115
- EventAggregator::Aggregator.register(listener, message_type)
115
+ it "unregister from list" do
116
+ EventAggregator::Aggregator.register(listener, message_type, callback)
116
117
 
117
118
  EventAggregator::Aggregator.unregister_all(listener)
118
119
 
119
- expect(EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type]).to_not include(listener)
120
+ expect(EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type]).to_not include([listener, callback])
120
121
  end
121
- it "should not unregister wrong listener" do
122
+ it "not unregister wrong listener" do
122
123
  listener2 = listener_class.new
123
124
  listener3 = listener_class.new
124
125
  listener4 = listener_class.new
@@ -126,65 +127,67 @@ describe EventAggregator::Aggregator do
126
127
  message_type2 = message_type + " different"
127
128
  message_type3 = message_type + " different 2"
128
129
 
129
- EventAggregator::Aggregator.register(listener, message_type)
130
- EventAggregator::Aggregator.register(listener2, message_type)
131
- EventAggregator::Aggregator.register(listener3, message_type2)
132
- EventAggregator::Aggregator.register(listener4, message_type3)
130
+ EventAggregator::Aggregator.register(listener, message_type, callback)
131
+ EventAggregator::Aggregator.register(listener2, message_type, callback)
132
+ EventAggregator::Aggregator.register(listener3, message_type2, callback)
133
+ EventAggregator::Aggregator.register(listener4, message_type3, callback)
133
134
 
134
135
 
135
136
  EventAggregator::Aggregator.unregister_all(listener)
136
137
 
137
- expect(EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type]).to include(listener2)
138
- expect(EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type2]).to include(listener3)
139
- expect(EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type3]).to include(listener4)
138
+ expect(EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type]).to include([listener2, callback])
139
+ expect(EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type2]).to include([listener3, callback])
140
+ expect(EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type3]).to include([listener4, callback])
140
141
  end
141
142
  end
142
143
  describe "unregistering listener registered for several message types" do
143
- it "should unregister from all lists" do
144
- EventAggregator::Aggregator.register(listener, message_type)
144
+ it "unregister from all lists" do
145
+ EventAggregator::Aggregator.register(listener, message_type, callback)
145
146
  message_type2 = message_type + " different"
146
- EventAggregator::Aggregator.register(listener, message_type2)
147
+ EventAggregator::Aggregator.register(listener, message_type2, callback)
147
148
 
148
149
  EventAggregator::Aggregator.unregister_all(listener)
149
150
 
150
- expect(EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type]).to_not include(listener)
151
- expect(EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type2]).to_not include(listener)
151
+ expect(EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type]).to_not include([listener, callback])
152
+ expect(EventAggregator::Aggregator.class_variable_get(:@@listeners)[message_type2]).to_not include([listener, callback])
152
153
  end
153
154
  end
154
155
  end
155
156
 
156
157
  describe "self.message_publish" do
157
158
  describe 'legal parameters' do
158
- it 'should receive correct messages' do
159
- EventAggregator::Aggregator.register(listener, message_type)
159
+ it 'run correct callback' do
160
+ EventAggregator::Aggregator.register(listener, message_type, callback)
160
161
  message = EventAggregator::Message.new(message_type, data)
161
162
 
162
- expect(listener).to receive(:receive_message).with(message)
163
+ expect(callback).to receive(:call).with(data)
163
164
 
164
165
  EventAggregator::Aggregator.message_publish(message)
165
166
  end
166
- it 'should not receive incorrect messages' do
167
+ it 'not run incorrect callback' do
167
168
  message_type2 = message_type + " different"
168
169
 
169
- EventAggregator::Aggregator.register(listener, message_type)
170
+ EventAggregator::Aggregator.register(listener, message_type, callback)
170
171
  message = EventAggregator::Message.new(message_type2, data)
171
172
 
172
- expect(listener).to_not receive(:receive_message)
173
+ expect(callback).to_not receive(:call).with(data)
173
174
 
174
175
  EventAggregator::Aggregator.message_publish(message)
175
176
  end
176
177
 
177
- it 'should send message to right listener' do
178
+ it 'run correct callback in list' do
178
179
  listener2 = listener_class.new
179
180
  message_type2 = message_type + " different"
180
181
 
181
- EventAggregator::Aggregator.register(listener, message_type)
182
- EventAggregator::Aggregator.register(listener, message_type2)
182
+ callback2 = lambda{|data|}
183
+
184
+ EventAggregator::Aggregator.register(listener, message_type, callback)
185
+ EventAggregator::Aggregator.register(listener, message_type2, callback2)
183
186
 
184
187
  message = EventAggregator::Message.new(message_type, data)
185
188
 
186
- expect(listener).to receive(:receive_message).with(message)
187
- expect(listener2).to_not receive(:receive_message)
189
+ expect(callback).to receive(:call).with(data)
190
+ expect(callback2).to_not receive(:call)
188
191
 
189
192
  EventAggregator::Aggregator.message_publish(message)
190
193
  end
@@ -198,5 +201,52 @@ describe EventAggregator::Aggregator do
198
201
  expect{EventAggregator::Aggregator.message_publish(nil)}.to raise_error
199
202
  end
200
203
  end
204
+ describe 'consisten_data behaviour' do
205
+ it 'uses same object when true' do
206
+ listener2 = listener_class.new
207
+ callback1 = lambda{|data|}
208
+ callback2 = lambda{|data|}
209
+
210
+ EventAggregator::Aggregator.register(listener, message_type, callback1)
211
+ EventAggregator::Aggregator.register(listener2, message_type, callback2)
212
+
213
+ message = EventAggregator::Message.new(message_type, data)
214
+
215
+ expect(callback1).to receive(:call) {|arg| expect(arg).to equal(data)}
216
+ expect(callback2).to receive(:call) {|arg| expect(arg).to equal(data)}
217
+
218
+ EventAggregator::Aggregator.message_publish(message, false, true)
219
+ end
220
+ it 'uses different objects when false' do
221
+ listener2 = listener_class.new
222
+ callback1 = lambda{|data| data ="no"}
223
+ callback2 = lambda{|data| data ="no"}
224
+
225
+ EventAggregator::Aggregator.register(listener, message_type, callback1)
226
+ EventAggregator::Aggregator.register(listener2, message_type, callback2)
227
+
228
+ message = EventAggregator::Message.new(message_type, data)
229
+
230
+ expect(callback1).to receive(:call) {|arg| expect(arg).to_not equal(data)}
231
+ expect(callback2).to receive(:call) {|arg| expect(arg).to_not equal(data)}
232
+
233
+ EventAggregator::Aggregator.message_publish(message, false, false)
234
+ end
235
+ it 'objects have same values when false' do
236
+ listener2 = listener_class.new
237
+ callback1 = lambda{|data| data ="no"}
238
+ callback2 = lambda{|data| data ="no"}
239
+
240
+ EventAggregator::Aggregator.register(listener, message_type, callback1)
241
+ EventAggregator::Aggregator.register(listener2, message_type, callback2)
242
+
243
+ message = EventAggregator::Message.new(message_type, data)
244
+
245
+ expect(callback1).to receive(:call) {|arg| expect(arg).to eq(data)}
246
+ expect(callback2).to receive(:call) {|arg| expect(arg).to eq(data)}
247
+
248
+ EventAggregator::Aggregator.message_publish(message, false, false)
249
+ end
250
+ end
201
251
  end
202
252
  end
@@ -23,68 +23,38 @@ describe EventAggregator::Listener do
23
23
  EventAggregator::Aggregator.class_variable_set :@@listener, Hash.new{|h, k| h[k] = []}
24
24
  @message = EventAggregator::Message.new(message_type, data)
25
25
  end
26
- describe '.receive_message' do
27
- describe 'legal parameters' do
28
- it 'execute callback' do
29
- #TODO: This is subject to refactor because the method is stroed in the module by a hack.
30
- # This stuff should be moved to the aggregator, or somewhere else.
31
- listener.class.publicize_methods do
32
- listener.message_type_to_receive_add(message_type, lambda_method)
33
-
34
- expect(lambda_method).to receive(:call)
35
-
36
- listener.receive_message(@message)
37
- end
38
- end
39
- end
40
- describe 'illegal parameters' do
41
- #This should not recieve illegal parameters.
42
- it 'pending' do
43
- pending "not implemented"
44
- end
45
- end
46
- end
47
26
 
48
27
  describe '.message_type_to_receive_add' do
49
28
  describe 'legal parameters' do
50
- it 'should register at aggregator' do
51
- expect(EventAggregator::Aggregator).to receive(:register).with(listener, message_type)
29
+ it 'invoke aggregator register' do
30
+ expect(EventAggregator::Aggregator).to receive(:register).with(listener, message_type, lambda_method)
52
31
 
53
32
  listener.class.publicize_methods do
54
- listener.message_type_to_receive_add(message_type, lambda_method)
33
+ listener.message_type_register(message_type, lambda_method)
55
34
  end
56
35
  end
57
- it 'pending' do
58
- pending "not implemented"
59
- end
60
36
  end
61
37
  describe 'illegal parameters' do
62
- it 'not valid' do
63
- expect{listener.message_type_to_receive_add(message_type, nil)}.to raise_error
64
- expect{listener.message_type_to_receive_add(message_type, 1)}.to raise_error
65
- expect{listener.message_type_to_receive_add(message_type, "string")}.to raise_error
66
- expect{listener.message_type_to_receive_add(message_type, listener_class.new)}.to raise_error
38
+ it 'raise error' do
39
+ expect{listener.message_type_register(message_type, nil)}.to raise_error
40
+ expect{listener.message_type_register(message_type, 1)}.to raise_error
41
+ expect{listener.message_type_register(message_type, "string")}.to raise_error
42
+ expect{listener.message_type_register(message_type, listener_class.new)}.to raise_error
67
43
  end
68
44
  end
69
45
  end
70
46
 
71
47
  describe '.message_type_to_receive_remove' do
72
48
  describe 'legal parameters' do
73
- it 'not recieve callbacks' do
49
+ it 'invoke aggregator unregister' do
74
50
  listener.class.publicize_methods do
75
- listener.message_type_to_receive_add(message_type, lambda_method)
76
- listener.message_type_to_receive_remove(message_type)
51
+ listener.message_type_register(message_type, lambda_method)
52
+
53
+ expect(EventAggregator::Aggregator).to receive(:unregister).with(listener, message_type)
77
54
 
78
- expect(lambda_method).to_not receive(:call)
79
-
80
- listener.receive_message(@message)
55
+ listener.message_type_unregister(message_type)
81
56
  end
82
57
  end
83
58
  end
84
- describe 'illegal parameters' do
85
- it 'not registered reciever' do
86
- pending "This will really likely be removed in next refactor"
87
- end
88
- end
89
59
  end
90
60
  end
@@ -5,25 +5,20 @@ describe EventAggregator::Message do
5
5
  let(:message_type) {Faker::Name.name}
6
6
  let(:data) {Faker::Name.name}
7
7
  let(:listener_class) { (Class.new { include EventAggregator::Listener }) }
8
+ let(:callback) { lambda{ |data| } }
8
9
 
9
10
  before(:each) do
10
11
  EventAggregator::Aggregator.class_variable_set :@@listener, Hash.new{|h, k| h[k] = []}
11
12
  @listener_one = listener_class.new
12
13
  @listener_two = listener_class.new
13
14
 
14
- EventAggregator::Aggregator.register(@listener_one, message_type)
15
- EventAggregator::Aggregator.register(@listener_two, message_type+" different")
15
+ EventAggregator::Aggregator.register(@listener_one, message_type, callback)
16
+ EventAggregator::Aggregator.register(@listener_two, message_type+" different", callback)
16
17
  end
17
18
 
18
- it 'should be received by a correct subscribers' do
19
- message = EventAggregator::Message.new(message_type, data)
20
- expect(@listener_one).to receive(:receive_message).with(message)
21
- expect(@listener_two).to_not receive(:receive_message)
22
-
23
- message.publish
24
- end
25
- it 'should be published to the aggregator' do
19
+ it 'should invoke message_publish on aggregator' do
26
20
  message = EventAggregator::Message.new(message_type, data)
21
+
27
22
  expect(EventAggregator::Aggregator).to receive(:message_publish).with(message)
28
23
 
29
24
  message.publish
data/spec/spec_helper.rb CHANGED
@@ -2,6 +2,8 @@ require "rubygems"
2
2
  require "bundler/setup"
3
3
  require "factory_girl"
4
4
  require "faker"
5
+ require "sucker_punch"
6
+ require "sucker_punch/testing/inline"
5
7
 
6
8
  require "event_aggregator"
7
9
 
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: event_aggregator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
5
- prerelease:
4
+ version: 1.0.0.pre
5
+ prerelease: 6
6
6
  platform: ruby
7
7
  authors:
8
8
  - Stephan Eriksen
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-12-19 00:00:00.000000000 Z
12
+ date: 2013-12-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -91,6 +91,22 @@ dependencies:
91
91
  - - ! '>='
92
92
  - !ruby/object:Gem::Version
93
93
  version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: sucker_punch
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: '1.0'
102
+ type: :runtime
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: '1.0'
94
110
  description: A simple Ruby event aggregator.
95
111
  email:
96
112
  - stephan.n.eriksen@gmail.com
@@ -110,6 +126,7 @@ files:
110
126
  - lib/event_aggregator/aggregator.rb
111
127
  - lib/event_aggregator/listener.rb
112
128
  - lib/event_aggregator/message.rb
129
+ - lib/event_aggregator/message_job.rb
113
130
  - lib/event_aggregator/version.rb
114
131
  - spec/factories.rb
115
132
  - spec/lib/event_aggregator/aggregator_spec.rb
@@ -132,9 +149,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
132
149
  required_rubygems_version: !ruby/object:Gem::Requirement
133
150
  none: false
134
151
  requirements:
135
- - - ! '>='
152
+ - - ! '>'
136
153
  - !ruby/object:Gem::Version
137
- version: '0'
154
+ version: 1.3.1
138
155
  requirements: []
139
156
  rubyforge_project:
140
157
  rubygems_version: 1.8.25