light-service 0.17.0 → 0.19.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/project-build.yml +3 -6
- data/.rubocop.yml +117 -3
- data/README.md +101 -31
- data/RELEASES.md +11 -0
- data/lib/generators/light_service/generator_utils.rb +0 -2
- data/lib/light-service/action.rb +3 -5
- data/lib/light-service/configuration.rb +10 -2
- data/lib/light-service/context/key_verifier.rb +4 -2
- data/lib/light-service/context.rb +10 -15
- data/lib/light-service/deprecation_warning.rb +17 -0
- data/lib/light-service/errors.rb +4 -0
- data/lib/light-service/i18n/localization_adapter.rb +46 -0
- data/lib/light-service/localization_adapter.rb +14 -27
- data/lib/light-service/localization_map.rb +7 -0
- data/lib/light-service/orchestrator.rb +3 -3
- data/lib/light-service/organizer/reduce_case.rb +48 -0
- data/lib/light-service/organizer/verify_call_method_exists.rb +1 -1
- data/lib/light-service/organizer/with_reducer.rb +6 -8
- data/lib/light-service/organizer/with_reducer_log_decorator.rb +2 -2
- data/lib/light-service/organizer.rb +5 -3
- data/lib/light-service/testing/context_factory.rb +4 -0
- data/lib/light-service/version.rb +1 -1
- data/lib/light-service.rb +5 -2
- data/light-service.gemspec +3 -6
- data/spec/acceptance/after_actions_spec.rb +3 -9
- data/spec/acceptance/before_actions_spec.rb +3 -9
- data/spec/acceptance/include_warning_spec.rb +2 -2
- data/spec/acceptance/message_localization_spec.rb +7 -7
- data/spec/acceptance/not_having_call_method_warning_spec.rb +3 -3
- data/spec/acceptance/organizer/reduce_case_spec.rb +53 -0
- data/spec/acceptance/organizer/reduce_if_spec.rb +2 -0
- data/spec/acceptance/skip_all_warning_spec.rb +1 -1
- data/spec/context/inspect_spec.rb +5 -21
- data/spec/context_spec.rb +2 -2
- data/spec/i18n_localization_adapter_spec.rb +83 -0
- data/spec/lib/generators/action_generator_advanced_spec.rb +1 -1
- data/spec/lib/generators/action_generator_simple_spec.rb +1 -1
- data/spec/lib/generators/organizer_generator_advanced_spec.rb +1 -1
- data/spec/lib/generators/organizer_generator_simple_spec.rb +1 -1
- data/spec/localization_adapter_spec.rb +17 -38
- data/spec/sample/calculates_tax_spec.rb +0 -1
- data/spec/sample/looks_up_tax_percentage_action_spec.rb +3 -1
- data/spec/support.rb +1 -1
- data/spec/test_doubles.rb +20 -5
- data/spec/testing/context_factory_spec.rb +15 -0
- metadata +19 -42
- data/Appraisals +0 -11
- data/gemfiles/activesupport_5.gemfile +0 -7
- data/gemfiles/activesupport_6.gemfile +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d569b02dd645032b8b5bf18aaaff2a571255cbb899b1c3975fb0f3708a740d4d
|
4
|
+
data.tar.gz: 41d774361e725cf016ecb5c168773a3e2cb0155b16fa4953b693c211cc77df22
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4b1e641b0136f71241bb047601b0003667ef1158d95635d7b70c57f301b6bb0faf313ecbc5a28b07dae7e139eb947460a2d5a78c9558c7e96ae773c6c025ef93
|
7
|
+
data.tar.gz: da0f8116260901f425c9829d1b4f97c990241ecbf693ac49696c1754313e7fe890ac7ad744a86740ff885c50aa373e4517843c29534ad9376c80c6b87e8df3b5
|
@@ -13,16 +13,13 @@ jobs:
|
|
13
13
|
fail-fast: false
|
14
14
|
matrix:
|
15
15
|
os: [ubuntu, macos]
|
16
|
-
ruby: [
|
17
|
-
gemfile: [activesupport_5, activesupport_6]
|
16
|
+
ruby: ['3.1', '3.2', '3.3']
|
18
17
|
continue-on-error: ${{ endsWith(matrix.ruby, 'head') || matrix.ruby == 'debug' }}
|
19
|
-
env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps
|
20
|
-
BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
|
21
18
|
steps:
|
22
|
-
- uses: actions/checkout@
|
19
|
+
- uses: actions/checkout@v3
|
23
20
|
- uses: ruby/setup-ruby@v1
|
24
21
|
with:
|
25
22
|
ruby-version: ${{ matrix.ruby }}
|
26
|
-
|
23
|
+
bundler-cache: true
|
27
24
|
- run: bundle exec rspec spec
|
28
25
|
- run: bundle exec rubocop
|
data/.rubocop.yml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
require: rubocop-performance
|
1
|
+
# require: rubocop-performance
|
2
2
|
|
3
3
|
AllCops:
|
4
|
-
TargetRubyVersion: 2.
|
4
|
+
TargetRubyVersion: 2.7
|
5
5
|
Exclude:
|
6
6
|
- 'lib/light-service.rb'
|
7
7
|
- 'vendor/bundle/**/*'
|
@@ -47,8 +47,122 @@ Metrics/BlockLength:
|
|
47
47
|
Exclude:
|
48
48
|
- 'spec/**/*.rb'
|
49
49
|
|
50
|
-
Layout/
|
50
|
+
Layout/TrailingEmptyLines:
|
51
51
|
Enabled: false
|
52
52
|
|
53
53
|
Layout/EndOfLine:
|
54
54
|
EnforcedStyle: lf
|
55
|
+
|
56
|
+
Lint/ConstantDefinitionInBlock:
|
57
|
+
Exclude:
|
58
|
+
- 'spec/**/*.rb'
|
59
|
+
|
60
|
+
Lint/EmptyClass:
|
61
|
+
Exclude:
|
62
|
+
- 'spec/**/*.rb'
|
63
|
+
|
64
|
+
# Defaults after the Rubocop upgrade
|
65
|
+
Gemspec/DateAssignment: # new in 1.10
|
66
|
+
Enabled: true
|
67
|
+
Layout/LineEndStringConcatenationIndentation: # new in 1.18
|
68
|
+
Enabled: true
|
69
|
+
Layout/SpaceBeforeBrackets: # new in 1.7
|
70
|
+
Enabled: true
|
71
|
+
Lint/AmbiguousAssignment: # new in 1.7
|
72
|
+
Enabled: true
|
73
|
+
Lint/AmbiguousOperatorPrecedence: # new in 1.21
|
74
|
+
Enabled: true
|
75
|
+
Lint/AmbiguousRange: # new in 1.19
|
76
|
+
Enabled: true
|
77
|
+
Lint/DeprecatedConstants: # new in 1.8
|
78
|
+
Enabled: true
|
79
|
+
Lint/DuplicateBranch: # new in 1.3
|
80
|
+
Enabled: true
|
81
|
+
Lint/DuplicateRegexpCharacterClassElement: # new in 1.1
|
82
|
+
Enabled: true
|
83
|
+
Lint/EmptyBlock: # new in 1.1
|
84
|
+
Enabled: true
|
85
|
+
Lint/EmptyClass: # new in 1.3
|
86
|
+
Enabled: true
|
87
|
+
Lint/EmptyInPattern: # new in 1.16
|
88
|
+
Enabled: true
|
89
|
+
Lint/IncompatibleIoSelectWithFiberScheduler: # new in 1.21
|
90
|
+
Enabled: true
|
91
|
+
Lint/LambdaWithoutLiteralBlock: # new in 1.8
|
92
|
+
Enabled: true
|
93
|
+
Lint/NoReturnInBeginEndBlocks: # new in 1.2
|
94
|
+
Enabled: true
|
95
|
+
Lint/NumberedParameterAssignment: # new in 1.9
|
96
|
+
Enabled: true
|
97
|
+
Lint/OrAssignmentToConstant: # new in 1.9
|
98
|
+
Enabled: true
|
99
|
+
Lint/RedundantDirGlobSort: # new in 1.8
|
100
|
+
Enabled: true
|
101
|
+
Lint/SymbolConversion: # new in 1.9
|
102
|
+
Enabled: true
|
103
|
+
Lint/ToEnumArguments: # new in 1.1
|
104
|
+
Enabled: true
|
105
|
+
Lint/TripleQuotes: # new in 1.9
|
106
|
+
Enabled: true
|
107
|
+
Lint/UnexpectedBlockArity: # new in 1.5
|
108
|
+
Enabled: true
|
109
|
+
Lint/UnmodifiedReduceAccumulator: # new in 1.1
|
110
|
+
Enabled: true
|
111
|
+
Style/ArgumentsForwarding: # new in 1.1
|
112
|
+
Enabled: true
|
113
|
+
Style/CollectionCompact: # new in 1.2
|
114
|
+
Enabled: true
|
115
|
+
Style/DocumentDynamicEvalDefinition: # new in 1.1
|
116
|
+
Enabled: true
|
117
|
+
Style/EndlessMethod: # new in 1.8
|
118
|
+
Enabled: true
|
119
|
+
Style/HashConversion: # new in 1.10
|
120
|
+
Enabled: true
|
121
|
+
Style/HashExcept: # new in 1.7
|
122
|
+
Enabled: true
|
123
|
+
Style/IfWithBooleanLiteralBranches: # new in 1.9
|
124
|
+
Enabled: true
|
125
|
+
Style/InPatternThen: # new in 1.16
|
126
|
+
Enabled: true
|
127
|
+
Style/MultilineInPatternThen: # new in 1.16
|
128
|
+
Enabled: true
|
129
|
+
Style/NegatedIfElseCondition: # new in 1.2
|
130
|
+
Enabled: true
|
131
|
+
Style/NilLambda: # new in 1.3
|
132
|
+
Enabled: true
|
133
|
+
Style/QuotedSymbols: # new in 1.16
|
134
|
+
Enabled: true
|
135
|
+
Style/RedundantArgument: # new in 1.4
|
136
|
+
Enabled: true
|
137
|
+
Style/RedundantSelfAssignmentBranch: # new in 1.19
|
138
|
+
Enabled: true
|
139
|
+
Style/StringChars: # new in 1.12
|
140
|
+
Enabled: true
|
141
|
+
Style/SwapValues: # new in 1.1
|
142
|
+
Enabled: true
|
143
|
+
Gemspec/RequireMFA: # new in 1.23
|
144
|
+
Enabled: true
|
145
|
+
Lint/RequireRelativeSelfPath: # new in 1.22
|
146
|
+
Enabled: true
|
147
|
+
Lint/UselessRuby2Keywords: # new in 1.23
|
148
|
+
Enabled: true
|
149
|
+
Naming/BlockForwarding: # new in 1.24
|
150
|
+
Enabled: true
|
151
|
+
Security/IoMethods: # new in 1.22
|
152
|
+
Enabled: true
|
153
|
+
Style/FileRead: # new in 1.24
|
154
|
+
Enabled: true
|
155
|
+
Style/FileWrite: # new in 1.24
|
156
|
+
Enabled: true
|
157
|
+
Style/MapToHash: # new in 1.24
|
158
|
+
Enabled: true
|
159
|
+
Style/NestedFileDirname: # new in 1.26
|
160
|
+
Enabled: true
|
161
|
+
Style/NumberedParameters: # new in 1.22
|
162
|
+
Enabled: true
|
163
|
+
Style/NumberedParametersLimit: # new in 1.22
|
164
|
+
Enabled: true
|
165
|
+
Style/OpenStructUse: # new in 1.23
|
166
|
+
Enabled: true
|
167
|
+
Style/SelectByRegexp: # new in 1.22
|
168
|
+
Enabled: true
|
data/README.md
CHANGED
@@ -10,29 +10,38 @@
|
|
10
10
|
LightService is a powerful and flexible service skeleton framework with an emphasis on simplicity
|
11
11
|
|
12
12
|
## Table of Contents
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
13
|
+
- [Table of Contents](#table-of-contents)
|
14
|
+
- [Why LightService?](#why-lightservice)
|
15
|
+
- [Getting started](#getting-started)
|
16
|
+
- [Requirements](#requirements)
|
17
|
+
- [Installation](#installation)
|
18
|
+
- [Your first action](#your-first-action)
|
19
|
+
- [Your first organizer](#your-first-organizer)
|
20
|
+
- [Stopping the Series of Actions](#stopping-the-series-of-actions)
|
21
|
+
- [Failing the Context](#failing-the-context)
|
22
|
+
- [Skipping the rest of the actions](#skipping-the-rest-of-the-actions)
|
23
|
+
- [Benchmarking Actions with Around Advice](#benchmarking-actions-with-around-advice)
|
24
|
+
- [Before and After Action Hooks](#before-and-after-action-hooks)
|
25
|
+
- [Expects and Promises](#expects-and-promises)
|
26
|
+
- [Default values for optional Expected keys](#default-values-for-optional-expected-keys)
|
27
|
+
- [Key Aliases](#key-aliases)
|
28
|
+
- [Logging](#logging)
|
29
|
+
- [Error Codes](#error-codes)
|
30
|
+
- [Action Rollback](#action-rollback)
|
31
|
+
- [Localizing Messages](#localizing-messages)
|
32
|
+
- [Built-in localization adapter](#built-in-localization-adapter)
|
33
|
+
- [I18n localization adapter](#i18n-localization-adapter)
|
34
|
+
- [Custom localization adapter](#custom-localization-adapter)
|
35
|
+
- [Orchestrating Logic in Organizers](#orchestrating-logic-in-organizers)
|
36
|
+
- [ContextFactory for Faster Action Testing](#contextfactory-for-faster-action-testing)
|
37
|
+
- [Rails support](#rails-support)
|
38
|
+
- [Organizer generation](#organizer-generation)
|
39
|
+
- [Action generation](#action-generation)
|
40
|
+
- [Advanced action generation](#advanced-action-generation)
|
41
|
+
- [Other implementations](#other-implementations)
|
42
|
+
- [Contributing](#contributing)
|
43
|
+
- [Release Notes](#release-notes)
|
44
|
+
- [License](#license)
|
36
45
|
|
37
46
|
## Why LightService?
|
38
47
|
|
@@ -823,7 +832,61 @@ end
|
|
823
832
|
```
|
824
833
|
|
825
834
|
## Localizing Messages
|
826
|
-
|
835
|
+
|
836
|
+
### Built-in localization adapter
|
837
|
+
|
838
|
+
The built-in adapter simply uses a manually created dictionary to search for translations.
|
839
|
+
|
840
|
+
```ruby
|
841
|
+
# lib/light_service_translations.rb
|
842
|
+
LightService::LocalizationMap.instance[:en] = {
|
843
|
+
:foo_action => {
|
844
|
+
:light_service => {
|
845
|
+
:failures => {
|
846
|
+
:exceeded_api_limit => "API limit for service Foo reached. Please try again later."
|
847
|
+
},
|
848
|
+
:successes => {
|
849
|
+
:yay => "Yaaay!"
|
850
|
+
}
|
851
|
+
}
|
852
|
+
}
|
853
|
+
}
|
854
|
+
```
|
855
|
+
|
856
|
+
```ruby
|
857
|
+
class FooAction
|
858
|
+
extend LightService::Action
|
859
|
+
|
860
|
+
executed do |context|
|
861
|
+
unless service_call.success?
|
862
|
+
context.fail!(:exceeded_api_limit)
|
863
|
+
|
864
|
+
# The failure message used here equates to:
|
865
|
+
# LightService::LocalizationMap.instance[:en][:foo_action][:light_service][:failures][:exceeded_api_limit]
|
866
|
+
end
|
867
|
+
end
|
868
|
+
end
|
869
|
+
```
|
870
|
+
|
871
|
+
Nested classes will work too: `App::FooAction`, for example, would be translated to `app/foo_action` hash key.
|
872
|
+
|
873
|
+
`:en` is the default locale, but you can switch it whenever you want with
|
874
|
+
|
875
|
+
```ruby
|
876
|
+
LightService::Configuration.locale = :it
|
877
|
+
```
|
878
|
+
|
879
|
+
If you have `I18n` loaded in your project the default adapter will automatically be updated to use it.
|
880
|
+
But would you want to opt for the built-in localization adapter you can force it with
|
881
|
+
|
882
|
+
```ruby
|
883
|
+
LightService::Configuration.localization_adapter = LightService::LocalizationAdapter
|
884
|
+
```
|
885
|
+
|
886
|
+
### I18n localization adapter
|
887
|
+
|
888
|
+
If `I18n` is loaded into your project, LightService will automatically provide a mechanism for easily translating your error or success messages via `I18n`.
|
889
|
+
|
827
890
|
|
828
891
|
```ruby
|
829
892
|
class FooAction
|
@@ -881,13 +944,17 @@ module PaymentGateway
|
|
881
944
|
end
|
882
945
|
```
|
883
946
|
|
947
|
+
### Custom localization adapter
|
948
|
+
|
949
|
+
You can also provide your own custom localization adapter if your application's logic is more complex than what is shown here.
|
950
|
+
|
884
951
|
To provide your own custom adapter, use the configuration setting and subclass the default adapter LightService provides.
|
885
952
|
|
886
953
|
```ruby
|
887
954
|
LightService::Configuration.localization_adapter = MyLocalizer.new
|
888
955
|
|
889
956
|
# lib/my_localizer.rb
|
890
|
-
class MyLocalizer < LightService::LocalizationAdapter
|
957
|
+
class MyLocalizer < LightService::I18n::LocalizationAdapter
|
891
958
|
|
892
959
|
# I just want to change the default lookup path
|
893
960
|
# => "light_service.failures.payment_gateway/capture_funds"
|
@@ -959,16 +1026,17 @@ end
|
|
959
1026
|
|
960
1027
|
This code is much easier to reason about, it's less noisy and it captures the goal of LightService well: simple, declarative code that's easy to understand.
|
961
1028
|
|
962
|
-
The
|
1029
|
+
The 9 different orchestrator constructs an organizer can have:
|
963
1030
|
|
964
1031
|
1. `reduce_until`
|
965
1032
|
2. `reduce_if`
|
966
1033
|
3. `reduce_if_else`
|
967
|
-
4. `
|
968
|
-
5. `
|
969
|
-
6. `
|
970
|
-
7. `
|
971
|
-
8. `
|
1034
|
+
4. `reduce_case`
|
1035
|
+
5. `iterate`
|
1036
|
+
6. `execute`
|
1037
|
+
7. `with_callback`
|
1038
|
+
8. `add_to_context`
|
1039
|
+
9. `add_aliases`
|
972
1040
|
|
973
1041
|
`reduce_until` behaves like a while loop in imperative languages, it iterates until the provided predicate in the lambda evaluates to true. Take a look at [this acceptance test](spec/acceptance/organizer/reduce_until_spec.rb) to see how it's used.
|
974
1042
|
|
@@ -976,6 +1044,8 @@ The 7 different orchestrator constructs an organizer can have:
|
|
976
1044
|
|
977
1045
|
`reduce_if_else` takes three arguments, a condition lambda, a first set of "if true" steps, and a second set of "if false" steps. If the lambda evaluates to true, the "if true" steps are executed, otherwise the "else steps" are executed. [This acceptance test](spec/acceptance/organizer/reduce_if_else_spec.rb) describes this functionality.
|
978
1046
|
|
1047
|
+
`reduce_case` behaves like a Ruby `case` statement. The first parameter `value` is the key of the value within the context that will be worked with. The second parameter `when` is a hash where the keys are conditional values and the values are steps to take if the condition matches. The final parameter `else` is a set of steps to take if no conditions within the `when` parameter are met. [This acceptance test](spec/acceptance/organizer/reduce_case_spec.rb) describes this functionality.
|
1048
|
+
|
979
1049
|
`iterate` gives your iteration logic, the symbol you define there has to be in the context as a key. For example, to iterate over items you will use `iterate(:items)` in your steps, the context needs to have `items` as a key, otherwise it will fail. The organizer will singularize the collection name and will put the actual item into the context under that name. Remaining with the example above, each element will be accessible by the name `item` for the actions in the `iterate` steps. [This acceptance test](spec/acceptance/organizer/iterate_spec.rb) should provide you with an example.
|
980
1050
|
|
981
1051
|
To take advantage of another organizer or action, you might need to tweak the context a bit. Let's say you have a hash, and you need to iterate over its values in a series of action. To alter the context and have the values assigned into a variable, you need to create a new action with 1 line of code in it. That seems a lot of ceremony for a simple change. You can do that in a `execute` method like this `execute(->(ctx) { ctx[:some_values] = ctx.some_hash.values })`. [This test](spec/acceptance/organizer/execute_spec.rb) describes how you can use it.
|
data/RELEASES.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
A brief list of new features and changes introduced with the specified version.
|
2
2
|
|
3
|
+
### 0.19.0
|
4
|
+
* [Implement built-in localization adapter](https://github.com/adomokos/light-service/pull/238)
|
5
|
+
* [Swap ActiveSupport::Deprecation with built-in LightSupport::Deprecation](https://github.com/adomokos/light-service/pull/241)
|
6
|
+
* [Remove Active Support dependency](https://github.com/adomokos/light-service/pull/246)
|
7
|
+
|
8
|
+
### 0.18.0
|
9
|
+
* [Remove Ruby 2.6, add 3.1 to build](https://github.com/adomokos/light-service/pull/233)
|
10
|
+
* [Add reduce_when](https://github.com/adomokos/light-service/pull/232)
|
11
|
+
* [Drop Ruby 2.5 version support, add 3.0 build](https://github.com/adomokos/light-service/pull/225)
|
12
|
+
* [Support for named argument in Ruby](https://github.com/adomokos/light-service/pull/224)
|
13
|
+
|
3
14
|
### 0.17.0
|
4
15
|
* [Fix around_action hook for nested actions](https://github.com/adomokos/light-service/pull/217)
|
5
16
|
* [Add ReduceIfElse macro](https://github.com/adomokos/light-service/pull/218)
|
@@ -25,7 +25,6 @@ module LightService
|
|
25
25
|
options.tests? && test_framework_supported?
|
26
26
|
end
|
27
27
|
|
28
|
-
# rubocop:disable Metrics/AbcSize
|
29
28
|
def create_required_gen_vals_from(name)
|
30
29
|
path_parts = name.underscore.split('/')
|
31
30
|
|
@@ -39,7 +38,6 @@ module LightService
|
|
39
38
|
:full_class_name => name.classify
|
40
39
|
}
|
41
40
|
end
|
42
|
-
# rubocop:enable Metrics/AbcSize
|
43
41
|
end
|
44
42
|
end
|
45
43
|
end
|
data/lib/light-service/action.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'active_support/deprecation'
|
2
|
-
|
3
1
|
module LightService
|
4
2
|
module Action
|
5
3
|
def self.extended(base_class)
|
@@ -7,9 +5,9 @@ module LightService
|
|
7
5
|
end
|
8
6
|
|
9
7
|
def self.included(base_class)
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
warning_msg = "including LightService::Action is deprecated. " \
|
9
|
+
"Please use `extend LightService::Action` instead"
|
10
|
+
LightService::Deprecation.warn(warning_msg)
|
13
11
|
base_class.extend Macros
|
14
12
|
end
|
15
13
|
|
@@ -2,14 +2,22 @@ module LightService
|
|
2
2
|
class Configuration
|
3
3
|
class << self
|
4
4
|
attr_accessor :capture_errors
|
5
|
-
attr_writer :logger, :localization_adapter
|
5
|
+
attr_writer :logger, :localization_adapter, :locale
|
6
6
|
|
7
7
|
def logger
|
8
8
|
@logger ||= _default_logger
|
9
9
|
end
|
10
10
|
|
11
11
|
def localization_adapter
|
12
|
-
@localization_adapter ||=
|
12
|
+
@localization_adapter ||= if Module.const_defined?('I18n')
|
13
|
+
LightService::I18n::LocalizationAdapter.new
|
14
|
+
else
|
15
|
+
LocalizationAdapter.new
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def locale
|
20
|
+
@locale ||= :en
|
13
21
|
end
|
14
22
|
|
15
23
|
private
|
@@ -24,7 +24,7 @@ module LightService
|
|
24
24
|
|
25
25
|
def error_message
|
26
26
|
"#{type_name} #{format_keys(keys_not_found(keys))} " \
|
27
|
-
|
27
|
+
"to be in the context during #{action}"
|
28
28
|
end
|
29
29
|
|
30
30
|
def throw_error_predicate(_keys)
|
@@ -95,7 +95,7 @@ module LightService
|
|
95
95
|
|
96
96
|
def error_message
|
97
97
|
"promised or expected keys cannot be a " \
|
98
|
-
|
98
|
+
"reserved key: [#{format_keys(violated_keys)}]"
|
99
99
|
end
|
100
100
|
|
101
101
|
def keys
|
@@ -116,9 +116,11 @@ module LightService
|
|
116
116
|
end
|
117
117
|
|
118
118
|
class ReservedKeysViaOrganizerVerifier < ReservedKeysVerifier
|
119
|
+
# rubocop:disable Lint/MissingSuper
|
119
120
|
def initialize(context_data)
|
120
121
|
@context = LightService::Context.make(context_data)
|
121
122
|
end
|
123
|
+
# rubocop:enable Lint/MissingSuper
|
122
124
|
|
123
125
|
def violated_keys
|
124
126
|
context.keys.map(&:to_sym) & reserved_keys
|
@@ -1,16 +1,15 @@
|
|
1
|
-
require 'active_support/deprecation'
|
2
|
-
|
3
1
|
module LightService
|
4
2
|
module Outcomes
|
5
3
|
SUCCESS = 0
|
6
4
|
FAILURE = 1
|
7
5
|
end
|
8
6
|
|
9
|
-
# rubocop:disable ClassLength
|
7
|
+
# rubocop:disable Metrics/ClassLength
|
10
8
|
class Context < Hash
|
11
9
|
attr_accessor :message, :error_code, :current_action, :around_actions,
|
12
10
|
:organized_by
|
13
11
|
|
12
|
+
# rubocop:disable Metrics/ParameterLists, Lint/MissingSuper
|
14
13
|
def initialize(context = {},
|
15
14
|
outcome = Outcomes::SUCCESS,
|
16
15
|
message = '',
|
@@ -22,6 +21,7 @@ module LightService
|
|
22
21
|
|
23
22
|
context.to_hash.each { |k, v| self[k] = v }
|
24
23
|
end
|
24
|
+
# rubocop:enable Metrics/ParameterLists, Lint/MissingSuper
|
25
25
|
|
26
26
|
def self.make(context = {})
|
27
27
|
unless context.is_a?(Hash) || context.is_a?(LightService::Context)
|
@@ -57,9 +57,9 @@ module LightService
|
|
57
57
|
end
|
58
58
|
|
59
59
|
def outcome
|
60
|
-
|
61
|
-
|
62
|
-
|
60
|
+
warning_msg = '`Context#outcome` attribute reader is ' \
|
61
|
+
'DEPRECATED and will be removed'
|
62
|
+
LightService::Deprecation.warn(warning_msg)
|
63
63
|
@outcome
|
64
64
|
end
|
65
65
|
|
@@ -101,7 +101,7 @@ module LightService
|
|
101
101
|
def skip_all!(message = nil)
|
102
102
|
warning_msg = "Using skip_all! has been deprecated, " \
|
103
103
|
"please use `skip_remaining!` instead."
|
104
|
-
|
104
|
+
LightService::Deprecation.warn(warning_msg)
|
105
105
|
|
106
106
|
skip_remaining!(message)
|
107
107
|
end
|
@@ -152,13 +152,8 @@ module LightService
|
|
152
152
|
end
|
153
153
|
|
154
154
|
def inspect
|
155
|
-
"#{self.class}(#{self}, " \
|
156
|
-
|
157
|
-
+ "message: #{check_nil(message)}, " \
|
158
|
-
+ "error_code: #{check_nil(error_code)}, " \
|
159
|
-
+ "skip_remaining: #{@skip_remaining}, " \
|
160
|
-
+ "aliases: #{@aliases}" \
|
161
|
-
+ ")"
|
155
|
+
"#{self.class}(#{self}, success: #{success?}, message: #{check_nil(message)}, error_code: " \
|
156
|
+
"#{check_nil(error_code)}, skip_remaining: #{@skip_remaining}, aliases: #{@aliases})"
|
162
157
|
end
|
163
158
|
|
164
159
|
private
|
@@ -169,5 +164,5 @@ module LightService
|
|
169
164
|
"'#{value}'"
|
170
165
|
end
|
171
166
|
end
|
172
|
-
# rubocop:enable ClassLength
|
167
|
+
# rubocop:enable Metrics/ClassLength
|
173
168
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module LightService
|
2
|
+
module Deprecation
|
3
|
+
class << self
|
4
|
+
# Basic implementation of a deprecation warning
|
5
|
+
def warn(message, callstack = caller)
|
6
|
+
# Construct the warning message
|
7
|
+
warning_message = "DEPRECATION WARNING: #{message}\n"
|
8
|
+
warning_message += "Called from: #{callstack.first}\n" unless callstack.empty?
|
9
|
+
|
10
|
+
# Output the warning message to stderr or a log file
|
11
|
+
warn warning_message
|
12
|
+
|
13
|
+
# Additional logging or actions can be added here
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/light-service/errors.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
module LightService
|
2
2
|
class FailWithRollbackError < StandardError; end
|
3
|
+
|
3
4
|
class ExpectedKeysNotInContextError < StandardError; end
|
5
|
+
|
4
6
|
class PromisedKeysNotInContextError < StandardError; end
|
7
|
+
|
5
8
|
class ReservedKeysInContextError < StandardError; end
|
9
|
+
|
6
10
|
class UnusableExpectKeyDefaultError < StandardError; end
|
7
11
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module LightService
|
2
|
+
module I18n
|
3
|
+
class LocalizationAdapter
|
4
|
+
def failure(message_or_key, action_class, i18n_options = {})
|
5
|
+
find_translated_message(message_or_key,
|
6
|
+
action_class,
|
7
|
+
i18n_options,
|
8
|
+
:type => :failure)
|
9
|
+
end
|
10
|
+
|
11
|
+
def success(message_or_key, action_class, i18n_options = {})
|
12
|
+
find_translated_message(message_or_key,
|
13
|
+
action_class,
|
14
|
+
i18n_options,
|
15
|
+
:type => :success)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def find_translated_message(message_or_key,
|
21
|
+
action_class,
|
22
|
+
i18n_options,
|
23
|
+
type)
|
24
|
+
if message_or_key.is_a?(Symbol)
|
25
|
+
i18n_options.merge!(type)
|
26
|
+
translate(message_or_key, action_class, i18n_options)
|
27
|
+
else
|
28
|
+
message_or_key
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def translate(key, action_class, options = {})
|
33
|
+
type = options.delete(:type)
|
34
|
+
|
35
|
+
scope = i18n_scope_from_class(action_class, type)
|
36
|
+
options[:scope] = scope
|
37
|
+
|
38
|
+
::I18n.t(key, **options)
|
39
|
+
end
|
40
|
+
|
41
|
+
def i18n_scope_from_class(action_class, type)
|
42
|
+
"#{action_class.name.underscore}.light_service.#{type.to_s.pluralize}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -1,44 +1,31 @@
|
|
1
1
|
module LightService
|
2
2
|
class LocalizationAdapter
|
3
|
-
def failure(message_or_key, action_class
|
3
|
+
def failure(message_or_key, action_class)
|
4
4
|
find_translated_message(message_or_key,
|
5
|
-
action_class,
|
6
|
-
|
7
|
-
:type => :failure)
|
5
|
+
action_class.to_s.underscore,
|
6
|
+
:failures)
|
8
7
|
end
|
9
8
|
|
10
|
-
def success(message_or_key, action_class
|
9
|
+
def success(message_or_key, action_class)
|
11
10
|
find_translated_message(message_or_key,
|
12
|
-
action_class,
|
13
|
-
|
14
|
-
:type => :success)
|
11
|
+
action_class.to_s.underscore,
|
12
|
+
:successes)
|
15
13
|
end
|
16
14
|
|
17
15
|
private
|
18
16
|
|
19
|
-
def find_translated_message(message_or_key,
|
20
|
-
action_class,
|
21
|
-
i18n_options,
|
22
|
-
type)
|
17
|
+
def find_translated_message(message_or_key, action_class, type)
|
23
18
|
if message_or_key.is_a?(Symbol)
|
24
|
-
|
25
|
-
|
19
|
+
LightService::LocalizationMap.instance.dig(
|
20
|
+
LightService::Configuration.locale,
|
21
|
+
action_class.to_sym,
|
22
|
+
:light_service,
|
23
|
+
type,
|
24
|
+
message_or_key
|
25
|
+
)
|
26
26
|
else
|
27
27
|
message_or_key
|
28
28
|
end
|
29
29
|
end
|
30
|
-
|
31
|
-
def translate(key, action_class, options = {})
|
32
|
-
type = options.delete(:type)
|
33
|
-
|
34
|
-
scope = i18n_scope_from_class(action_class, type)
|
35
|
-
options[:scope] = scope
|
36
|
-
|
37
|
-
I18n.t(key, **options)
|
38
|
-
end
|
39
|
-
|
40
|
-
def i18n_scope_from_class(action_class, type)
|
41
|
-
"#{action_class.name.underscore}.light_service.#{type.to_s.pluralize}"
|
42
|
-
end
|
43
30
|
end
|
44
31
|
end
|