light-service 0.5.1 → 0.5.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/README.md +2 -2
- data/RELEASES.md +3 -0
- data/lib/light-service.rb +1 -1
- data/lib/light-service/action.rb +10 -9
- data/lib/light-service/context/key_verifier.rb +114 -0
- data/lib/light-service/errors.rb +1 -0
- data/lib/light-service/version.rb +1 -1
- data/spec/action_expected_keys_spec.rb +15 -0
- data/spec/action_promised_keys_spec.rb +16 -1
- data/spec/test_doubles.rb +37 -0
- metadata +17 -17
- data/lib/light-service/context_key_verifier.rb +0 -48
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cce43f62b668f6fa04385c772ca0d006b9e92ca0
|
4
|
+
data.tar.gz: 3d246a1c22bc6dfa9afef1c64d77c1b15b16618b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c00210b56fb1be0cf27ac8c415f421421902088443ed8919d48ee600f22446e8d2b007586b5a4fae553fe39e11092589face9df3950e6e638f5e1a7fa524a81
|
7
|
+
data.tar.gz: 4171398c9f082dae55888485c98e7fe0d335cd0bd527c488b095921055b05659ab1495b33be899b1460839ac41783d902d43121c074276e94c8670481646dae9
|
data/README.md
CHANGED
@@ -147,8 +147,8 @@ I gave a [talk at RailsConf 2013](http://www.adomokos.com/2013/06/simple-and-ele
|
|
147
147
|
simple and elegant Rails code where I told the story of how LightService was extracted from the projects I had worked on.
|
148
148
|
|
149
149
|
## Expects and Promises
|
150
|
-
|
151
|
-
`expects` describes what keys it needs to execute and `promises` makes sure the keys are in the context after the
|
150
|
+
The `expects` and `promises` macros are rules for the inputs/outputs of an action.
|
151
|
+
`expects` describes what keys it needs to execute, and `promises` makes sure the keys are in the context after the
|
152
152
|
action is reduced. If either of them are violated, a custom exception is thrown.
|
153
153
|
|
154
154
|
This is how it's used:
|
data/RELEASES.md
CHANGED
data/lib/light-service.rb
CHANGED
@@ -6,7 +6,7 @@ require 'light-service/errors'
|
|
6
6
|
require 'light-service/configuration'
|
7
7
|
require 'light-service/localization_adapter'
|
8
8
|
require 'light-service/context'
|
9
|
-
require 'light-service/
|
9
|
+
require 'light-service/context/key_verifier'
|
10
10
|
require 'light-service/organizer/with_reducer'
|
11
11
|
require 'light-service/organizer/with_reducer_log_decorator'
|
12
12
|
require 'light-service/organizer/with_reducer_factory'
|
data/lib/light-service/action.rb
CHANGED
@@ -25,28 +25,25 @@ module LightService
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def executed
|
28
|
-
define_singleton_method
|
28
|
+
define_singleton_method :execute do |context = {}|
|
29
29
|
action_context = create_action_context(context)
|
30
30
|
return action_context if action_context.stop_processing?
|
31
31
|
|
32
32
|
# Store the action within the context
|
33
33
|
action_context.current_action = self
|
34
34
|
|
35
|
-
Context::KeyVerifier.
|
35
|
+
Context::KeyVerifier.verify_keys(action_context) do
|
36
|
+
action_context.define_accessor_methods_for_keys(all_keys)
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
yield(action_context)
|
41
|
-
|
42
|
-
Context::KeyVerifier.verify_promised_keys_are_in_context(action_context)
|
38
|
+
yield(action_context)
|
39
|
+
end
|
43
40
|
end
|
44
41
|
end
|
45
42
|
|
46
43
|
def rolled_back
|
47
44
|
raise "`rolled_back` macro can not be invoked again" if self.respond_to?(:rollback)
|
48
45
|
|
49
|
-
define_singleton_method
|
46
|
+
define_singleton_method :rollback do |context = {}|
|
50
47
|
yield(context)
|
51
48
|
|
52
49
|
context
|
@@ -64,6 +61,10 @@ module LightService
|
|
64
61
|
LightService::Context.make(context)
|
65
62
|
end
|
66
63
|
|
64
|
+
def all_keys
|
65
|
+
expected_keys + promised_keys
|
66
|
+
end
|
67
|
+
|
67
68
|
end
|
68
69
|
end
|
69
70
|
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module LightService; class Context
|
2
|
+
class KeyVerifier
|
3
|
+
attr_reader :context, :action
|
4
|
+
|
5
|
+
def initialize(context)
|
6
|
+
@context = context
|
7
|
+
@action = context.current_action
|
8
|
+
end
|
9
|
+
|
10
|
+
def are_all_keys_in_context?(keys)
|
11
|
+
not_found_keys = keys_not_found(keys)
|
12
|
+
!not_found_keys.any?
|
13
|
+
end
|
14
|
+
|
15
|
+
def keys_not_found(keys)
|
16
|
+
keys ||= context.keys
|
17
|
+
keys - context.keys
|
18
|
+
end
|
19
|
+
|
20
|
+
def format_keys(keys)
|
21
|
+
keys.map { |k| ":#{k}"}.join(', ')
|
22
|
+
end
|
23
|
+
|
24
|
+
def error_message
|
25
|
+
"#{type_name} #{format_keys(keys_not_found(keys))} to be in the context during #{action}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def throw_error_predicate(keys)
|
29
|
+
raise NotImplementedError, 'Sorry, you have to override length'
|
30
|
+
end
|
31
|
+
|
32
|
+
def verify
|
33
|
+
return context if context.failure?
|
34
|
+
|
35
|
+
if throw_error_predicate(keys)
|
36
|
+
Configuration.logger.error error_message
|
37
|
+
fail error_to_throw, error_message
|
38
|
+
end
|
39
|
+
|
40
|
+
context
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.verify_keys(context, &block)
|
44
|
+
ReservedKeysVerifier.new(context).verify
|
45
|
+
ExpectedKeyVerifier.new(context).verify
|
46
|
+
|
47
|
+
block.call
|
48
|
+
|
49
|
+
PromisedKeyVerifier.new(context).verify
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class ExpectedKeyVerifier < KeyVerifier
|
54
|
+
def type_name
|
55
|
+
"expected"
|
56
|
+
end
|
57
|
+
|
58
|
+
def keys
|
59
|
+
action.expected_keys
|
60
|
+
end
|
61
|
+
|
62
|
+
def error_to_throw
|
63
|
+
ExpectedKeysNotInContextError
|
64
|
+
end
|
65
|
+
|
66
|
+
def throw_error_predicate(keys)
|
67
|
+
!are_all_keys_in_context?(keys)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class PromisedKeyVerifier < KeyVerifier
|
72
|
+
def type_name
|
73
|
+
"promised"
|
74
|
+
end
|
75
|
+
|
76
|
+
def keys
|
77
|
+
action.promised_keys
|
78
|
+
end
|
79
|
+
|
80
|
+
def error_to_throw
|
81
|
+
PromisedKeysNotInContextError
|
82
|
+
end
|
83
|
+
|
84
|
+
def throw_error_predicate(keys)
|
85
|
+
!are_all_keys_in_context?(keys)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class ReservedKeysVerifier < KeyVerifier
|
90
|
+
def violated_keys
|
91
|
+
(action.promised_keys + action.expected_keys) & reserved_keys
|
92
|
+
end
|
93
|
+
|
94
|
+
def error_message
|
95
|
+
"promised or expected keys cannot be a reserved key: [#{format_keys(violated_keys)}]"
|
96
|
+
end
|
97
|
+
|
98
|
+
def keys
|
99
|
+
violated_keys
|
100
|
+
end
|
101
|
+
|
102
|
+
def error_to_throw
|
103
|
+
ReservedKeysInContextError
|
104
|
+
end
|
105
|
+
|
106
|
+
def throw_error_predicate(keys)
|
107
|
+
keys.any?
|
108
|
+
end
|
109
|
+
|
110
|
+
def reserved_keys
|
111
|
+
[:message, :error_code, :current_action].freeze
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end; end
|
data/lib/light-service/errors.rb
CHANGED
@@ -32,4 +32,19 @@ describe ":expects macro" do
|
|
32
32
|
expect(resulting_context[:milk_tea]).to eq("black - full cream - with dark chocolate")
|
33
33
|
end
|
34
34
|
|
35
|
+
context "when a reserved key is listed as an expected key" do
|
36
|
+
it "raises an error indicating a reserved key is expected" do
|
37
|
+
exception_error_text = "promised or expected keys cannot be a reserved key: [:message]"
|
38
|
+
expect {
|
39
|
+
TestDoubles::MakesTeaExpectingReservedKey.execute(:tea => "black", :message => "no no")
|
40
|
+
}.to raise_error(LightService::ReservedKeysInContextError, exception_error_text)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "raises an error indicating that multiple reserved keys are expected" do
|
44
|
+
exception_error_text = "promised or expected keys cannot be a reserved key: [:message, :error_code, :current_action]"
|
45
|
+
expect {
|
46
|
+
TestDoubles::MakesTeaExpectingMultipleReservedKeys.execute(:tea => "black", :message => "no no", :error_code => 1, :current_action => "update")
|
47
|
+
}.to raise_error(LightService::ReservedKeysInContextError, exception_error_text)
|
48
|
+
end
|
49
|
+
end
|
35
50
|
end
|
@@ -77,6 +77,22 @@ describe ":promises macro" do
|
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
|
+
context "when a reserved key is listed as a promised key" do
|
81
|
+
it "raises an error indicating a reserved key has been promised" do
|
82
|
+
exception_error_text = "promised or expected keys cannot be a reserved key: [:message]"
|
83
|
+
expect {
|
84
|
+
TestDoubles::MakesTeaPromisingReservedKey.execute(:tea => "black")
|
85
|
+
}.to raise_error(LightService::ReservedKeysInContextError, exception_error_text)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "raises an error indicating that multiple reserved keys have been promised" do
|
89
|
+
exception_error_text = "promised or expected keys cannot be a reserved key: [:message, :error_code, :current_action]"
|
90
|
+
expect {
|
91
|
+
TestDoubles::MakesTeaPromisingMultipleReservedKeys.execute(:tea => "black")
|
92
|
+
}.to raise_error(LightService::ReservedKeysInContextError, exception_error_text)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
80
96
|
it "can collect promised keys when the `promised` macro is called multiple times" do
|
81
97
|
resulting_context = TestDoubles::MultiplePromisesAction.execute(
|
82
98
|
:coffee => "espresso",
|
@@ -85,5 +101,4 @@ describe ":promises macro" do
|
|
85
101
|
expect(resulting_context.cappuccino).to eq("Cappucino needs espresso and a little milk")
|
86
102
|
expect(resulting_context.latte).to eq("Latte needs espresso and a lot of milk")
|
87
103
|
end
|
88
|
-
|
89
104
|
end
|
data/spec/test_doubles.rb
CHANGED
@@ -176,4 +176,41 @@ module TestDoubles
|
|
176
176
|
end
|
177
177
|
end
|
178
178
|
|
179
|
+
class MakesTeaExpectingReservedKey
|
180
|
+
include LightService::Action
|
181
|
+
expects :tea, :message
|
182
|
+
|
183
|
+
executed do |context|
|
184
|
+
context.product = context.number + 3
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
class MakesTeaExpectingMultipleReservedKeys
|
189
|
+
include LightService::Action
|
190
|
+
expects :tea, :message, :error_code, :current_action
|
191
|
+
|
192
|
+
executed do |context|
|
193
|
+
context.product = context.number + 3
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
class MakesTeaPromisingReservedKey
|
198
|
+
include LightService::Action
|
199
|
+
expects :tea
|
200
|
+
promises :product, :message
|
201
|
+
|
202
|
+
executed do |context|
|
203
|
+
context.product = context.number + 3
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
class MakesTeaPromisingMultipleReservedKeys
|
208
|
+
include LightService::Action
|
209
|
+
expects :tea
|
210
|
+
promises :product, :message, :error_code, :current_action
|
211
|
+
|
212
|
+
executed do |context|
|
213
|
+
context.product = context.number + 3
|
214
|
+
end
|
215
|
+
end
|
179
216
|
end
|
metadata
CHANGED
@@ -1,69 +1,69 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: light-service
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Attila Domokos
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-04-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '4.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '4.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rspec
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ~>
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '3.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ~>
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '3.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec-its
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ~>
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '1.0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ~>
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '1.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: simplecov
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ~>
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: 0.7.1
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ~>
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 0.7.1
|
69
69
|
- !ruby/object:Gem::Dependency
|
@@ -87,9 +87,9 @@ executables: []
|
|
87
87
|
extensions: []
|
88
88
|
extra_rdoc_files: []
|
89
89
|
files:
|
90
|
-
-
|
91
|
-
-
|
92
|
-
-
|
90
|
+
- .gitignore
|
91
|
+
- .rspec
|
92
|
+
- .travis.yml
|
93
93
|
- Gemfile
|
94
94
|
- LICENSE
|
95
95
|
- README.md
|
@@ -99,7 +99,7 @@ files:
|
|
99
99
|
- lib/light-service/action.rb
|
100
100
|
- lib/light-service/configuration.rb
|
101
101
|
- lib/light-service/context.rb
|
102
|
-
- lib/light-service/
|
102
|
+
- lib/light-service/context/key_verifier.rb
|
103
103
|
- lib/light-service/errors.rb
|
104
104
|
- lib/light-service/localization_adapter.rb
|
105
105
|
- lib/light-service/organizer.rb
|
@@ -142,17 +142,17 @@ require_paths:
|
|
142
142
|
- lib
|
143
143
|
required_ruby_version: !ruby/object:Gem::Requirement
|
144
144
|
requirements:
|
145
|
-
- -
|
145
|
+
- - '>='
|
146
146
|
- !ruby/object:Gem::Version
|
147
147
|
version: '0'
|
148
148
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
|
-
- -
|
150
|
+
- - '>='
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '0'
|
153
153
|
requirements: []
|
154
154
|
rubyforge_project:
|
155
|
-
rubygems_version: 2.
|
155
|
+
rubygems_version: 2.0.14
|
156
156
|
signing_key:
|
157
157
|
specification_version: 4
|
158
158
|
summary: A service skeleton with an emphasis on simplicity
|
@@ -1,48 +0,0 @@
|
|
1
|
-
module LightService
|
2
|
-
class Context
|
3
|
-
class KeyVerifier
|
4
|
-
class << self
|
5
|
-
def verify_expected_keys_are_in_context(context)
|
6
|
-
action = context.current_action
|
7
|
-
|
8
|
-
verify_keys_are_in_context(context, action.expected_keys) do |not_found_keys|
|
9
|
-
error_message = "expected #{format_keys(not_found_keys)} to be in the context during #{action}"
|
10
|
-
|
11
|
-
Configuration.logger.error error_message
|
12
|
-
fail ExpectedKeysNotInContextError, error_message
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def verify_promised_keys_are_in_context(context)
|
17
|
-
return context if context.failure?
|
18
|
-
|
19
|
-
action = context.current_action
|
20
|
-
|
21
|
-
verify_keys_are_in_context(context, action.promised_keys) do |not_found_keys|
|
22
|
-
error_message = "promised #{format_keys(not_found_keys)} to be in the context during #{action}"
|
23
|
-
|
24
|
-
Configuration.logger.error error_message
|
25
|
-
fail PromisedKeysNotInContextError, error_message
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def verify_keys_are_in_context(context, keys)
|
32
|
-
keys ||= context.keys
|
33
|
-
|
34
|
-
not_found_keys = keys - context.keys
|
35
|
-
unless not_found_keys.empty?
|
36
|
-
yield not_found_keys
|
37
|
-
end
|
38
|
-
|
39
|
-
context
|
40
|
-
end
|
41
|
-
|
42
|
-
def format_keys(keys)
|
43
|
-
keys.map { |k| ":#{k}"}.join(', ')
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|