emittance 0.0.6 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 04b42fbe154e0d5cde79009304ca822446cdab4a
4
- data.tar.gz: 7ab0a1d41824b4ac72b0eea7ffb452a1d4023434
3
+ metadata.gz: 5aa08e8db74f9be24f08a38983291c67293c204e
4
+ data.tar.gz: 738f991042e17d4414fc491bdf74df4360801f30
5
5
  SHA512:
6
- metadata.gz: f7a2c245677fbedd995c14a097111051f9b5e545d72d3653e5ffa18eb7b931531453c050c8d8f6cfd58b9c1dec2a55637a63b1a21f374e56ac7e86754e3f3d03
7
- data.tar.gz: b96f64c4b769476dab89bd3922db4db33b3cb14a5f4c7f6d91b7db3263148e2fcc25cac845c0915452afc696bf34604c6ee65da9575fc196c8350711ae71900b
6
+ metadata.gz: 86045a1315babc710189b66ddde7e800ff830048c3bbcd954469adb915d689ebcd4d3dea42dc91a2ceca3c5e3932da5c260bb955c8381b02342e97a1579cfabc
7
+ data.tar.gz: ec7772819f3e6e0e47a367667b2fb986547ebe293a1ccb5a318eaf05ac279f2bb480f6d66e30c172f1de92ea1f966e0096f7cb438d838cebcafe7f21489a55ef
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- emittance (0.0.6)
4
+ emittance (0.1.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emittance
4
+ class Dispatcher
5
+ ##
6
+ # A collection proxy for registrations. Can include multiple key/value pairs.
7
+ #
8
+ class RegistrationCollectionProxy
9
+ # @param lookup_term the term initially used to lookup the registrations
10
+ # @param mappings [Hash] the mappings of identifiers to their respective registrations
11
+ def initialize(lookup_term, mappings)
12
+ @lookup_term = lookup_term
13
+ @mappings = mappings
14
+ end
15
+
16
+ # @param args args passed to +Array#each+
17
+ # @param blk block passed to +Array#each+
18
+ # @return [RegistrationCollectionProxy] self
19
+ def each(*args, &blk)
20
+ arrays = mappings.values.map(&:to_a)
21
+ arrays.flatten.each(*args, &blk)
22
+ self
23
+ end
24
+
25
+ # @return [Boolean] true if there are no registrations at all, false otherwise
26
+ def empty?
27
+ mappings.values.all?(&:empty?)
28
+ end
29
+
30
+ # @return [RegistrationCollectionProxy] self
31
+ def <<(item)
32
+ mappings[lookup_term] << item
33
+ self
34
+ end
35
+
36
+ # @return [RegistrationCollectionProxy] self
37
+ def clear
38
+ mappings.values.each(&:clear)
39
+ self
40
+ end
41
+
42
+ private
43
+
44
+ attr_reader :lookup_term, :mappings
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'emittance/dispatcher/registration_collection_proxy'
4
+
5
+ module Emittance
6
+ class Dispatcher
7
+ ##
8
+ # A proxy for a hash. Identifies special identifiers.
9
+ #
10
+ class RegistrationMap
11
+ SPECIAL_IDENTIFIER_REGEX = /^\@/
12
+
13
+ class << self
14
+ # @param identifier the identifier we want to know information about
15
+ # @return [Boolean] true if the identifier is a special one, false otherwise
16
+ def special_identifier?(identifier)
17
+ identifier.to_s =~ SPECIAL_IDENTIFIER_REGEX
18
+ end
19
+ end
20
+
21
+ # Build a registration map.
22
+ def initialize
23
+ @reg_map = {}
24
+ end
25
+
26
+ # @param identifier the identifier you wish to lookup registrations for
27
+ # @return [RegistrationCollectionProxy] a collection of registrations for that identifier
28
+ def [](identifier)
29
+ lookup_term, keys = keys_for(identifier)
30
+ collection_for(lookup_term, keys)
31
+ end
32
+
33
+ # @param args args passed to +Hash#each_key+
34
+ # @param blk block passed to +Hash#each_key+
35
+ # @return [RegistrationMap] self
36
+ def each_key(*args, &blk)
37
+ reg_map.each_key(*args, &blk)
38
+ self
39
+ end
40
+
41
+ private
42
+
43
+ attr_reader :reg_map
44
+
45
+ def keys_for(identifier)
46
+ if special_identifier?(identifier)
47
+ keys_for_special_identifier(identifier)
48
+ else
49
+ keys_for_event_identifier(identifier)
50
+ end
51
+ end
52
+
53
+ def keys_for_special_identifier(identifier)
54
+ keys = [identifier.to_sym]
55
+
56
+ case identifier.to_s
57
+ when '@all'
58
+ keys += reg_map.keys.select { |key| key.is_a?(Class) }
59
+ end
60
+
61
+ [identifier.to_sym, keys]
62
+ end
63
+
64
+ def keys_for_event_identifier(identifier)
65
+ klass = Emittance::EventLookup.find_event_klass(identifier)
66
+ keys = [klass] + keys_matching_event_klass(klass)
67
+ [klass, keys]
68
+ end
69
+
70
+ def keys_matching_event_klass(_klass)
71
+ [:@all]
72
+ end
73
+
74
+ def collection_for(lookup_term, keys)
75
+ mappings = Hash[
76
+ keys.map do |key|
77
+ reg_map[key] ||= empty_registration
78
+ [key, reg_map[key]]
79
+ end
80
+ ]
81
+
82
+ RegistrationCollectionProxy.new(lookup_term, mappings)
83
+ end
84
+
85
+ def empty_registration
86
+ Set.new
87
+ end
88
+
89
+ def special_identifier?(identifier)
90
+ self.class.special_identifier?(identifier)
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'set'
4
+
5
+ require 'emittance/dispatcher/registration_map'
6
+
7
+ module Emittance
8
+ ##
9
+ # Abstract class for dispatchers. Subclasses must implement the following methods:
10
+ #
11
+ # - +._process_event+
12
+ # - +._register+
13
+ # - +._register_method_call+
14
+ #
15
+ # These methods can be private. These methods will have access to +.registrations_for+, which takes an identifier
16
+ # and returns an enumerable object with each object registered to that identifier. These objects can be anything
17
+ # you want, but typically represent the callback you would like to run whenever an event of a certain type is
18
+ # emitted.
19
+ #
20
+ class Dispatcher
21
+ class << self
22
+ # @private
23
+ def inherited(subklass)
24
+ subklass.instance_variable_set '@registrations', RegistrationMap.new
25
+ end
26
+
27
+ # Calls the subclass's +_process_event+ method.
28
+ def process_event(event)
29
+ _process_event(event)
30
+ end
31
+
32
+ # Calls the subclass's +_register+ method.
33
+ def register(identifier, &callback)
34
+ _register(identifier, &callback)
35
+ end
36
+
37
+ # Calls the subclass's +_register_method_call+ method.
38
+ def register_method_call(identifier, object, method_name)
39
+ _register_method_call(identifier, object, method_name)
40
+ end
41
+
42
+ # @param identifier the identifier the registrations for which you would like to look up
43
+ # @return [RegistrationCollectionProxy] an enumerable containing all registrations for a given identifier
44
+ def registrations_for(identifier)
45
+ registrations[identifier]
46
+ end
47
+
48
+ # @return [RegistrationMap] the registrations
49
+ def clear_registrations!
50
+ registrations.each_key { |key| clear_registrations_for! key }
51
+ registrations
52
+ end
53
+
54
+ # @param identifier the identifier the registrations for hwich you would like to clear
55
+ # @return [RegistrationCollectionProxy] the cleared registration proxy
56
+ def clear_registrations_for!(identifier)
57
+ registrations_for(identifier).clear
58
+ end
59
+
60
+ private
61
+
62
+ attr_reader :registrations
63
+
64
+ def _process_event(_event)
65
+ raise NotImplementedError
66
+ end
67
+
68
+ def _register(_identifier, &_callback)
69
+ raise NotImplementedError
70
+ end
71
+
72
+ def _register_method_call(_identifier, _object, _method_name)
73
+ raise NotImplementedError
74
+ end
75
+ end
76
+ end
77
+ end
@@ -5,76 +5,30 @@ module Emittance
5
5
  ##
6
6
  # The synchronous dispatcher. Runs callbacks one-by-one, in series.
7
7
  #
8
- class Dispatcher
9
- @registrations = {}
10
- @enabled = true
11
-
8
+ class Dispatcher < Emittance::Dispatcher
12
9
  class << self
13
- def process_event(event)
10
+ private
11
+
12
+ def _process_event(event)
14
13
  registrations_for(event).each do |registration|
15
14
  registration.call event
16
15
  end
17
16
  end
18
17
 
19
- def registrations_for(identifier)
20
- event_klass = find_event_klass identifier
21
- registrations[event_klass] ||= empty_registration
22
- registrations[event_klass]
23
- end
24
-
25
- def register(identifier, &callback)
26
- event_klass = find_event_klass identifier
27
- registrations[event_klass] ||= empty_registration
28
- registrations_for(event_klass) << Registration.new(event_klass, &callback)
29
-
18
+ def _register(identifier, &callback)
19
+ registrations = registrations_for identifier
20
+ registrations << callback
30
21
  callback
31
22
  end
32
23
 
33
- def register_method_call(identifier, object, method_name)
24
+ def _register_method_call(identifier, object, method_name)
34
25
  register identifier, &lambda_for_method_call(object, method_name)
35
26
  end
36
27
 
37
- def clear_registrations!
38
- registrations.each_key do |event_klass|
39
- clear_registrations_for! event_klass
40
- end
41
- end
42
-
43
- def clear_registrations_for!(identifier)
44
- event_klass = find_event_klass identifier
45
- registrations[event_klass].clear
46
- end
47
-
48
- private
49
-
50
- attr_accessor :registrations
51
-
52
- def empty_registration
53
- Set.new
54
- end
55
-
56
- def find_event_klass(event)
57
- Emittance::EventLookup.find_event_klass(event)
58
- end
59
-
60
28
  def lambda_for_method_call(object, method_name)
61
29
  ->(event) { object.send method_name, event }
62
30
  end
63
31
  end
64
-
65
- # @private
66
- class Registration
67
- attr_reader :event_klass
68
-
69
- def initialize(event_klass, &callback)
70
- @event_klass = event_klass
71
- @callback = callback
72
- end
73
-
74
- def call(event)
75
- @callback.call event
76
- end
77
- end
78
32
  end
79
33
  end
80
34
  end
@@ -114,7 +114,7 @@ module Emittance
114
114
  end
115
115
 
116
116
  def _method_patch_str(method_name, non_emitting_method, identifier)
117
- <<~RUBY
117
+ <<-RUBY
118
118
  def #{method_name}(*args, &blk)
119
119
  return_value = #{non_emitting_method}(*args, &blk)
120
120
  if #{!identifier.nil? ? true : false}
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Emittance
4
+ ##
5
+ # Like +Emittance::Action+, this is a convenience module that you can mix-in to any class that provides a shortuct
6
+ # for a common pattern. An object (usually, a class) that mixes in +Emittance::Notifier+ will watch for all events
7
+ # and call the method on that object with the same name as the event's identifier. For example:
8
+ #
9
+ # class MyNotifier
10
+ # extend Emittance::Notifier
11
+ #
12
+ # def self.something_happened(event)
13
+ # puts 'something definitely happened!'
14
+ # end
15
+ # end
16
+ #
17
+ # Whenever an event whose identifiers include +something_happened+ is emitted, +MyNotifier.something_happened+ will
18
+ # be invoked.
19
+ #
20
+ # foo.emit :something_happened
21
+ # # Prints:
22
+ # # something definitely happened!
23
+ #
24
+ # foo.emit :something_else_happened
25
+ # # (nothing)
26
+ #
27
+ # Notice that (1) +MyNotifier+ doesn't need to explicitly listen to `:something_happened`, and (2) no errors or
28
+ # anything occur when an event is emitted for which +MyNotifier+ doesn't have a method defined.
29
+ #
30
+ module Notifier
31
+ # @private
32
+ class << self
33
+ def extended(extender)
34
+ extender.extend Emittance::Watcher
35
+
36
+ extender.watch :@all, :_emittance_handle_event
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ def _emittance_handle_event(event)
43
+ identifiers = event.identifiers
44
+ identifiers.each do |identifier|
45
+ formatted_identifier = _emittance_format_identifier(identifier)
46
+ send(formatted_identifier) if respond_to?(formatted_identifier)
47
+ end
48
+ end
49
+
50
+ def _emittance_format_identifier(identifier)
51
+ identifier.to_s.split('/').last
52
+ end
53
+ end
54
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Emittance
4
- VERSION = '0.0.6'
4
+ VERSION = '0.1.0'
5
5
  end
data/lib/emittance.rb CHANGED
@@ -6,11 +6,13 @@ require 'emittance/errors'
6
6
  require 'emittance/helpers/string_helpers'
7
7
  require 'emittance/helpers/constant_helpers'
8
8
  require 'emittance/event_lookup'
9
+ require 'emittance/dispatcher'
9
10
  require 'emittance/brokerage'
10
11
  require 'emittance/broker'
11
12
  require 'emittance/event'
12
13
  require 'emittance/emitter'
13
14
  require 'emittance/watcher'
15
+ require 'emittance/notifier'
14
16
  require 'emittance/action'
15
17
 
16
18
  ##
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: emittance
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tyler Guillen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-12-15 00:00:00.000000000 Z
11
+ date: 2017-12-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -120,6 +120,9 @@ files:
120
120
  - lib/emittance/broker.rb
121
121
  - lib/emittance/brokerage.rb
122
122
  - lib/emittance/brokers/synchronous.rb
123
+ - lib/emittance/dispatcher.rb
124
+ - lib/emittance/dispatcher/registration_collection_proxy.rb
125
+ - lib/emittance/dispatcher/registration_map.rb
123
126
  - lib/emittance/dispatchers/synchronous.rb
124
127
  - lib/emittance/emitter.rb
125
128
  - lib/emittance/errors.rb
@@ -127,6 +130,7 @@ files:
127
130
  - lib/emittance/event_lookup.rb
128
131
  - lib/emittance/helpers/constant_helpers.rb
129
132
  - lib/emittance/helpers/string_helpers.rb
133
+ - lib/emittance/notifier.rb
130
134
  - lib/emittance/version.rb
131
135
  - lib/emittance/watcher.rb
132
136
  homepage: https://github.com/aastronautss/emittance