appfuel 0.2.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 +7 -0
- data/.codeclimate.yml +25 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.rubocop.yml +1156 -0
- data/.travis.yml +19 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +9 -0
- data/README.md +38 -0
- data/Rakefile +6 -0
- data/appfuel.gemspec +42 -0
- data/bin/console +7 -0
- data/bin/setup +8 -0
- data/lib/appfuel.rb +210 -0
- data/lib/appfuel/application.rb +4 -0
- data/lib/appfuel/application/app_container.rb +223 -0
- data/lib/appfuel/application/container_class_registration.rb +22 -0
- data/lib/appfuel/application/container_key.rb +201 -0
- data/lib/appfuel/application/qualify_container_key.rb +76 -0
- data/lib/appfuel/application/root.rb +140 -0
- data/lib/appfuel/cli_msg_request.rb +19 -0
- data/lib/appfuel/configuration.rb +14 -0
- data/lib/appfuel/configuration/definition_dsl.rb +175 -0
- data/lib/appfuel/configuration/file_loader.rb +61 -0
- data/lib/appfuel/configuration/populate.rb +95 -0
- data/lib/appfuel/configuration/search.rb +45 -0
- data/lib/appfuel/db_model.rb +16 -0
- data/lib/appfuel/domain.rb +7 -0
- data/lib/appfuel/domain/criteria.rb +436 -0
- data/lib/appfuel/domain/domain_name_parser.rb +44 -0
- data/lib/appfuel/domain/dsl.rb +247 -0
- data/lib/appfuel/domain/entity.rb +242 -0
- data/lib/appfuel/domain/entity_collection.rb +87 -0
- data/lib/appfuel/domain/expr.rb +127 -0
- data/lib/appfuel/domain/value_object.rb +7 -0
- data/lib/appfuel/errors.rb +104 -0
- data/lib/appfuel/feature.rb +2 -0
- data/lib/appfuel/feature/action_loader.rb +25 -0
- data/lib/appfuel/feature/initializer.rb +43 -0
- data/lib/appfuel/handler.rb +6 -0
- data/lib/appfuel/handler/action.rb +17 -0
- data/lib/appfuel/handler/base.rb +103 -0
- data/lib/appfuel/handler/command.rb +18 -0
- data/lib/appfuel/handler/inject_dsl.rb +88 -0
- data/lib/appfuel/handler/validator_dsl.rb +256 -0
- data/lib/appfuel/initialize.rb +70 -0
- data/lib/appfuel/initialize/initializer.rb +68 -0
- data/lib/appfuel/msg_request.rb +207 -0
- data/lib/appfuel/predicates.rb +10 -0
- data/lib/appfuel/presenter.rb +18 -0
- data/lib/appfuel/presenter/base.rb +7 -0
- data/lib/appfuel/repository.rb +73 -0
- data/lib/appfuel/repository/base.rb +72 -0
- data/lib/appfuel/repository/initializer.rb +19 -0
- data/lib/appfuel/repository/mapper.rb +203 -0
- data/lib/appfuel/repository/mapping_dsl.rb +210 -0
- data/lib/appfuel/repository/mapping_entry.rb +76 -0
- data/lib/appfuel/repository/mapping_registry.rb +121 -0
- data/lib/appfuel/repository_runner.rb +60 -0
- data/lib/appfuel/request.rb +53 -0
- data/lib/appfuel/response.rb +96 -0
- data/lib/appfuel/response_handler.rb +79 -0
- data/lib/appfuel/root_module.rb +31 -0
- data/lib/appfuel/run_error.rb +9 -0
- data/lib/appfuel/storage.rb +3 -0
- data/lib/appfuel/storage/db.rb +4 -0
- data/lib/appfuel/storage/db/active_record_model.rb +42 -0
- data/lib/appfuel/storage/db/mapper.rb +213 -0
- data/lib/appfuel/storage/db/migration_initializer.rb +42 -0
- data/lib/appfuel/storage/db/migration_runner.rb +15 -0
- data/lib/appfuel/storage/db/migration_tasks.rb +18 -0
- data/lib/appfuel/storage/db/repository.rb +231 -0
- data/lib/appfuel/storage/db/repository_query.rb +13 -0
- data/lib/appfuel/storage/file.rb +1 -0
- data/lib/appfuel/storage/file/base.rb +32 -0
- data/lib/appfuel/storage/memory.rb +2 -0
- data/lib/appfuel/storage/memory/mapper.rb +30 -0
- data/lib/appfuel/storage/memory/repository.rb +37 -0
- data/lib/appfuel/types.rb +53 -0
- data/lib/appfuel/validation.rb +80 -0
- data/lib/appfuel/validation/validator.rb +59 -0
- data/lib/appfuel/validation/validator_pipe.rb +47 -0
- data/lib/appfuel/version.rb +3 -0
- metadata +335 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
module Appfuel
|
2
|
+
module Handler
|
3
|
+
class Command < Base
|
4
|
+
class << self
|
5
|
+
def resolve_dependencies(results = Dry::Container.new)
|
6
|
+
=begin
|
7
|
+
super
|
8
|
+
resolve_container(results)
|
9
|
+
resolve_domains(results)
|
10
|
+
resolve_db_models(results)
|
11
|
+
resolve_repos(results)
|
12
|
+
results
|
13
|
+
=end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Appfuel
|
2
|
+
module Handler
|
3
|
+
# Allow handlers to inject domains, commands, repositories or anything
|
4
|
+
# that was initialized in the app container. Injections are done in two
|
5
|
+
# steps, first, when the class is loaded in memory the declarations are
|
6
|
+
# converted into fully qualified container keys and second, when the
|
7
|
+
# handler is run they plucked from the app container into a container
|
8
|
+
# dedicated to that one execution.
|
9
|
+
module InjectDsl
|
10
|
+
TYPES = [:domain, :cmd, :repo, :container]
|
11
|
+
|
12
|
+
# Holds a dictionary where the key is the container key and the value
|
13
|
+
# is an an optional alias for the name of the injection to be saved
|
14
|
+
# as. Injections a separated into two categories because domains are
|
15
|
+
# part of the type system (Dry::Types) and therefore kept in its own
|
16
|
+
# container "Types", meaning are fetched differently.
|
17
|
+
#
|
18
|
+
# @return [Hash]
|
19
|
+
def injections
|
20
|
+
@injections ||= {}
|
21
|
+
end
|
22
|
+
|
23
|
+
# Dsl to declare a dependency injection. You can inject one of four
|
24
|
+
# types, which are:
|
25
|
+
# domain: these are domains or value object
|
26
|
+
# cmd: commands to be run
|
27
|
+
# repo: repositories to query the persistence layer
|
28
|
+
# container: any initialized container item
|
29
|
+
#
|
30
|
+
# since names an collide you can rename your injection with the
|
31
|
+
# :as option.
|
32
|
+
#
|
33
|
+
# @example of using an alias to rename a domain injection
|
34
|
+
# inject :domain, 'member.user', as: :current_user
|
35
|
+
#
|
36
|
+
# @example of normal domain injection. In this case the name of the
|
37
|
+
# domain with me the base name "user" not "member.user"
|
38
|
+
#
|
39
|
+
# inject :domain, 'member.user'
|
40
|
+
#
|
41
|
+
#
|
42
|
+
# @param type [Symbol] type of injection
|
43
|
+
# @param key [String, Symbol] container key
|
44
|
+
# @param opts [Hash]
|
45
|
+
# @option as [String, Symbol] alternate name for injection
|
46
|
+
# @return nil
|
47
|
+
def inject(type, key, opts = {})
|
48
|
+
unless inject_type?(type)
|
49
|
+
fail "inject type must be #{TYPES.join(",")} #{type} given"
|
50
|
+
end
|
51
|
+
|
52
|
+
cat = case type
|
53
|
+
when :repo then 'repositories'
|
54
|
+
when :cmd then 'commands'
|
55
|
+
when :domain then 'domains'
|
56
|
+
else
|
57
|
+
"container"
|
58
|
+
end
|
59
|
+
|
60
|
+
namespaced_key = qualify_container_key(key, cat)
|
61
|
+
injections[namespaced_key] = opts[:as]
|
62
|
+
nil
|
63
|
+
end
|
64
|
+
|
65
|
+
def resolve_dependencies(container = Dry::Container.new)
|
66
|
+
app_container = Appfuel.app_container
|
67
|
+
injections.each do |key, alias_name|
|
68
|
+
unless app_container.key?(key)
|
69
|
+
fail "Could not inject (#{key}): not registered in app container"
|
70
|
+
end
|
71
|
+
|
72
|
+
basename = key.split('.').last
|
73
|
+
item = app_container[key]
|
74
|
+
container_key = alias_name || basename
|
75
|
+
container.register(container_key, item)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
# @param type [Symbol]
|
82
|
+
# @return [Bool]
|
83
|
+
def inject_type?(type)
|
84
|
+
TYPES.include?(type)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,256 @@
|
|
1
|
+
module Appfuel
|
2
|
+
module Handler
|
3
|
+
#
|
4
|
+
#
|
5
|
+
# 1) single block validator. A basic validator that is only used by
|
6
|
+
# that particular interactor
|
7
|
+
#
|
8
|
+
#
|
9
|
+
# validator('foo', fail_fast: true) do
|
10
|
+
#
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# 2) single validator from the features validators located in the app
|
14
|
+
# container under the key "features.<feature-name>.validators.<validator-name>"
|
15
|
+
#
|
16
|
+
# validator 'foo'
|
17
|
+
#
|
18
|
+
# 3) single validator from the global validators located in the app
|
19
|
+
# container under the key "global.validators.<validator-name>"
|
20
|
+
#
|
21
|
+
# validator 'global.foo'
|
22
|
+
#
|
23
|
+
# 4) muliple validators, all are located in the feature namespace
|
24
|
+
# validators 'foo', 'bar', 'baz'
|
25
|
+
#
|
26
|
+
# 5) multiple validators, some in features other in global
|
27
|
+
# validators 'foo', 'global.bar', 'baz'
|
28
|
+
#
|
29
|
+
# 6) a pipe is a closure that lives before a given validator in order
|
30
|
+
# to manipulate the inputs to fit the next validator. it does not validate
|
31
|
+
#
|
32
|
+
# validator_pipe do |inputs, data|
|
33
|
+
#
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# 7) using a pipe when using muliple validators
|
37
|
+
#
|
38
|
+
# validators 'foo', 'pipe.bar', 'base'
|
39
|
+
#
|
40
|
+
# 8) using global pipe in multiple validator declaration
|
41
|
+
# validators 'foo', 'global-pipe.bar', 'base'
|
42
|
+
#
|
43
|
+
# 9) validator_schema is used to use Dry::Validations with out our block
|
44
|
+
# processing
|
45
|
+
#
|
46
|
+
# validation_schema 'foo', Dry::Validation.Schama do
|
47
|
+
#
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# validation_schema Dry::Validation.Schema do
|
51
|
+
#
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# validation_schema 'foo', fail_fast: true, Dry::Validation.Schema do
|
55
|
+
#
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# validator
|
59
|
+
# name: to identify it in errors and as a key to register it with container
|
60
|
+
# fail_fast: when true runner will bail on first error
|
61
|
+
# pipe?: false
|
62
|
+
# code: validator schema to run
|
63
|
+
# call: run the validator schema
|
64
|
+
#
|
65
|
+
# validator-pipe
|
66
|
+
# name: to identify the pipe in errors and register it with container
|
67
|
+
# code: lambda to run
|
68
|
+
# call: run the lamda
|
69
|
+
module ValidatorDsl
|
70
|
+
|
71
|
+
def validators(*args)
|
72
|
+
@validators ||= []
|
73
|
+
return @validators if args.empty?
|
74
|
+
|
75
|
+
args.each do |arg|
|
76
|
+
@validators << load_validator(arg)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# When no name for a validator is given then the default name will
|
81
|
+
# be the name of the concrete handler class
|
82
|
+
#
|
83
|
+
# @return [String]
|
84
|
+
def default_validator_name
|
85
|
+
self.to_s.split('::').last.underscore
|
86
|
+
end
|
87
|
+
|
88
|
+
# Converts a given block to a validator or load the validator from
|
89
|
+
# either global or feature validators
|
90
|
+
#
|
91
|
+
# @param key [String] name of the validator
|
92
|
+
# @param opts [Hash] options for creating a validator
|
93
|
+
# @option fail_fast [Bool] allows that validator to fail immediately
|
94
|
+
# @return [Nil]
|
95
|
+
def validator(key = nil, opts = {}, &block)
|
96
|
+
key = default_validator_name if key.nil?
|
97
|
+
validators << build_validator(key, opts, &block)
|
98
|
+
nil
|
99
|
+
end
|
100
|
+
|
101
|
+
# load a validator with the given key from the app container.
|
102
|
+
#
|
103
|
+
# @note the key is encode and will be decoded first
|
104
|
+
# @see ValidatorDsl#convert_to_container_key for details
|
105
|
+
#
|
106
|
+
# @param key [String]
|
107
|
+
# @param opts [Hash]
|
108
|
+
# @return Appfuel::Validation::Validator
|
109
|
+
def load_validator(key, opts = {})
|
110
|
+
fail "validator must have a key" if key.nil?
|
111
|
+
|
112
|
+
container_key = convert_to_container_key(key)
|
113
|
+
container = Appfuel.app_container
|
114
|
+
unless container.key?(container_key)
|
115
|
+
fail "Could not locate validator with (#{container_key})"
|
116
|
+
end
|
117
|
+
|
118
|
+
container[container_key]
|
119
|
+
end
|
120
|
+
|
121
|
+
# return [Bool]
|
122
|
+
def validators?
|
123
|
+
!validators.empty?
|
124
|
+
end
|
125
|
+
|
126
|
+
# Used when resolving inputs to determine if we should apply any
|
127
|
+
# validation
|
128
|
+
#
|
129
|
+
# return [Bool]
|
130
|
+
def skip_validation?
|
131
|
+
@skip_validation == true
|
132
|
+
end
|
133
|
+
|
134
|
+
# Dsl method to allow a handler to tell the system not to validate
|
135
|
+
# anything and use the raw inputs
|
136
|
+
#
|
137
|
+
# return [Bool]
|
138
|
+
def skip_validation!
|
139
|
+
@skip_validation = true
|
140
|
+
end
|
141
|
+
|
142
|
+
# Validate all inputs using the list of validators that were assigned
|
143
|
+
# using the dsl methods.
|
144
|
+
#
|
145
|
+
# @param inputs [Hash]
|
146
|
+
# @return Appfuel::Response
|
147
|
+
def resolve_inputs(inputs = {})
|
148
|
+
return ok(inputs) if skip_validation?
|
149
|
+
return ok({}) unless validators?
|
150
|
+
|
151
|
+
response = nil
|
152
|
+
has_failed = false
|
153
|
+
validators.each do |validator|
|
154
|
+
if validator.pipe?
|
155
|
+
result = handle_validator_pipe(validator, inputs)
|
156
|
+
inputs = result unless result == false
|
157
|
+
next
|
158
|
+
end
|
159
|
+
|
160
|
+
result = validator.call(inputs)
|
161
|
+
if result.success? && !has_failed
|
162
|
+
response = handle_successful_inputs(result, response)
|
163
|
+
next
|
164
|
+
end
|
165
|
+
|
166
|
+
return error(result.errors(full: true)) if validator.fail_fast?
|
167
|
+
has_failed = true
|
168
|
+
response = handle_error_inputs(result, response)
|
169
|
+
end
|
170
|
+
|
171
|
+
fail "multi validators can not be only Procs" if response.nil?
|
172
|
+
|
173
|
+
response
|
174
|
+
end
|
175
|
+
|
176
|
+
private
|
177
|
+
|
178
|
+
# Decodes the given key into a dependency injection namespace that is
|
179
|
+
# used to find a validator or pipe in the app container. It decodes
|
180
|
+
# to a global or feature namespaces.
|
181
|
+
#
|
182
|
+
# @param key [String]
|
183
|
+
# #return [String]
|
184
|
+
def convert_to_container_key(key)
|
185
|
+
parts = key.to_s.split('.')
|
186
|
+
last = parts.last
|
187
|
+
first = parts.first
|
188
|
+
case first
|
189
|
+
when 'global'
|
190
|
+
"global.validators.#{last}"
|
191
|
+
when 'global-pipe'
|
192
|
+
"global.validator-pipes.#{last}"
|
193
|
+
when 'pipe'
|
194
|
+
"#{container_feature_key}.validator-pipes.#{last}"
|
195
|
+
else
|
196
|
+
"#{container_feature_key}.validators.#{first}"
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
# Create a validator for the handler or load it from the container
|
201
|
+
# depending on if a block is given
|
202
|
+
#
|
203
|
+
# @param key [String] key used to identify the item
|
204
|
+
# @param opts [Hash]
|
205
|
+
# @return [
|
206
|
+
# Appfuel::Validation::Validator,
|
207
|
+
# Appfuel::Validation::ValidatorPipe
|
208
|
+
# ]
|
209
|
+
def build_validator(key, opts = {}, &block)
|
210
|
+
return load_validator(key, opts) unless block_given?
|
211
|
+
|
212
|
+
Appfuel::Validation.build_validator(key, opts, &block)
|
213
|
+
end
|
214
|
+
|
215
|
+
# Creates a response the first time otherwise it merges the results
|
216
|
+
# from the last validator into the response
|
217
|
+
#
|
218
|
+
# @param results [Hash] successful valid inputs
|
219
|
+
# @param response [Appfuel::Response]
|
220
|
+
def handle_successful_inputs(result, response)
|
221
|
+
if response.nil?
|
222
|
+
ok(result.output)
|
223
|
+
else
|
224
|
+
ok(response.ok.merge(result.output))
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# Creates a response the first time otherwise it merges the error
|
229
|
+
# results from the last validator into the response
|
230
|
+
#
|
231
|
+
# @param results [Hash] successful valid inputs
|
232
|
+
# @param response [Appfuel::Response]
|
233
|
+
def handle_error_inputs(result, response)
|
234
|
+
if response.nil?
|
235
|
+
error(result.errors(full: true))
|
236
|
+
else
|
237
|
+
error(result.errors(full: true).merge(response.error_messages))
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
# Delegates call to the validator pipe
|
242
|
+
#
|
243
|
+
# @param pipe [Appfuel::Validation::ValidatorPipe]
|
244
|
+
# @param inputs [Hash]
|
245
|
+
# @return [Hash]
|
246
|
+
def handle_validator_pipe(pipe, inputs)
|
247
|
+
result = pipe.call(inputs, Dry::Container.new)
|
248
|
+
return false unless result
|
249
|
+
unless result.is_a?(Hash)
|
250
|
+
fail "multi validator proc must return a Hash"
|
251
|
+
end
|
252
|
+
result
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require_relative 'initialize/initializer'
|
2
|
+
|
3
|
+
module Appfuel
|
4
|
+
module Initialize
|
5
|
+
class << self
|
6
|
+
|
7
|
+
# Dsl used to add an initializer into to the application container. This
|
8
|
+
# will add an initializer into the default app unless another name is
|
9
|
+
# given.
|
10
|
+
#
|
11
|
+
# @param name [String] name of the initializer
|
12
|
+
# @param envs [String, Symbol, Array] A env,list of envs this can run in
|
13
|
+
# @param app_name [String] name of app for this initializer
|
14
|
+
def define(namespace_key, name, envs = [], app_name = nil, &block)
|
15
|
+
initializers = Appfuel.resolve("#{namespace_key}.initializers", app_name)
|
16
|
+
initializers << Initializer.new(name, envs, &block)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Populate configuration definition that is in the container and
|
20
|
+
# add its results to the container. It also adds the environment from
|
21
|
+
# the config to the container for easier access.
|
22
|
+
#
|
23
|
+
# @raises RuntimeError when :env is not in the config
|
24
|
+
#
|
25
|
+
#
|
26
|
+
# @param container [Dry::Container]
|
27
|
+
# @param params [Hash]
|
28
|
+
# @option overrides [Hash] used to override config values
|
29
|
+
# @option env [ENV] used to collect environment variables
|
30
|
+
# @return [Dry::Container] that was passed in
|
31
|
+
def handle_configuration(container, params = {})
|
32
|
+
overrides = params[:overrides] || {}
|
33
|
+
env = params[:env] || ENV
|
34
|
+
definition = container['config_definition']
|
35
|
+
|
36
|
+
config = definition.populate(env: env, overrides: overrides)
|
37
|
+
env = config.fetch(:env) { fail "key (:env) is missing from config" }
|
38
|
+
|
39
|
+
container.register(:config, config)
|
40
|
+
container.register(:env, env)
|
41
|
+
|
42
|
+
container
|
43
|
+
end
|
44
|
+
|
45
|
+
def handle_repository_mapping(container, params = {})
|
46
|
+
initializer = container[:repository_initializer]
|
47
|
+
initializer.call(container)
|
48
|
+
end
|
49
|
+
|
50
|
+
# This will initialize the app by handling configuration and running
|
51
|
+
# all the initilizers, which will result in an app container that has
|
52
|
+
# registered the config, env, and anything else the initializers
|
53
|
+
# decide to add.
|
54
|
+
#
|
55
|
+
# @param params [Hash]
|
56
|
+
# @option app_name [String] name of the app to initialize, (optional)
|
57
|
+
# @return [Dry::Container]
|
58
|
+
def run(params = {})
|
59
|
+
app_name = params.fetch(:app_name) { Appfuel.default_app_name }
|
60
|
+
container = Appfuel.app_container(app_name)
|
61
|
+
handle_configuration(container, params)
|
62
|
+
handle_repository_mapping(container, params)
|
63
|
+
|
64
|
+
Appfuel.run_initializers('global', container, params[:exclude] || [])
|
65
|
+
|
66
|
+
container
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Appfuel
|
2
|
+
module Initialize
|
3
|
+
# The client application will declare a series of initializer blocks.
|
4
|
+
# Each of these blocks are represented as this class. This allows us
|
5
|
+
# to save the block to be later executed along with info about which
|
6
|
+
# environments this can run on
|
7
|
+
class Initializer
|
8
|
+
attr_reader :name, :envs, :code
|
9
|
+
|
10
|
+
# Ensure each environment is stored as a lowercased string, convert
|
11
|
+
# the name to a string as save the block to be executed later
|
12
|
+
#
|
13
|
+
# @raises ArgumentError, when env is not an Array
|
14
|
+
# @raises ArgumentError, when block is not given
|
15
|
+
#
|
16
|
+
# @param name [String, Symbol] name to identify this initializer
|
17
|
+
# @param env [String, Symbol, Array] env or list of envs to execute on
|
18
|
+
# @param blk [Proc] the code to be excuted
|
19
|
+
# @return [Initializer]
|
20
|
+
def initialize(name, env = [], &block)
|
21
|
+
@name = name.to_s
|
22
|
+
@envs = []
|
23
|
+
|
24
|
+
env = [env] if env.is_a?(String) || env.is_a?(Symbol)
|
25
|
+
env = [] if env.nil?
|
26
|
+
|
27
|
+
unless env.is_a?(Array)
|
28
|
+
fail ArgumentError, "environments must be a string, symbol or array"
|
29
|
+
end
|
30
|
+
env.each {|item| add_env(item) }
|
31
|
+
|
32
|
+
fail ArgumentError, "initializer requires a block" unless block_given?
|
33
|
+
@code = block
|
34
|
+
end
|
35
|
+
|
36
|
+
# Determines which env this is allowed to execute on. No enironment means
|
37
|
+
# it it is allow to execute on all
|
38
|
+
#
|
39
|
+
# @param env [String, Symbol]
|
40
|
+
# @return [Bool]
|
41
|
+
def env_allowed?(env)
|
42
|
+
return true if envs.empty?
|
43
|
+
|
44
|
+
envs.include?(env.to_s.downcase)
|
45
|
+
end
|
46
|
+
|
47
|
+
# @raises RuntimeError, when env already exists
|
48
|
+
#
|
49
|
+
# @param name [String, Symbol] name of the environment
|
50
|
+
# @return [Array]
|
51
|
+
def add_env(name)
|
52
|
+
name = name.to_s.downcase
|
53
|
+
fail "env already exists" if envs.include?(name)
|
54
|
+
envs << name.to_s.downcase
|
55
|
+
end
|
56
|
+
|
57
|
+
# Delegate to executing the stored code
|
58
|
+
#
|
59
|
+
# @param config [Hash]
|
60
|
+
# @param app_container [Dry::Container]
|
61
|
+
# @return nil
|
62
|
+
def call(config, container)
|
63
|
+
code.call(config, container)
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|