light-service 0.5.2 → 0.6.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/README.md +54 -14
- data/RELEASES.md +4 -0
- data/lib/light-service/action.rb +7 -2
- data/lib/light-service/context.rb +30 -11
- data/lib/light-service/context/key_verifier.rb +6 -6
- data/lib/light-service/organizer.rb +13 -10
- data/lib/light-service/organizer/with_reducer.rb +4 -3
- data/lib/light-service/version.rb +1 -1
- data/spec/acceptance/include_warning_spec.rb +26 -0
- data/spec/acceptance/message_localization_spec.rb +1 -1
- data/spec/acceptance/rollback_spec.rb +4 -4
- data/spec/action_expects_and_promises_spec.rb +5 -5
- data/spec/action_promised_keys_spec.rb +4 -4
- data/spec/context_spec.rb +27 -0
- data/spec/organizer_key_aliases_spec.rb +27 -0
- data/spec/organizer_spec.rb +49 -0
- data/spec/sample/tax/calculates_order_tax_action.rb +1 -1
- data/spec/sample/tax/calculates_tax.rb +2 -1
- data/spec/sample/tax/looks_up_tax_percentage_action.rb +1 -1
- data/spec/sample/tax/provides_free_shipping_action.rb +1 -1
- data/spec/spec_helper.rb +1 -0
- data/spec/test_doubles.rb +55 -18
- metadata +20 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 55ba3cb29c4ce4e3e59c3129bc8baf4287efe0c2
|
4
|
+
data.tar.gz: ba0a1fc827bee6a92346c886948c024753796880
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 64a014abda6e16cd5d1c4a62ea188b576a8878e46304f90d5768666f5e944869fc84814c250dfc986b7be67eb7c76fd736d74363171445f5401b5457704d36d4
|
7
|
+
data.tar.gz: 77d665f3fcd08eb79c598871fe1c97e6bba9e34b773fe2b083ed8001fa356c383a13fba2195157d187d84110c57fc929f0de81874de07207dfa529b821319ed2
|
data/README.md
CHANGED
@@ -66,7 +66,7 @@ This is how the organizer and actions interact with eachother:
|
|
66
66
|
|
67
67
|
```ruby
|
68
68
|
class CalculatesTax
|
69
|
-
|
69
|
+
extend LightService::Organizer
|
70
70
|
|
71
71
|
def self.for_order(order)
|
72
72
|
with(:order => order).reduce(
|
@@ -78,7 +78,7 @@ class CalculatesTax
|
|
78
78
|
end
|
79
79
|
|
80
80
|
class LooksUpTaxPercentageAction
|
81
|
-
|
81
|
+
extend LightService::Action
|
82
82
|
expects :order
|
83
83
|
promises :tax_percentage
|
84
84
|
|
@@ -104,7 +104,7 @@ class LooksUpTaxPercentageAction
|
|
104
104
|
end
|
105
105
|
|
106
106
|
class CalculatesOrderTaxAction
|
107
|
-
|
107
|
+
extend ::LightService::Action
|
108
108
|
expects :order, :tax_percentage
|
109
109
|
|
110
110
|
executed do |context|
|
@@ -114,7 +114,7 @@ class CalculatesOrderTaxAction
|
|
114
114
|
end
|
115
115
|
|
116
116
|
class ProvidesFreeShippingAction
|
117
|
-
|
117
|
+
extend LightService::Action
|
118
118
|
expects :order
|
119
119
|
|
120
120
|
executed do |context|
|
@@ -154,7 +154,7 @@ action is reduced. If either of them are violated, a custom exception is thrown.
|
|
154
154
|
This is how it's used:
|
155
155
|
```ruby
|
156
156
|
class FooAction
|
157
|
-
|
157
|
+
extend LightService::Action
|
158
158
|
expects :baz
|
159
159
|
promises :bar
|
160
160
|
|
@@ -172,7 +172,7 @@ makes it available to you through a reader. You can refactor the action like thi
|
|
172
172
|
|
173
173
|
```ruby
|
174
174
|
class FooAction
|
175
|
-
|
175
|
+
extend LightService::Action
|
176
176
|
expects :baz
|
177
177
|
promises :bar
|
178
178
|
|
@@ -188,7 +188,7 @@ you use the accessor with the same name. The code above can be further simplifie
|
|
188
188
|
|
189
189
|
```ruby
|
190
190
|
class FooAction
|
191
|
-
|
191
|
+
extend LightService::Action
|
192
192
|
expects :baz
|
193
193
|
promises :bar
|
194
194
|
|
@@ -200,6 +200,46 @@ end
|
|
200
200
|
|
201
201
|
Take a look at [this spec](spec/action_expects_and_promises_spec.rb) to see the refactoring in action.
|
202
202
|
|
203
|
+
## Key Aliases
|
204
|
+
The `aliases` macro sets up pairs of keys and aliases in an Organizer. Actions can access the context using the aliases.
|
205
|
+
|
206
|
+
This allows you to put together existing Actions from different sources and have them work together without having to modify their code. Aliases will work with or without Action `expects`.
|
207
|
+
|
208
|
+
Say for example you have actions `AnAction` and `AnotherAction` that you've used in previous projects. `AnAction` provides `:my_key` but `AnotherAction` needs to use that value but expects `:key_alias`. You can use them together in an organizer like so:
|
209
|
+
|
210
|
+
```ruby
|
211
|
+
class AnOrganizer
|
212
|
+
extend LightService::Organizer
|
213
|
+
|
214
|
+
aliases my_key: :key_alias
|
215
|
+
|
216
|
+
def self.for_order(order)
|
217
|
+
with(:order => order).reduce(
|
218
|
+
AnAction,
|
219
|
+
AnotherAction,
|
220
|
+
)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
class AnAction
|
225
|
+
extend LightService::Action
|
226
|
+
promises :my_key
|
227
|
+
|
228
|
+
executed do |context|
|
229
|
+
context.my_key = "value"
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
class AnotherAction
|
234
|
+
extend LightService::Action
|
235
|
+
expects :key_alias
|
236
|
+
|
237
|
+
executed do |context|
|
238
|
+
context.key_alias # => "value"
|
239
|
+
end
|
240
|
+
end
|
241
|
+
```
|
242
|
+
|
203
243
|
## Logging
|
204
244
|
|
205
245
|
Enable LightService's logging to better understand what goes on within the series of actions,
|
@@ -266,7 +306,7 @@ Normally, when something goes wrong in your actions, you fail the process by set
|
|
266
306
|
|
267
307
|
```ruby
|
268
308
|
class FooAction
|
269
|
-
|
309
|
+
extend LightService::Action
|
270
310
|
|
271
311
|
executed do |context|
|
272
312
|
context.fail!("I don't like what happened here.")
|
@@ -280,7 +320,7 @@ or in the actions.
|
|
280
320
|
|
281
321
|
```ruby
|
282
322
|
class FooAction
|
283
|
-
|
323
|
+
extend LightService::Action
|
284
324
|
|
285
325
|
executed do |context|
|
286
326
|
unless (service_call.success?)
|
@@ -305,7 +345,7 @@ the `rolled_back` macro.
|
|
305
345
|
|
306
346
|
```ruby
|
307
347
|
class SaveEntities
|
308
|
-
|
348
|
+
extend LightService::Action
|
309
349
|
expects :user
|
310
350
|
|
311
351
|
executed do |context|
|
@@ -323,7 +363,7 @@ was triggered.
|
|
323
363
|
|
324
364
|
```ruby
|
325
365
|
class CallExternalApi
|
326
|
-
|
366
|
+
extend LightService::Action
|
327
367
|
|
328
368
|
executed do |context|
|
329
369
|
api_call_result = SomeAPI.save_user(context.user)
|
@@ -345,7 +385,7 @@ By default LightService provides a mechanism for easily translating your error o
|
|
345
385
|
|
346
386
|
```ruby
|
347
387
|
class FooAction
|
348
|
-
|
388
|
+
extend LightService::Action
|
349
389
|
|
350
390
|
executed do |context|
|
351
391
|
unless service_call.success?
|
@@ -363,7 +403,7 @@ This also works with nested classes via the ActiveSupport `#underscore` method,
|
|
363
403
|
```ruby
|
364
404
|
module PaymentGateway
|
365
405
|
class CaptureFunds
|
366
|
-
|
406
|
+
extend LightService::Action
|
367
407
|
|
368
408
|
executed do |context|
|
369
409
|
if api_service.failed?
|
@@ -382,7 +422,7 @@ If you need to provide custom variables for interpolation during localization, p
|
|
382
422
|
```ruby
|
383
423
|
module PaymentGateway
|
384
424
|
class CaptureFunds
|
385
|
-
|
425
|
+
extend LightService::Action
|
386
426
|
|
387
427
|
executed do |context|
|
388
428
|
if api_service.failed?
|
data/RELEASES.md
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
A brief list of new features and changes introduced with the specified version.
|
2
2
|
|
3
|
+
### 0.6.0
|
4
|
+
* Using [extend](https://github.com/adomokos/light-service/pull/64) for using class methods in Actions and Organizers
|
5
|
+
* Setting [key aliases](https://github.com/adomokos/light-service/pull/69) for the Context from the Organizer
|
6
|
+
|
3
7
|
### 0.5.2
|
4
8
|
* Guarding context keys against the reserved keys the context needs to operate.
|
5
9
|
|
data/lib/light-service/action.rb
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
module LightService
|
2
2
|
module Action
|
3
3
|
|
4
|
+
def self.extended(base_class)
|
5
|
+
base_class.extend Macros
|
6
|
+
end
|
7
|
+
|
4
8
|
def self.included(base_class)
|
9
|
+
ActiveSupport::Deprecation.warn "including LightService::Action is deprecated. Please use `extend LightService::Action` instead"
|
5
10
|
base_class.extend Macros
|
6
11
|
end
|
7
12
|
|
@@ -32,7 +37,7 @@ module LightService
|
|
32
37
|
# Store the action within the context
|
33
38
|
action_context.current_action = self
|
34
39
|
|
35
|
-
Context::KeyVerifier.verify_keys(action_context) do
|
40
|
+
Context::KeyVerifier.verify_keys(action_context, self) do
|
36
41
|
action_context.define_accessor_methods_for_keys(all_keys)
|
37
42
|
|
38
43
|
yield(action_context)
|
@@ -64,7 +69,7 @@ module LightService
|
|
64
69
|
def all_keys
|
65
70
|
expected_keys + promised_keys
|
66
71
|
end
|
67
|
-
|
68
72
|
end
|
73
|
+
|
69
74
|
end
|
70
75
|
end
|
@@ -5,7 +5,7 @@ module LightService
|
|
5
5
|
end
|
6
6
|
|
7
7
|
class Context < Hash
|
8
|
-
attr_accessor :
|
8
|
+
attr_accessor :message, :error_code, :current_action
|
9
9
|
|
10
10
|
def initialize(context={}, outcome=Outcomes::SUCCESS, message='', error_code=nil)
|
11
11
|
@outcome, @message, @error_code = outcome, message, error_code
|
@@ -19,8 +19,12 @@ module LightService
|
|
19
19
|
raise ArgumentError, 'Argument must be Hash or LightService::Context'
|
20
20
|
end
|
21
21
|
|
22
|
-
|
23
|
-
|
22
|
+
unless context.is_a?(Context)
|
23
|
+
context = self.new(context)
|
24
|
+
end
|
25
|
+
|
26
|
+
context.set_aliases(context.delete(:_aliases)) if context[:_aliases]
|
27
|
+
context
|
24
28
|
end
|
25
29
|
|
26
30
|
def add_to_context(values)
|
@@ -39,9 +43,9 @@ module LightService
|
|
39
43
|
@skip_all
|
40
44
|
end
|
41
45
|
|
42
|
-
def
|
43
|
-
warn '`
|
44
|
-
|
46
|
+
def outcome
|
47
|
+
ActiveSupport::Deprecation.warn '`Context#outcome` attribute reader is DEPRECATED and will be removed'
|
48
|
+
@outcome
|
45
49
|
end
|
46
50
|
|
47
51
|
def succeed!(message=nil, options={})
|
@@ -49,11 +53,6 @@ module LightService
|
|
49
53
|
@outcome = Outcomes::SUCCESS
|
50
54
|
end
|
51
55
|
|
52
|
-
def set_failure!(message)
|
53
|
-
warn '`set_failure!` is DEPRECATED: please use `fail!` instead'
|
54
|
-
fail!(message)
|
55
|
-
end
|
56
|
-
|
57
56
|
def fail!(message=nil, options_or_error_code={})
|
58
57
|
options_or_error_code ||= {}
|
59
58
|
|
@@ -92,5 +91,25 @@ module LightService
|
|
92
91
|
define_singleton_method("#{key}=") { |value| self[key] = value }
|
93
92
|
end
|
94
93
|
end
|
94
|
+
|
95
|
+
def set_aliases(aliases)
|
96
|
+
@aliases = aliases
|
97
|
+
|
98
|
+
aliases.each_pair do |key, key_alias|
|
99
|
+
self[key_alias] = self[key]
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def aliases
|
104
|
+
@aliases ||= {}
|
105
|
+
end
|
106
|
+
|
107
|
+
def [](key)
|
108
|
+
super(key) || super(aliases.key(key))
|
109
|
+
end
|
110
|
+
|
111
|
+
def fetch(key, default_or_block = nil)
|
112
|
+
self[key] ||= super(key, default_or_block)
|
113
|
+
end
|
95
114
|
end
|
96
115
|
end
|
@@ -2,9 +2,9 @@ module LightService; class Context
|
|
2
2
|
class KeyVerifier
|
3
3
|
attr_reader :context, :action
|
4
4
|
|
5
|
-
def initialize(context)
|
5
|
+
def initialize(context, action)
|
6
6
|
@context = context
|
7
|
-
@action =
|
7
|
+
@action = action
|
8
8
|
end
|
9
9
|
|
10
10
|
def are_all_keys_in_context?(keys)
|
@@ -40,13 +40,13 @@ module LightService; class Context
|
|
40
40
|
context
|
41
41
|
end
|
42
42
|
|
43
|
-
def self.verify_keys(context, &block)
|
44
|
-
ReservedKeysVerifier.new(context).verify
|
45
|
-
ExpectedKeyVerifier.new(context).verify
|
43
|
+
def self.verify_keys(context, action, &block)
|
44
|
+
ReservedKeysVerifier.new(context, action).verify
|
45
|
+
ExpectedKeyVerifier.new(context, action).verify
|
46
46
|
|
47
47
|
block.call
|
48
48
|
|
49
|
-
PromisedKeyVerifier.new(context).verify
|
49
|
+
PromisedKeyVerifier.new(context, action).verify
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
@@ -1,28 +1,31 @@
|
|
1
1
|
module LightService
|
2
2
|
module Organizer
|
3
|
+
def self.extended(base_class)
|
4
|
+
base_class.extend ClassMethods
|
5
|
+
base_class.extend Macros
|
6
|
+
end
|
3
7
|
def self.included(base_class)
|
8
|
+
ActiveSupport::Deprecation.warn "including LightService::Organizer is deprecated. Please use `extend LightService::Organizer` instead"
|
4
9
|
base_class.extend ClassMethods
|
10
|
+
base_class.extend Macros
|
5
11
|
end
|
6
12
|
|
7
13
|
# In case this module is included
|
8
14
|
module ClassMethods
|
9
|
-
def with(data)
|
15
|
+
def with(data={})
|
16
|
+
data.merge!(:_aliases => @aliases) if @aliases
|
10
17
|
WithReducerFactory.make(self).with(data)
|
11
18
|
end
|
12
19
|
|
13
20
|
def reduce(*actions)
|
14
|
-
|
21
|
+
with({}).reduce(actions)
|
15
22
|
end
|
16
23
|
end
|
17
24
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
def reduce(*actions)
|
24
|
-
WithReducerFactory.make(self).with.reduce(actions)
|
25
|
+
module Macros
|
26
|
+
def aliases(key_hash)
|
27
|
+
@aliases = key_hash
|
28
|
+
end
|
25
29
|
end
|
26
|
-
|
27
30
|
end
|
28
31
|
end
|
@@ -11,14 +11,14 @@ module LightService; module Organizer
|
|
11
11
|
raise "No action(s) were provided" if actions.empty?
|
12
12
|
actions.flatten!
|
13
13
|
|
14
|
-
actions.reduce(context) do |
|
14
|
+
actions.reduce(context) do |current_context, action|
|
15
15
|
begin
|
16
|
-
result = action.execute(
|
16
|
+
result = action.execute(current_context)
|
17
17
|
rescue FailWithRollbackError
|
18
18
|
result = reduce_rollback(actions)
|
19
19
|
ensure
|
20
20
|
# For logging
|
21
|
-
yield(
|
21
|
+
yield(current_context, action) if block_given?
|
22
22
|
end
|
23
23
|
|
24
24
|
result
|
@@ -45,5 +45,6 @@ module LightService; module Organizer
|
|
45
45
|
# Reverse from the point where the fail was triggered
|
46
46
|
actions.take(index_of_current_action + 1)
|
47
47
|
end
|
48
|
+
|
48
49
|
end
|
49
50
|
end; end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'test_doubles'
|
3
|
+
|
4
|
+
describe "Including is discouraged" do
|
5
|
+
context "when including LightService::Organizer" do
|
6
|
+
it "gives warning" do
|
7
|
+
expect(ActiveSupport::Deprecation).to receive(:warn)
|
8
|
+
.with("including LightService::Organizer is deprecated. Please use `extend LightService::Organizer` instead")
|
9
|
+
|
10
|
+
class OrganizerIncludingLS
|
11
|
+
include LightService::Organizer
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "when including LightService::Action" do
|
17
|
+
it "gives warning" do
|
18
|
+
expect(ActiveSupport::Deprecation).to receive(:warn)
|
19
|
+
.with("including LightService::Action is deprecated. Please use `extend LightService::Action` instead")
|
20
|
+
|
21
|
+
class ActionIncludingLS
|
22
|
+
include LightService::Action
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -14,7 +14,7 @@ class RollbackOrganizer
|
|
14
14
|
end
|
15
15
|
|
16
16
|
class AddsOneWithRollbackAction
|
17
|
-
|
17
|
+
extend LightService::Action
|
18
18
|
expects :number
|
19
19
|
promises :number
|
20
20
|
|
@@ -32,7 +32,7 @@ class AddsOneWithRollbackAction
|
|
32
32
|
end
|
33
33
|
|
34
34
|
class AddsThreeWithRollbackAction
|
35
|
-
|
35
|
+
extend LightService::Action
|
36
36
|
expects :number
|
37
37
|
|
38
38
|
executed do |context|
|
@@ -59,7 +59,7 @@ class RollbackOrganizerWithNoRollback
|
|
59
59
|
end
|
60
60
|
|
61
61
|
class AddsThreeWithNoRollbackAction
|
62
|
-
|
62
|
+
extend LightService::Action
|
63
63
|
expects :number
|
64
64
|
|
65
65
|
executed do |context|
|
@@ -82,7 +82,7 @@ class RollbackOrganizerWithMiddleRollback
|
|
82
82
|
end
|
83
83
|
|
84
84
|
class AddsTwoActionWithRollback
|
85
|
-
|
85
|
+
extend LightService::Action
|
86
86
|
expects :number
|
87
87
|
|
88
88
|
executed do |context|
|
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
describe ":expects and :promises macros" do
|
4
4
|
describe "actions are backward compatible" do
|
5
5
|
class FooAction
|
6
|
-
|
6
|
+
extend LightService::Action
|
7
7
|
|
8
8
|
executed do |context|
|
9
9
|
baz = context.fetch :baz
|
@@ -21,7 +21,7 @@ describe ":expects and :promises macros" do
|
|
21
21
|
|
22
22
|
context "when expected keys are not in context" do
|
23
23
|
class FooNoExpectedKeyAction
|
24
|
-
|
24
|
+
extend LightService::Action
|
25
25
|
expects :baz
|
26
26
|
|
27
27
|
executed do |context|
|
@@ -40,7 +40,7 @@ describe ":expects and :promises macros" do
|
|
40
40
|
|
41
41
|
describe "expected keys" do
|
42
42
|
class FooWithReaderAction
|
43
|
-
|
43
|
+
extend LightService::Action
|
44
44
|
expects :baz
|
45
45
|
|
46
46
|
executed do |context|
|
@@ -58,7 +58,7 @@ describe ":expects and :promises macros" do
|
|
58
58
|
|
59
59
|
context "when promised keys are not in context" do
|
60
60
|
class FooNoPromisedKeyAction
|
61
|
-
|
61
|
+
extend LightService::Action
|
62
62
|
expects :baz
|
63
63
|
promises :bar
|
64
64
|
|
@@ -75,7 +75,7 @@ describe ":expects and :promises macros" do
|
|
75
75
|
|
76
76
|
describe "promised keys" do
|
77
77
|
class FooWithExpectsAndPromisesAction
|
78
|
-
|
78
|
+
extend LightService::Action
|
79
79
|
expects :baz
|
80
80
|
promises :bar
|
81
81
|
|
@@ -6,7 +6,7 @@ describe ":promises macro" do
|
|
6
6
|
context "when the promised key is not in the context" do
|
7
7
|
it "raises an ArgumentError" do
|
8
8
|
class TestDoubles::MakesCappuccinoAction1
|
9
|
-
|
9
|
+
extend LightService::Action
|
10
10
|
expects :coffee, :milk
|
11
11
|
promises :cappuccino
|
12
12
|
executed do |context|
|
@@ -22,7 +22,7 @@ describe ":promises macro" do
|
|
22
22
|
|
23
23
|
it "can fail the context without fulfilling its promise" do
|
24
24
|
class TestDoubles::MakesCappuccinoAction2
|
25
|
-
|
25
|
+
extend LightService::Action
|
26
26
|
expects :coffee, :milk
|
27
27
|
promises :cappuccino
|
28
28
|
executed do |context|
|
@@ -42,7 +42,7 @@ describe ":promises macro" do
|
|
42
42
|
context "when the promised key is in the context" do
|
43
43
|
it "can be set with an actual value" do
|
44
44
|
class TestDoubles::MakesCappuccinoAction3
|
45
|
-
|
45
|
+
extend LightService::Action
|
46
46
|
expects :coffee, :milk
|
47
47
|
promises :cappuccino
|
48
48
|
executed do |context|
|
@@ -61,7 +61,7 @@ describe ":promises macro" do
|
|
61
61
|
|
62
62
|
it "can be set with nil" do
|
63
63
|
class TestDoubles::MakesCappuccinoAction4
|
64
|
-
|
64
|
+
extend LightService::Action
|
65
65
|
expects :coffee, :milk
|
66
66
|
promises :cappuccino
|
67
67
|
executed do |context|
|
data/spec/context_spec.rb
CHANGED
@@ -145,4 +145,31 @@ describe LightService::Context do
|
|
145
145
|
expect { context.fail_with_rollback!("roll me back") }.to \
|
146
146
|
raise_error(LightService::FailWithRollbackError)
|
147
147
|
end
|
148
|
+
|
149
|
+
it "warns about the outcome attribute reader being deprecated" do
|
150
|
+
expect(ActiveSupport::Deprecation).to receive(:warn)
|
151
|
+
|
152
|
+
expect(context.outcome).to eq(::LightService::Outcomes::SUCCESS)
|
153
|
+
end
|
154
|
+
|
155
|
+
context "when aliases are included via .make" do
|
156
|
+
let(:context) do
|
157
|
+
LightService::Context.make(
|
158
|
+
:foo => "foobar",
|
159
|
+
:_aliases => aliases,
|
160
|
+
)
|
161
|
+
end
|
162
|
+
let(:aliases) { { :foo => :bar } }
|
163
|
+
|
164
|
+
it "contains the aliases" do
|
165
|
+
expect(context.aliases).to eq(aliases)
|
166
|
+
expect(context).to include(:foo, :bar)
|
167
|
+
end
|
168
|
+
|
169
|
+
it "returns the correct values for #[] and #fetch" do
|
170
|
+
expect(context[:bar]).to eq context[:foo]
|
171
|
+
expect(context.fetch(:bar)).to eq context[:foo]
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
148
175
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'test_doubles'
|
3
|
+
|
4
|
+
describe "organizer aliases macro" do
|
5
|
+
let(:organizer_with_alias) do
|
6
|
+
Class.new do
|
7
|
+
extend LightService::Organizer
|
8
|
+
|
9
|
+
aliases :promised_key => :expected_key
|
10
|
+
|
11
|
+
def self.do_something(ctx={})
|
12
|
+
with(ctx).reduce([
|
13
|
+
TestDoubles::PromisesPromisedKeyAction,
|
14
|
+
TestDoubles::ExpectsExpectedKeyAction,
|
15
|
+
])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when aliases is invoked" do
|
21
|
+
it "makes aliases available to the actions" do
|
22
|
+
result = organizer_with_alias.do_something
|
23
|
+
expect(result[:expected_key]).to eq(result[:promised_key])
|
24
|
+
expect(result.expected_key).to eq(result[:promised_key])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/spec/organizer_spec.rb
CHANGED
@@ -58,4 +58,53 @@ describe LightService::Organizer do
|
|
58
58
|
.not_to raise_error
|
59
59
|
end
|
60
60
|
end
|
61
|
+
|
62
|
+
context "when the organizer is also an action", "and the organizer rescues exceptions of its sub-actions" do
|
63
|
+
let(:organizer) do
|
64
|
+
Class.new do
|
65
|
+
extend LightService::Organizer
|
66
|
+
extend LightService::Action
|
67
|
+
|
68
|
+
executed do |ctx|
|
69
|
+
begin
|
70
|
+
with(ctx).
|
71
|
+
reduce(TestDoubles::MakesTeaPromisingKeyButRaisesException)
|
72
|
+
rescue
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
it "does not raise an error concerning a sub-action's missing keys" do
|
79
|
+
expect { organizer.execute }.not_to raise_error
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context "when aliases are declared" do
|
84
|
+
let(:organizer) do
|
85
|
+
Class.new do
|
86
|
+
extend LightService::Organizer
|
87
|
+
aliases :foo => :bar
|
88
|
+
|
89
|
+
def self.do_stuff
|
90
|
+
with.reduce(TestDoubles::AnAction)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
it "merges the aliases into the data" do
|
96
|
+
with_reducer = double(reduce: true)
|
97
|
+
|
98
|
+
allow(described_class::WithReducerFactory).to receive(:make).
|
99
|
+
and_return(with_reducer)
|
100
|
+
|
101
|
+
expect(with_reducer).to \
|
102
|
+
receive(:with).
|
103
|
+
with(hash_including(:_aliases => { :foo => :bar })).
|
104
|
+
and_return(with_reducer)
|
105
|
+
|
106
|
+
organizer.do_stuff
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
61
110
|
end
|
data/spec/spec_helper.rb
CHANGED
data/spec/test_doubles.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module TestDoubles
|
4
4
|
class AddsTwoActionWithFetch
|
5
|
-
|
5
|
+
extend LightService::Action
|
6
6
|
|
7
7
|
executed do |context|
|
8
8
|
number = context.fetch(:number, 0)
|
@@ -14,7 +14,7 @@ module TestDoubles
|
|
14
14
|
class AnotherAction; end
|
15
15
|
|
16
16
|
class AnOrganizer
|
17
|
-
|
17
|
+
extend LightService::Organizer
|
18
18
|
|
19
19
|
def self.do_something(action_arguments)
|
20
20
|
with(action_arguments).reduce([AnAction, AnotherAction])
|
@@ -30,7 +30,7 @@ module TestDoubles
|
|
30
30
|
end
|
31
31
|
|
32
32
|
class MakesTeaWithMilkAction
|
33
|
-
|
33
|
+
extend LightService::Action
|
34
34
|
expects :tea, :milk
|
35
35
|
promises :milk_tea
|
36
36
|
|
@@ -40,7 +40,7 @@ module TestDoubles
|
|
40
40
|
end
|
41
41
|
|
42
42
|
class MultipleExpectsAction
|
43
|
-
|
43
|
+
extend LightService::Action
|
44
44
|
expects :tea
|
45
45
|
expects :milk, :chocolate
|
46
46
|
promises :milk_tea
|
@@ -51,13 +51,13 @@ module TestDoubles
|
|
51
51
|
end
|
52
52
|
|
53
53
|
class MakesCappuccinoAction
|
54
|
-
|
54
|
+
extend LightService::Action
|
55
55
|
expects :coffee, :milk
|
56
56
|
promises :cappuccino
|
57
57
|
end
|
58
58
|
|
59
59
|
class MakesLatteAction
|
60
|
-
|
60
|
+
extend LightService::Action
|
61
61
|
expects :coffee, :milk
|
62
62
|
promises :latte
|
63
63
|
|
@@ -82,7 +82,7 @@ module TestDoubles
|
|
82
82
|
end
|
83
83
|
|
84
84
|
class MultiplePromisesAction
|
85
|
-
|
85
|
+
extend LightService::Action
|
86
86
|
expects :coffee, :milk
|
87
87
|
promises :cappuccino
|
88
88
|
promises :latte
|
@@ -94,7 +94,7 @@ module TestDoubles
|
|
94
94
|
end
|
95
95
|
|
96
96
|
class MakesTeaAndCappuccino
|
97
|
-
|
97
|
+
extend LightService::Organizer
|
98
98
|
|
99
99
|
def self.call(tea, milk, coffee)
|
100
100
|
with(:tea => tea, :milk => milk, :coffee => coffee)
|
@@ -104,7 +104,7 @@ module TestDoubles
|
|
104
104
|
end
|
105
105
|
|
106
106
|
class MakesCappuccinoAddsTwo
|
107
|
-
|
107
|
+
extend LightService::Organizer
|
108
108
|
|
109
109
|
def self.call(milk, coffee)
|
110
110
|
with(:milk => milk, :coffee => coffee)
|
@@ -114,7 +114,7 @@ module TestDoubles
|
|
114
114
|
end
|
115
115
|
|
116
116
|
class MakesCappuccinoAddsTwoAndFails
|
117
|
-
|
117
|
+
extend LightService::Organizer
|
118
118
|
|
119
119
|
def self.call(coffee, this_hot = :very_hot)
|
120
120
|
with(:milk => this_hot, :coffee => coffee)
|
@@ -125,7 +125,7 @@ module TestDoubles
|
|
125
125
|
end
|
126
126
|
|
127
127
|
class MakesCappuccinoSkipsAddsTwo
|
128
|
-
|
128
|
+
extend LightService::Organizer
|
129
129
|
|
130
130
|
def self.call(coffee)
|
131
131
|
with(:milk => "5%", :coffee => coffee)
|
@@ -148,7 +148,7 @@ module TestDoubles
|
|
148
148
|
end
|
149
149
|
|
150
150
|
class AddsOneAction
|
151
|
-
|
151
|
+
extend LightService::Action
|
152
152
|
expects :number
|
153
153
|
promises :number
|
154
154
|
|
@@ -158,7 +158,7 @@ module TestDoubles
|
|
158
158
|
end
|
159
159
|
|
160
160
|
class AddsTwoAction
|
161
|
-
|
161
|
+
extend LightService::Action
|
162
162
|
expects :number
|
163
163
|
|
164
164
|
executed do |context|
|
@@ -167,7 +167,7 @@ module TestDoubles
|
|
167
167
|
end
|
168
168
|
|
169
169
|
class AddsThreeAction
|
170
|
-
|
170
|
+
extend LightService::Action
|
171
171
|
expects :number
|
172
172
|
promises :product
|
173
173
|
|
@@ -177,7 +177,7 @@ module TestDoubles
|
|
177
177
|
end
|
178
178
|
|
179
179
|
class MakesTeaExpectingReservedKey
|
180
|
-
|
180
|
+
extend LightService::Action
|
181
181
|
expects :tea, :message
|
182
182
|
|
183
183
|
executed do |context|
|
@@ -186,7 +186,7 @@ module TestDoubles
|
|
186
186
|
end
|
187
187
|
|
188
188
|
class MakesTeaExpectingMultipleReservedKeys
|
189
|
-
|
189
|
+
extend LightService::Action
|
190
190
|
expects :tea, :message, :error_code, :current_action
|
191
191
|
|
192
192
|
executed do |context|
|
@@ -195,7 +195,7 @@ module TestDoubles
|
|
195
195
|
end
|
196
196
|
|
197
197
|
class MakesTeaPromisingReservedKey
|
198
|
-
|
198
|
+
extend LightService::Action
|
199
199
|
expects :tea
|
200
200
|
promises :product, :message
|
201
201
|
|
@@ -205,7 +205,7 @@ module TestDoubles
|
|
205
205
|
end
|
206
206
|
|
207
207
|
class MakesTeaPromisingMultipleReservedKeys
|
208
|
-
|
208
|
+
extend LightService::Action
|
209
209
|
expects :tea
|
210
210
|
promises :product, :message, :error_code, :current_action
|
211
211
|
|
@@ -213,4 +213,41 @@ module TestDoubles
|
|
213
213
|
context.product = context.number + 3
|
214
214
|
end
|
215
215
|
end
|
216
|
+
|
217
|
+
class MakesTeaPromisingKeyButRaisesException
|
218
|
+
extend LightService::Action
|
219
|
+
promises :product
|
220
|
+
|
221
|
+
executed do |context|
|
222
|
+
context.product = make_product
|
223
|
+
end
|
224
|
+
|
225
|
+
private
|
226
|
+
|
227
|
+
def self.make_product
|
228
|
+
fail "Fail"
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
class PromisesPromisedKeyAction
|
233
|
+
extend LightService::Action
|
234
|
+
|
235
|
+
promises :promised_key
|
236
|
+
|
237
|
+
executed do |ctx|
|
238
|
+
ctx.promised_key = "promised_key"
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
class ExpectsExpectedKeyAction
|
243
|
+
extend LightService::Action
|
244
|
+
|
245
|
+
expects :expected_key
|
246
|
+
promises :final_key
|
247
|
+
|
248
|
+
executed do |ctx|
|
249
|
+
ctx.final_key = ctx.expected_key
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
216
253
|
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.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Attila Domokos
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-07-30 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
|
-
- .gitignore
|
91
|
-
- .rspec
|
92
|
-
- .travis.yml
|
90
|
+
- ".gitignore"
|
91
|
+
- ".rspec"
|
92
|
+
- ".travis.yml"
|
93
93
|
- Gemfile
|
94
94
|
- LICENSE
|
95
95
|
- README.md
|
@@ -111,6 +111,7 @@ files:
|
|
111
111
|
- resources/light-service.png
|
112
112
|
- resources/organizer_and_actions.png
|
113
113
|
- spec/acceptance/add_numbers_spec.rb
|
114
|
+
- spec/acceptance/include_warning_spec.rb
|
114
115
|
- spec/acceptance/log_from_organizer_spec.rb
|
115
116
|
- spec/acceptance/message_localization_spec.rb
|
116
117
|
- spec/acceptance/rollback_spec.rb
|
@@ -121,6 +122,7 @@ files:
|
|
121
122
|
- spec/context_spec.rb
|
122
123
|
- spec/localization_adapter_spec.rb
|
123
124
|
- spec/organizer/with_reducer_spec.rb
|
125
|
+
- spec/organizer_key_aliases_spec.rb
|
124
126
|
- spec/organizer_spec.rb
|
125
127
|
- spec/sample/calculates_order_tax_action_spec.rb
|
126
128
|
- spec/sample/calculates_tax_spec.rb
|
@@ -142,22 +144,23 @@ require_paths:
|
|
142
144
|
- lib
|
143
145
|
required_ruby_version: !ruby/object:Gem::Requirement
|
144
146
|
requirements:
|
145
|
-
- -
|
147
|
+
- - ">="
|
146
148
|
- !ruby/object:Gem::Version
|
147
149
|
version: '0'
|
148
150
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
151
|
requirements:
|
150
|
-
- -
|
152
|
+
- - ">="
|
151
153
|
- !ruby/object:Gem::Version
|
152
154
|
version: '0'
|
153
155
|
requirements: []
|
154
156
|
rubyforge_project:
|
155
|
-
rubygems_version: 2.
|
157
|
+
rubygems_version: 2.4.5
|
156
158
|
signing_key:
|
157
159
|
specification_version: 4
|
158
160
|
summary: A service skeleton with an emphasis on simplicity
|
159
161
|
test_files:
|
160
162
|
- spec/acceptance/add_numbers_spec.rb
|
163
|
+
- spec/acceptance/include_warning_spec.rb
|
161
164
|
- spec/acceptance/log_from_organizer_spec.rb
|
162
165
|
- spec/acceptance/message_localization_spec.rb
|
163
166
|
- spec/acceptance/rollback_spec.rb
|
@@ -168,6 +171,7 @@ test_files:
|
|
168
171
|
- spec/context_spec.rb
|
169
172
|
- spec/localization_adapter_spec.rb
|
170
173
|
- spec/organizer/with_reducer_spec.rb
|
174
|
+
- spec/organizer_key_aliases_spec.rb
|
171
175
|
- spec/organizer_spec.rb
|
172
176
|
- spec/sample/calculates_order_tax_action_spec.rb
|
173
177
|
- spec/sample/calculates_tax_spec.rb
|