emittance 0.0.1 → 0.0.2
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/.gitignore +3 -0
- data/.rubocop.yml +12 -0
- data/.travis.yml +3 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/LICENSE.txt +21 -0
- data/README.md +91 -3
- data/lib/emittance/action.rb +174 -181
- data/lib/emittance/broker.rb +18 -65
- data/lib/emittance/brokerage.rb +56 -0
- data/lib/emittance/brokers/synchronous.rb +15 -0
- data/lib/emittance/dispatcher.rb +115 -0
- data/lib/emittance/emitter.rb +112 -88
- data/lib/emittance/errors.rb +13 -0
- data/lib/emittance/event/event_builder.rb +143 -63
- data/lib/emittance/event.rb +66 -18
- data/lib/emittance/registration.rb +13 -9
- data/lib/emittance/version.rb +3 -1
- data/lib/emittance/watcher.rb +10 -6
- data/lib/emittance.rb +23 -8
- data/pkg/emittance-0.0.1.gem +0 -0
- metadata +11 -5
- data/.rspec_status +0 -29
- data/lib/.DS_Store +0 -0
- data/lib/emittance/.DS_Store +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 480d65a814b24509517a96de13d0590117504f2d
|
4
|
+
data.tar.gz: 3c41c536af288cb32adc9cc00f2be9c0f8c7f15c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d1946bdae18b76de6989aef2342a8ed87341a9d0475dfc1f5459598bdd804c69a97c789f6bbb37af270341d1a8cbda2d2249e0f1adada2a74066883fcf5b5729
|
7
|
+
data.tar.gz: 2b1735b0f9f56884ae2e9520b48df74b7540f26565c125a3272ec9165614cbebfa8b3ee2e36a64918b3c244589ff71a6100daeb667947abbe2fb25fc3fae3739
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, disability, ethnicity, gender identity and expression, level of experience,
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
10
|
+
orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
15
|
+
include:
|
16
|
+
|
17
|
+
* Using welcoming and inclusive language
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
19
|
+
* Gracefully accepting constructive criticism
|
20
|
+
* Focusing on what is best for the community
|
21
|
+
* Showing empathy towards other community members
|
22
|
+
|
23
|
+
Examples of unacceptable behavior by participants include:
|
24
|
+
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
+
advances
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
+
* Public or private harassment
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
30
|
+
address, without explicit permission
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
+
professional setting
|
33
|
+
|
34
|
+
## Our Responsibilities
|
35
|
+
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
38
|
+
response to any instances of unacceptable behavior.
|
39
|
+
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
+
threatening, offensive, or harmful.
|
45
|
+
|
46
|
+
## Scope
|
47
|
+
|
48
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
+
when an individual is representing the project or its community. Examples of
|
50
|
+
representing a project or community include using an official project e-mail
|
51
|
+
address, posting via an official social media account, or acting as an appointed
|
52
|
+
representative at an online or offline event. Representation of a project may be
|
53
|
+
further defined and clarified by project maintainers.
|
54
|
+
|
55
|
+
## Enforcement
|
56
|
+
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
+
reported by contacting the project team at tyguillen@gmail.com. All
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
63
|
+
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
66
|
+
members of the project's leadership.
|
67
|
+
|
68
|
+
## Attribution
|
69
|
+
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
+
available at [http://contributor-covenant.org/version/1/4][version]
|
72
|
+
|
73
|
+
[homepage]: http://contributor-covenant.org
|
74
|
+
[version]: http://contributor-covenant.org/version/1/4/
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Tyler Guillen
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
# Emittance
|
2
2
|
|
3
|
+
[](https://travis-ci.org/aastronautss/emittance)
|
4
|
+
[](https://codeclimate.com/github/aastronautss/emittance/maintainability)
|
5
|
+
|
3
6
|
Emittance is a flexible eventing library that provides a clean interface for both emitting and capturing events. It follows the following workflow:
|
4
7
|
|
5
8
|
1. Objects (and therefore, classes) can emit events, identified by a symbol.
|
6
|
-
2. Events are objects that know who emitted them.
|
9
|
+
2. Events are objects that know who emitted them, what time the event was emitted, and any additional information.
|
7
10
|
3. Objects (and therefore, classes) can watch for events that get emitted.
|
8
11
|
|
9
12
|
Per this pattern, objects are responsible for knowing what events they want to listen to. While this is pragmatically the same as a "push"-style message system (watchers don't need to go check a topic themselves), the semantics are a little different.
|
@@ -28,7 +31,92 @@ Or install it yourself as:
|
|
28
31
|
|
29
32
|
## Usage
|
30
33
|
|
31
|
-
|
34
|
+
If you want a class and its instances to be able to emit events, have it extend `Emittance::Emitter`.
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
class Foo
|
38
|
+
extend Emittance::Emitter
|
39
|
+
end
|
40
|
+
```
|
41
|
+
|
42
|
+
Emitters can emit events like so:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
my_foo = Foo.new
|
46
|
+
my_foo.emit :something_happened
|
47
|
+
Foo.emit :something_else_happened # Classes who extended Emitter can also emit events!
|
48
|
+
```
|
49
|
+
|
50
|
+
As you can see, event types are identified by a symbol. More on that later. You can also pass in an optional payload, which can be any object:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
my_foo.emit :something_happened, "Here's a payload!"
|
54
|
+
```
|
55
|
+
|
56
|
+
The above examples are cool, but it's generally a better idea to have an object emit its own events:
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
class Foo
|
60
|
+
extend Emittance::Emitter
|
61
|
+
|
62
|
+
def make_something_happen
|
63
|
+
emit :something_happened, "Here's a payload!"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
my_foo = Foo.new
|
68
|
+
my_foo.make_something_happen
|
69
|
+
```
|
70
|
+
|
71
|
+
What happens with these events? Watchers are objects that capture these event emissions. You can set up a watcher by including or extending `Emittance::Watcher`:
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
class Bar
|
75
|
+
extend Emittance::Watcher
|
76
|
+
end
|
77
|
+
```
|
78
|
+
|
79
|
+
To watch for these events, you can just call the `watch` method, which takes the symbol identifier and a block that serves as a callback:
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
Bar.watch :something_happened do |event|
|
83
|
+
puts 'Something definitely happened!'
|
84
|
+
puts event.identifier.inspect
|
85
|
+
puts event.payload
|
86
|
+
end
|
87
|
+
|
88
|
+
my_foo.make_something_happen
|
89
|
+
# prints:
|
90
|
+
# Something definitely happened!
|
91
|
+
# :something_happened
|
92
|
+
# Here's a payload!
|
93
|
+
```
|
94
|
+
|
95
|
+
Note that the block gets passed an "event" object, which has some attributes. See the docs for more details.
|
96
|
+
|
97
|
+
You can also make `watch` call a method:
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
class Bar
|
101
|
+
extend Emittance::Watcher
|
102
|
+
|
103
|
+
def self.greet(event)
|
104
|
+
puts 'Hello, something must have happened!'
|
105
|
+
puts event.identifier.inspect
|
106
|
+
puts event.payload
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
Bar.watch :something_happened, :greet
|
111
|
+
|
112
|
+
my_foo.make_something_happen
|
113
|
+
# prints:
|
114
|
+
# Hello, something must have happened!
|
115
|
+
# :something_happened
|
116
|
+
# Here's a payload!
|
117
|
+
```
|
118
|
+
|
119
|
+
Those are the basics--for more info, check the docs!
|
32
120
|
|
33
121
|
## Development
|
34
122
|
|
@@ -38,4 +126,4 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
38
126
|
|
39
127
|
## Contributing
|
40
128
|
|
41
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
129
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/aastronautss/emittance.
|
data/lib/emittance/action.rb
CHANGED
@@ -1,199 +1,192 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
# However, this can easily just become a proxy for the same antipattern it was made to solve. We might wind
|
29
|
-
# +#call+ method like the following:
|
30
|
-
#
|
31
|
-
# class
|
32
|
-
# # ...
|
33
|
-
#
|
34
|
-
# def call
|
35
|
-
# do_stuff
|
36
|
-
# do_stuff_to_another_object
|
37
|
-
# do_stuff_to_something_else
|
38
|
-
# do_stuff_to_yet_another_thing
|
39
|
-
# end
|
40
|
-
#
|
41
|
-
# # ...
|
42
|
-
# end
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
#
|
59
|
-
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
#
|
66
|
-
#
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
#
|
79
|
-
#
|
80
|
-
#
|
81
|
-
#
|
82
|
-
#
|
83
|
-
#
|
84
|
-
#
|
85
|
-
#
|
86
|
-
#
|
87
|
-
#
|
88
|
-
#
|
89
|
-
#
|
90
|
-
#
|
91
|
-
#
|
92
|
-
#
|
93
|
-
#
|
94
|
-
#
|
95
|
-
# Next, we
|
96
|
-
#
|
97
|
-
#
|
98
|
-
#
|
99
|
-
#
|
100
|
-
#
|
101
|
-
#
|
102
|
-
#
|
103
|
-
#
|
104
|
-
#
|
105
|
-
#
|
106
|
-
#
|
107
|
-
#
|
108
|
-
#
|
109
|
-
#
|
110
|
-
#
|
111
|
-
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
117
|
-
|
118
|
-
#
|
119
|
-
|
120
|
-
#
|
121
|
-
#
|
122
|
-
|
123
|
-
#
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
#
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
class NoHandlerMethodError < StandardError; end
|
140
|
-
|
141
|
-
# @private
|
142
|
-
class << self
|
143
|
-
def included(action_klass)
|
144
|
-
handler_klass_name = Emittance::Action.handler_klass_name(action_klass)
|
145
|
-
handler_klass = Emittance::Action.find_or_create_klass(handler_klass_name)
|
146
|
-
|
147
|
-
action_klass.class_eval do
|
148
|
-
extend Emittance::Emitter
|
149
|
-
|
150
|
-
class << self
|
151
|
-
# @private
|
152
|
-
def method_added(method_name)
|
153
|
-
emitting_method = Emittance::Action::EMITTING_METHOD
|
154
|
-
emits_on method_name if method_name == emitting_method
|
155
|
-
super
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Emittance
|
4
|
+
##
|
5
|
+
# Consider the usual "Service Object" pattern:
|
6
|
+
#
|
7
|
+
# class Foo
|
8
|
+
# def assign
|
9
|
+
# FooAssignment.new(self).call
|
10
|
+
# end
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# class FooAssignment
|
14
|
+
# attr_reader :assignable
|
15
|
+
#
|
16
|
+
# def initialize(assignable)
|
17
|
+
# @assignable = assignable
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# def call
|
21
|
+
# do_stuff
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# # ...
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# There are variations on this pattern, the idea is that the service object represents something that your application
|
28
|
+
# is doing. However, this can easily just become a proxy for the same antipattern it was made to solve. We might wind
|
29
|
+
# up with a +#call+ method like the following:
|
30
|
+
#
|
31
|
+
# class FooAssignment
|
32
|
+
# # ...
|
33
|
+
#
|
34
|
+
# def call
|
35
|
+
# do_stuff
|
36
|
+
# do_stuff_to_another_object
|
37
|
+
# do_stuff_to_something_else
|
38
|
+
# do_stuff_to_yet_another_thing
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# # ...
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# We can use the +Emittance+ core features to prune those method calls:
|
45
|
+
#
|
46
|
+
# class FooAssignment
|
47
|
+
# extend Emittance::Emitter
|
48
|
+
#
|
49
|
+
# # ...
|
50
|
+
#
|
51
|
+
# def call
|
52
|
+
# do_stuff
|
53
|
+
# emit :foo_assignment
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# # ...
|
57
|
+
# end
|
58
|
+
#
|
59
|
+
# +Emittance::Action+ provides a shortcut for this. Just mix it in and implement +#call+! This allows us to keep the
|
60
|
+
# expressitivity that a Service Object is made to provide, while preventing us from having to give such an object too
|
61
|
+
# many responsibilities.
|
62
|
+
#
|
63
|
+
# == Usage
|
64
|
+
#
|
65
|
+
# First, define a class and include this module:
|
66
|
+
#
|
67
|
+
# class FooAssignment
|
68
|
+
# include Emittance::Action
|
69
|
+
#
|
70
|
+
# attr_reader :assignable
|
71
|
+
#
|
72
|
+
# def initialize(assignable)
|
73
|
+
# @assignable = assignable
|
74
|
+
# end
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# Next, we'll implement the +#call+ instance method. +Emittance::Action+ will take care of the dirty work for us:
|
78
|
+
#
|
79
|
+
# class FooAssignment
|
80
|
+
# # ...
|
81
|
+
#
|
82
|
+
# def call
|
83
|
+
# do_one_and_i_mean_only_one_thing
|
84
|
+
# end
|
85
|
+
#
|
86
|
+
# # ...
|
87
|
+
# end
|
88
|
+
#
|
89
|
+
# From here, your code should be able to run without error! You might notice, though, that a mysterious class will
|
90
|
+
# have been defined after loading this file.
|
91
|
+
#
|
92
|
+
# defined? FooAssignmentHandler
|
93
|
+
# => "constant"
|
94
|
+
#
|
95
|
+
# Next, we can open up this class to implement the event handler. +Emittance+ will look for a method called
|
96
|
+
# +#handle_call+, and invoke it whenever, in this example, +FooAssignment#call+ is called.
|
97
|
+
#
|
98
|
+
# class FooAssignmentHandler
|
99
|
+
# def handle_call
|
100
|
+
# notify_someone(action)
|
101
|
+
# end
|
102
|
+
#
|
103
|
+
# # ...
|
104
|
+
# end
|
105
|
+
#
|
106
|
+
# The "Action" object is stored as the instance variable +@action+, made available with a getter class +#action+. This
|
107
|
+
# will allow us to access its data and make decisions based on it.
|
108
|
+
#
|
109
|
+
# Now, this seems like we're passing the buck of all that control flow to yet another object, but this pattern has
|
110
|
+
# several advantages. First, we can disable +Emittance+ at will, so if we ever want to shut +FooAssignment+ actions
|
111
|
+
# off from their listeners, that is always an option to us. Second, to address the concern raised at the beginning of
|
112
|
+
# this paragraph, this paradigm puts us into the mindset of spreading the flow of our program out across multiple
|
113
|
+
# action/handler pairs, allowing us to think more clearly about what our code is doing.
|
114
|
+
#
|
115
|
+
# One possible disadvantage of this pattern is that it suggests a one-to-one pairing between events and handlers.
|
116
|
+
#
|
117
|
+
module Action
|
118
|
+
# Name of the method that will emit an event when invoked.
|
119
|
+
EMITTING_METHOD = :call
|
120
|
+
# Name of the method that will be invoked when the handler class captures an event.
|
121
|
+
HANDLER_METHOD_NAME = "handle_#{EMITTING_METHOD}".to_sym
|
122
|
+
|
123
|
+
# @private
|
124
|
+
class << self
|
125
|
+
def included(action_klass)
|
126
|
+
handler_klass_name = Emittance::Action.handler_klass_name(action_klass)
|
127
|
+
handler_klass = Emittance::Action.find_or_create_klass(handler_klass_name)
|
128
|
+
|
129
|
+
action_klass.class_eval do
|
130
|
+
extend Emittance::Emitter
|
131
|
+
|
132
|
+
class << self
|
133
|
+
# @private
|
134
|
+
def method_added(method_name)
|
135
|
+
emitting_method = Emittance::Action::EMITTING_METHOD
|
136
|
+
emits_on method_name if method_name == emitting_method
|
137
|
+
super
|
138
|
+
end
|
156
139
|
end
|
157
140
|
end
|
158
|
-
end
|
159
141
|
|
160
|
-
|
161
|
-
|
142
|
+
handler_klass.class_eval do
|
143
|
+
attr_reader :action
|
162
144
|
|
163
|
-
|
145
|
+
extend Emittance::Watcher
|
164
146
|
|
165
|
-
|
166
|
-
|
167
|
-
|
147
|
+
def initialize(action_obj)
|
148
|
+
@action = action_obj
|
149
|
+
end
|
168
150
|
|
169
|
-
|
170
|
-
|
171
|
-
|
151
|
+
watch Emittance::Action.emitting_event_name(action_klass) do |event|
|
152
|
+
handler_obj = new(event.emitter)
|
153
|
+
handler_method_name = Emittance::Action::HANDLER_METHOD_NAME
|
172
154
|
|
173
|
-
|
174
|
-
|
155
|
+
if handler_obj.respond_to? handler_method_name
|
156
|
+
handler_obj.send handler_method_name
|
157
|
+
end
|
175
158
|
end
|
176
159
|
end
|
177
160
|
end
|
178
|
-
end
|
179
161
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
162
|
+
# @private
|
163
|
+
def handler_klass_name(action_klass)
|
164
|
+
"#{action_klass}Handler"
|
165
|
+
end
|
184
166
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
167
|
+
# @private
|
168
|
+
def emitting_event_name(action_klass)
|
169
|
+
Emittance::Emitter.emitting_method_event(action_klass, Emittance::Action::EMITTING_METHOD)
|
170
|
+
end
|
189
171
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
172
|
+
# @private
|
173
|
+
def find_or_create_klass(klass_name)
|
174
|
+
unless Object.const_defined? klass_name
|
175
|
+
set_namespaced_constant_by_name klass_name, Class.new
|
176
|
+
end
|
177
|
+
|
178
|
+
Object.const_get klass_name
|
194
179
|
end
|
195
180
|
|
196
|
-
|
181
|
+
private
|
182
|
+
|
183
|
+
def set_namespaced_constant_by_name(const_name, obj)
|
184
|
+
names = const_name.split('::')
|
185
|
+
names.shift if names.size > 1 && names.first.empty?
|
186
|
+
|
187
|
+
namespace = names.size == 1 ? Object : Object.const_get(names[0...-1].join('::'))
|
188
|
+
namespace.const_set names.last, obj
|
189
|
+
end
|
197
190
|
end
|
198
191
|
end
|
199
192
|
end
|