knowledge 0.1.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/.gitignore +13 -0
- data/.rspec +3 -0
- data/.rubocop.yml +10 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +16 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +71 -0
- data/LICENSE.md +675 -0
- data/README.md +107 -0
- data/Rakefile +8 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/knowledge.gemspec +49 -0
- data/lib/knowledge.rb +55 -0
- data/lib/knowledge/adapters.rb +17 -0
- data/lib/knowledge/adapters/base.rb +51 -0
- data/lib/knowledge/adapters/environment.rb +36 -0
- data/lib/knowledge/adapters/file.rb +25 -0
- data/lib/knowledge/adapters/key_value.rb +35 -0
- data/lib/knowledge/configuration.rb +50 -0
- data/lib/knowledge/exceptions.rb +47 -0
- data/lib/knowledge/initializer.rb +77 -0
- data/lib/knowledge/learner.rb +381 -0
- data/lib/knowledge/setter.rb +39 -0
- data/lib/knowledge/version.rb +5 -0
- metadata +171 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Knowledge
|
4
|
+
#
|
5
|
+
# === Description ===
|
6
|
+
#
|
7
|
+
# This error class should be considered as the lib's standard error.
|
8
|
+
# All error classes inherit from this one.
|
9
|
+
# The goal is to be able to rescue Knowledge::Error outside the lib and catch them all.
|
10
|
+
#
|
11
|
+
# === Usage ===
|
12
|
+
#
|
13
|
+
# You have many examples behind. Just inherit from this class and it's ok.
|
14
|
+
#
|
15
|
+
# @example:
|
16
|
+
# class ::MyCustomKnowledgeError < Knowledge::Error; end
|
17
|
+
#
|
18
|
+
class Error < ::StandardError; end
|
19
|
+
|
20
|
+
#
|
21
|
+
# === Description ===
|
22
|
+
#
|
23
|
+
# This error is used when, at some point, we can't find the adapter we're looking for
|
24
|
+
#
|
25
|
+
class AdapterNotFound < Error; end
|
26
|
+
|
27
|
+
#
|
28
|
+
# === Description ===
|
29
|
+
#
|
30
|
+
# This error is used when an adapter has no #run method declared
|
31
|
+
#
|
32
|
+
class AdapterRunMethodNotImplemented < Error; end
|
33
|
+
|
34
|
+
#
|
35
|
+
# === Description ===
|
36
|
+
#
|
37
|
+
# This error is pretty generic and is meant to be used when we're not able to gather infos in order to set vars.
|
38
|
+
#
|
39
|
+
class LearnError < Error; end
|
40
|
+
|
41
|
+
#
|
42
|
+
# === Description ===
|
43
|
+
#
|
44
|
+
# This error is used when we fail registering an adapter.
|
45
|
+
#
|
46
|
+
class RegisterError < Error; end
|
47
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Knowledge
|
4
|
+
#
|
5
|
+
# === Description ===
|
6
|
+
#
|
7
|
+
# We all need an initializer, here's this lib's initializer.
|
8
|
+
# Its role is to gather all informations and run the enabled adapters.
|
9
|
+
#
|
10
|
+
# === Usage ===
|
11
|
+
#
|
12
|
+
# @example:
|
13
|
+
# Knowledge::Initializer.new(adapters: adapters, params: { foo: :bar }, setter: setter, variables: variables).run
|
14
|
+
#
|
15
|
+
# Knowledge::Initializer.run(adapters: adapters, params: { foo: :bar }, setter: setter, variables: variables)
|
16
|
+
#
|
17
|
+
# === Attributes ===
|
18
|
+
#
|
19
|
+
# @attr_reader [Array<String | Symbol>] adapters
|
20
|
+
# @attr_reader [Hash] params
|
21
|
+
# @attr_reader [Class] setter
|
22
|
+
# @attr_reader [Hash] variables
|
23
|
+
#
|
24
|
+
class Initializer
|
25
|
+
# == Attributes ==================================================================================================
|
26
|
+
attr_reader :adapters, :params, :setter, :variables
|
27
|
+
|
28
|
+
# == Constructor =================================================================================================
|
29
|
+
#
|
30
|
+
# @option [Array<Class>] :adapters
|
31
|
+
# @option [Hash] :params
|
32
|
+
# @option [Class] :setter
|
33
|
+
# @option [Hash] :variables
|
34
|
+
#
|
35
|
+
def initialize(adapters:, params:, setter:, variables:)
|
36
|
+
@adapters = adapters
|
37
|
+
@params = params
|
38
|
+
@setter = setter
|
39
|
+
@variables = variables
|
40
|
+
end
|
41
|
+
|
42
|
+
# == Class methods ===============================================================================================
|
43
|
+
class << self
|
44
|
+
#
|
45
|
+
# === Description ===
|
46
|
+
#
|
47
|
+
# Instanciates the current class and runs all registered adapters.
|
48
|
+
#
|
49
|
+
# === Parameters ===
|
50
|
+
#
|
51
|
+
# @option [Hash{Symbol => Class}] :adapters
|
52
|
+
# @option [Hash] :params
|
53
|
+
# @option [Class] :setter
|
54
|
+
# @option [Hash] :variables
|
55
|
+
#
|
56
|
+
def run(adapters:, params:, setter:, variables: {})
|
57
|
+
new(adapters: adapters, params: params, setter: setter, variables: variables).run
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# == Instance methods ============================================================================================
|
62
|
+
#
|
63
|
+
# === Description ===
|
64
|
+
#
|
65
|
+
# Runs all registered adapters.
|
66
|
+
#
|
67
|
+
def run
|
68
|
+
Hash(adapters).each do |name, adapter|
|
69
|
+
adapter.new(
|
70
|
+
params: params[name.to_sym] || params,
|
71
|
+
setter: setter,
|
72
|
+
variables: variables[name.to_sym] || variables
|
73
|
+
).run
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,381 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
require 'knowledge/initializer'
|
6
|
+
require 'knowledge/adapters'
|
7
|
+
require 'knowledge/setter'
|
8
|
+
|
9
|
+
module Knowledge
|
10
|
+
#
|
11
|
+
# === Description ===
|
12
|
+
#
|
13
|
+
# Knowledge is something that needs some learning.
|
14
|
+
#
|
15
|
+
# === Usage ===
|
16
|
+
#
|
17
|
+
# @example:
|
18
|
+
#
|
19
|
+
# learner = Knowledge::Learner.new
|
20
|
+
#
|
21
|
+
# === Attributes ===
|
22
|
+
#
|
23
|
+
# @attr_reader [Hash] additionnal_params
|
24
|
+
# @attr_reader [Hash{Symbol => Class}] available_adapters
|
25
|
+
# @attr_reader [Hash{Symbol => Class}] enabled_adapters
|
26
|
+
# @attr [Class] setter
|
27
|
+
# @attr_reader [Hash] variables
|
28
|
+
#
|
29
|
+
class Learner
|
30
|
+
# == Attributes ====================================================================================================
|
31
|
+
attr_accessor :setter
|
32
|
+
attr_reader :additionnal_params, :available_adapters, :enabled_adapters, :variables
|
33
|
+
|
34
|
+
# == Constructor ===================================================================================================
|
35
|
+
def initialize
|
36
|
+
@additionnal_params = {}
|
37
|
+
@available_adapters = {}
|
38
|
+
@enabled_adapters = {}
|
39
|
+
@setter = ::Knowledge::Setter.new
|
40
|
+
@variables = {}
|
41
|
+
end
|
42
|
+
|
43
|
+
# == Class methods =================================================================================================
|
44
|
+
class << self
|
45
|
+
attr_reader :adapters
|
46
|
+
|
47
|
+
def register_default_adapter(names:, klass:)
|
48
|
+
@adapters ||= {}
|
49
|
+
|
50
|
+
names.each { |name| @adapters[name.to_sym] = klass }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# == Instance methods ==============================================================================================
|
55
|
+
#
|
56
|
+
# === Description ===
|
57
|
+
#
|
58
|
+
# Gathers all the knowledge and put it into your app.
|
59
|
+
#
|
60
|
+
# === Usage ===
|
61
|
+
#
|
62
|
+
# @example:
|
63
|
+
# learner = Knowledge::Learner.new
|
64
|
+
# # Do some config (add adapters, define your setter, etc.)
|
65
|
+
# learner.gather!
|
66
|
+
#
|
67
|
+
def gather!
|
68
|
+
::Knowledge::Initializer.new(
|
69
|
+
adapters: enabled_adapters,
|
70
|
+
params: additionnal_params,
|
71
|
+
setter: setter,
|
72
|
+
variables: variables
|
73
|
+
).run
|
74
|
+
end
|
75
|
+
|
76
|
+
# == Adapters methods ============================================================================================
|
77
|
+
#
|
78
|
+
# === Description ===
|
79
|
+
#
|
80
|
+
# Sets additional params to be passed to the adapter through params option.
|
81
|
+
#
|
82
|
+
# === Usage ===
|
83
|
+
#
|
84
|
+
# @example:
|
85
|
+
# learner = Knowledge::Learner.new
|
86
|
+
# learner.add_adapter_param(adapter: :custom, name: :base_path, value: '/base/path')
|
87
|
+
#
|
88
|
+
# === Parameters ===
|
89
|
+
#
|
90
|
+
# @option [String | Symbol] :adapter
|
91
|
+
# @option [String | Symbol] :name
|
92
|
+
# @option [any] :value
|
93
|
+
#
|
94
|
+
def add_adapter_param(adapter:, name:, value:)
|
95
|
+
@additionnal_params[adapter.to_sym] ||= {}
|
96
|
+
@additionnal_params[adapter.to_sym][name] = value
|
97
|
+
end
|
98
|
+
|
99
|
+
#
|
100
|
+
# === Description ===
|
101
|
+
#
|
102
|
+
# Sets additional params to be passed to the adapter through params option.
|
103
|
+
#
|
104
|
+
# === Usage ===
|
105
|
+
#
|
106
|
+
# @example:
|
107
|
+
# learner = Knowledge::Learner.new
|
108
|
+
# learner.add_adapter_param(name: :base_path, value: '/base/path')
|
109
|
+
#
|
110
|
+
# === Parameters ===
|
111
|
+
#
|
112
|
+
# @option [String | Symbol] :adapter
|
113
|
+
# @option [any] :params
|
114
|
+
#
|
115
|
+
def add_adapter_params(adapter:, params:)
|
116
|
+
@additionnal_params[adapter.to_sym] = params
|
117
|
+
end
|
118
|
+
|
119
|
+
#
|
120
|
+
# === Description ===
|
121
|
+
#
|
122
|
+
# Disables an adapter.
|
123
|
+
#
|
124
|
+
# === Usage ===
|
125
|
+
#
|
126
|
+
# @example:
|
127
|
+
# learner = Knowledge::Learner.new
|
128
|
+
# learner.register_adapter(name: :my_adapter, klass: MyAdapter, enable: true)
|
129
|
+
# # Somewhere else in the code
|
130
|
+
# learner.disable_adapter(name: :my_adapter) if should_disable_custom_adapter?
|
131
|
+
#
|
132
|
+
# === Parameters ===
|
133
|
+
#
|
134
|
+
# @option [String | Symbol] :name
|
135
|
+
#
|
136
|
+
def disable_adapter(name:)
|
137
|
+
@enabled_adapters.delete(name.to_sym)
|
138
|
+
end
|
139
|
+
|
140
|
+
#
|
141
|
+
# === Description ===
|
142
|
+
#
|
143
|
+
# Enables an adapter.
|
144
|
+
#
|
145
|
+
# === Usage ===
|
146
|
+
#
|
147
|
+
# @example:
|
148
|
+
# learner = Knowledge::Learner.new
|
149
|
+
# learner.register_adapter(name: :my_adapter, klass: MyAdapter)
|
150
|
+
# learner.enable_adapter(name: :my_adapter)
|
151
|
+
#
|
152
|
+
# === Errors ===
|
153
|
+
#
|
154
|
+
# @raises [Knowledge::AdapterNotFound] if adapter is not available
|
155
|
+
#
|
156
|
+
# === Parameters ===
|
157
|
+
#
|
158
|
+
# @option [String | Symbol] :name
|
159
|
+
# @option [Hash | String | nil] :variables
|
160
|
+
#
|
161
|
+
def enable_adapter(name:, variables: nil)
|
162
|
+
_key, klass = available_adapters.find { |key, _klass| key.to_sym == name.to_sym }
|
163
|
+
|
164
|
+
raise Knowledge::AdapterNotFound, "Cannot find \"#{name}\" in available adapters" if klass.nil?
|
165
|
+
|
166
|
+
@enabled_adapters[name.to_sym] = klass
|
167
|
+
set_adapter_variables(name: name, variables: variables)
|
168
|
+
end
|
169
|
+
|
170
|
+
#
|
171
|
+
# === Description ===
|
172
|
+
#
|
173
|
+
# Registers an adapter and enable it if asked.
|
174
|
+
#
|
175
|
+
# === Usage ===
|
176
|
+
#
|
177
|
+
# @example:
|
178
|
+
# learner = Knowledge::Learner.new
|
179
|
+
# learner.register_adapter(name: :my_adapter, klass: MyAdapter, enable: true)
|
180
|
+
#
|
181
|
+
# === Parameters ===
|
182
|
+
#
|
183
|
+
# @option [String | Symbol] :name
|
184
|
+
# @option [Class] :klass
|
185
|
+
# @option [Boolean] :enable
|
186
|
+
# @option [Hash | String | nil] :variables
|
187
|
+
#
|
188
|
+
def register_adapter(name:, klass:, enable: false, variables: nil)
|
189
|
+
@available_adapters[name.to_sym] = klass
|
190
|
+
enable_adapter(name: name) if enable
|
191
|
+
set_adapter_variables(name: name, variables: variables)
|
192
|
+
end
|
193
|
+
|
194
|
+
#
|
195
|
+
# === Description ===
|
196
|
+
#
|
197
|
+
# Sets variables for a given adapter
|
198
|
+
#
|
199
|
+
# === Usage ===
|
200
|
+
#
|
201
|
+
# @example:
|
202
|
+
# learner = Knowledge::Learner.new
|
203
|
+
# learner.set_adapter_variables(name: :default, variables: { foo: :bar })
|
204
|
+
#
|
205
|
+
# === Attributes ===
|
206
|
+
#
|
207
|
+
# @option [String | Symbol] :name
|
208
|
+
# @option [Hash | nil] :variables
|
209
|
+
#
|
210
|
+
def set_adapter_variables(name:, variables: nil)
|
211
|
+
return unless variables
|
212
|
+
|
213
|
+
case variables
|
214
|
+
when Hash
|
215
|
+
set_adapter_variables_by_hash(name: name, variables: variables)
|
216
|
+
when String
|
217
|
+
set_adapter_variables(name: name, variables: yaml_content(variables))
|
218
|
+
else
|
219
|
+
raise "Unknown variables type #{variables.class}"
|
220
|
+
end
|
221
|
+
rescue StandardError => e
|
222
|
+
raise ::Knowledge::LearnError, e.message
|
223
|
+
end
|
224
|
+
|
225
|
+
#
|
226
|
+
# === Description ===
|
227
|
+
#
|
228
|
+
# Sets variables as a hash for a given adapter
|
229
|
+
#
|
230
|
+
# === Usage ===
|
231
|
+
#
|
232
|
+
# @example
|
233
|
+
# learner = Knowledge::Learner.new
|
234
|
+
# learner.set_adapter_variables_by_hash(name: :default, variables: { foo: :bar })
|
235
|
+
#
|
236
|
+
# === Attributes ===
|
237
|
+
#
|
238
|
+
# @option [String | Symbol] :name
|
239
|
+
# @option [Hash] :variables
|
240
|
+
#
|
241
|
+
def set_adapter_variables_by_hash(name:, variables:)
|
242
|
+
variables = variables[name.to_s] if variables.key?(name.to_s)
|
243
|
+
variables = variables[name.to_sym] if variables.key?(name.to_sym)
|
244
|
+
@variables[name.to_sym] = variables
|
245
|
+
end
|
246
|
+
|
247
|
+
#
|
248
|
+
# === Description ===
|
249
|
+
#
|
250
|
+
# Unregisters an adapter and disable it.
|
251
|
+
#
|
252
|
+
# === Usage ===
|
253
|
+
#
|
254
|
+
# @example:
|
255
|
+
# learner = Knowledge::Learner.new
|
256
|
+
# learner.register_adapter(name: :my_adapter, klass: MyAdapter)
|
257
|
+
# # somewhere else in the code
|
258
|
+
# learner.unregister_adapter(name: :my_adapter)
|
259
|
+
#
|
260
|
+
# === Parameters ===
|
261
|
+
#
|
262
|
+
# @option [String | Symbol] :name
|
263
|
+
#
|
264
|
+
def unregister_adapter(name:)
|
265
|
+
disable_adapter(name: name)
|
266
|
+
@available_adapters.delete(name.to_sym)
|
267
|
+
end
|
268
|
+
|
269
|
+
#
|
270
|
+
# === Description ===
|
271
|
+
#
|
272
|
+
# Registers & enables one of the lib's adapters.
|
273
|
+
#
|
274
|
+
# === Usage ===
|
275
|
+
#
|
276
|
+
# @example:
|
277
|
+
# learner = Knowledge::Learner.new
|
278
|
+
# learner.use(name: :ssm)
|
279
|
+
#
|
280
|
+
# === Parameters ===
|
281
|
+
#
|
282
|
+
# @option [String | Symbol] name
|
283
|
+
# @option [Boolean] enable
|
284
|
+
#
|
285
|
+
def use(name:, enable: true)
|
286
|
+
adapter = self.class.adapters[name.to_sym]
|
287
|
+
|
288
|
+
raise ::Knowledge::RegisterError, "Unable to register following: #{name}" if adapter.nil?
|
289
|
+
|
290
|
+
register_adapter(name: name.to_sym, klass: adapter, enable: enable)
|
291
|
+
end
|
292
|
+
|
293
|
+
# == Variables config ==============================================================================================
|
294
|
+
#
|
295
|
+
# === Description ===
|
296
|
+
#
|
297
|
+
# Setter for the variables config.
|
298
|
+
#
|
299
|
+
# === Usage ===
|
300
|
+
#
|
301
|
+
# @example:
|
302
|
+
# learner = Knowledge::Learner.new
|
303
|
+
# learner.variables = { name: 'value' }
|
304
|
+
#
|
305
|
+
# @example:
|
306
|
+
# learner = Knowledge::Learner.new
|
307
|
+
# learner.use(name: :env)
|
308
|
+
# learner.variables = { name: 'ENV_KEY' }
|
309
|
+
#
|
310
|
+
# @example:
|
311
|
+
# learner = Knowledge::Learner.new
|
312
|
+
# learner.variables = 'path/to/vars/config/file.yml'
|
313
|
+
#
|
314
|
+
# === Errors ===
|
315
|
+
#
|
316
|
+
# @raise [Knowledge::LearnError] if parameter isn't a hash or a string
|
317
|
+
#
|
318
|
+
# === Parameters
|
319
|
+
#
|
320
|
+
# @param [String | Hash] path_or_descriptor
|
321
|
+
#
|
322
|
+
def variables=(path_or_descriptor)
|
323
|
+
case path_or_descriptor
|
324
|
+
when Hash
|
325
|
+
@variables = path_or_descriptor
|
326
|
+
when String
|
327
|
+
fetch_variables_config(path_or_descriptor)
|
328
|
+
else
|
329
|
+
raise ::Knowledge::LearnError, "Unable to understand following path or descriptor: #{path_or_descriptor}"
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
protected
|
334
|
+
|
335
|
+
#
|
336
|
+
# === Description ===
|
337
|
+
#
|
338
|
+
# Opens the config file and sets the variable config.
|
339
|
+
#
|
340
|
+
# === Parameters ===
|
341
|
+
#
|
342
|
+
# @param [String] path
|
343
|
+
#
|
344
|
+
def fetch_variables_config(path)
|
345
|
+
descriptor = yaml_content(path)
|
346
|
+
@variables = descriptor[::Knowledge.config.environment.to_s] || descriptor
|
347
|
+
end
|
348
|
+
|
349
|
+
#
|
350
|
+
# === Description ===
|
351
|
+
#
|
352
|
+
# Loads YAML file content
|
353
|
+
#
|
354
|
+
# === Parameters ===
|
355
|
+
#
|
356
|
+
# @param [String] path
|
357
|
+
#
|
358
|
+
# @return [Hash]
|
359
|
+
#
|
360
|
+
def yaml_content(path)
|
361
|
+
::YAML.safe_load(::File.open(path))
|
362
|
+
end
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
# Registering default adapters
|
367
|
+
|
368
|
+
Knowledge::Learner.register_default_adapter(
|
369
|
+
klass: Knowledge::Adapters::Environment,
|
370
|
+
names: %i[env environment env_vars]
|
371
|
+
)
|
372
|
+
|
373
|
+
Knowledge::Learner.register_default_adapter(
|
374
|
+
klass: Knowledge::Adapters::KeyValue,
|
375
|
+
names: %i[default keyval key_value]
|
376
|
+
)
|
377
|
+
|
378
|
+
Knowledge::Learner.register_default_adapter(
|
379
|
+
klass: Knowledge::Adapters::File,
|
380
|
+
names: %i[config file config_file]
|
381
|
+
)
|