emittance 0.0.6 → 0.1.0
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/emittance/dispatcher/registration_collection_proxy.rb +47 -0
- data/lib/emittance/dispatcher/registration_map.rb +94 -0
- data/lib/emittance/dispatcher.rb +77 -0
- data/lib/emittance/dispatchers/synchronous.rb +8 -54
- data/lib/emittance/emitter.rb +1 -1
- data/lib/emittance/notifier.rb +54 -0
- data/lib/emittance/version.rb +1 -1
- data/lib/emittance.rb +2 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5aa08e8db74f9be24f08a38983291c67293c204e
|
4
|
+
data.tar.gz: 738f991042e17d4414fc491bdf74df4360801f30
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 86045a1315babc710189b66ddde7e800ff830048c3bbcd954469adb915d689ebcd4d3dea42dc91a2ceca3c5e3932da5c260bb955c8381b02342e97a1579cfabc
|
7
|
+
data.tar.gz: ec7772819f3e6e0e47a367667b2fb986547ebe293a1ccb5a318eaf05ac279f2bb480f6d66e30c172f1de92ea1f966e0096f7cb438d838cebcafe7f21489a55ef
|
data/Gemfile.lock
CHANGED
@@ -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
|
-
|
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
|
20
|
-
|
21
|
-
registrations
|
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
|
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
|
data/lib/emittance/emitter.rb
CHANGED
@@ -114,7 +114,7 @@ module Emittance
|
|
114
114
|
end
|
115
115
|
|
116
116
|
def _method_patch_str(method_name, non_emitting_method, identifier)
|
117
|
-
|
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
|
data/lib/emittance/version.rb
CHANGED
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
|
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-
|
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
|