tty-config 0.1.0 → 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 +4 -4
- data/CHANGELOG.md +10 -1
- data/README.md +67 -14
- data/lib/tty/config.rb +62 -3
- data/lib/tty/config/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b7d2891f50d6ec7735ddf4c68e811d2b9726d5f1
|
4
|
+
data.tar.gz: a4c6a91a265b84c849aa7be416eb0062d9253ff7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f735b5c715194df5873b78bee19062392effc855f712659ab3fc07cd6c87737eedcc79fbce15362ecbe473df226090a3d76c00c1438f0f522c265f742141c50
|
7
|
+
data.tar.gz: 282c1817e5c73f18bf1be3c0b2c32d41d142a22a894ab5c528901bdfda0a573cbda9cfe74961b92dfe63ee91e89d89f2e06649cd4c208c7e85db47e226dd2ce5
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,16 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
|
+
## [v0.2.0] - 2018-05-07
|
4
|
+
|
5
|
+
### Added
|
6
|
+
* Add ability to validate values for arbitrarily nested keys
|
7
|
+
|
8
|
+
### Changed
|
9
|
+
* Change to ensure that either value or block is provided when setting a value
|
10
|
+
|
3
11
|
## [v0.1.0] - 2018-04-14
|
4
12
|
|
5
13
|
* Initial implementation and release
|
6
14
|
|
7
|
-
[v0.
|
15
|
+
[v0.2.0]: https://github.com/piotrmurach/tty-config/compare/v0.1.0...v0.2.0
|
16
|
+
[v0.1.0]: https://github.com/piotrmurach/tty-config/compare/v0.1.0
|
data/README.md
CHANGED
@@ -44,6 +44,7 @@ Or install it yourself as:
|
|
44
44
|
## Contents
|
45
45
|
|
46
46
|
* [1. Usage](#1-usage)
|
47
|
+
* [1.1 app](#11-app)
|
47
48
|
* [2. Interface](#2-interface)
|
48
49
|
* [2.1 set](#21-set)
|
49
50
|
* [2.2 set_if_empty](#22-set_if_empty)
|
@@ -53,13 +54,14 @@ Or install it yourself as:
|
|
53
54
|
* [2.6 append](#26-append)
|
54
55
|
* [2.7 remove](#27-remove)
|
55
56
|
* [2.8 delete](#28-delete)
|
56
|
-
* [2.9
|
57
|
-
* [2.10
|
58
|
-
* [2.11
|
59
|
-
* [2.12
|
60
|
-
* [2.13
|
61
|
-
* [2.14
|
62
|
-
* [2.15
|
57
|
+
* [2.9 validate](#29-validate)
|
58
|
+
* [2.10 filename=](#210-filename)
|
59
|
+
* [2.11 extname=](#211-extname)
|
60
|
+
* [2.12 append_path](#212-append_path)
|
61
|
+
* [2.13 prepend_path](#213-prepend_path)
|
62
|
+
* [2.14 read](#214-read)
|
63
|
+
* [2.15 write](#215-write)
|
64
|
+
* [2.16 persisted?](#216-persisted)
|
63
65
|
|
64
66
|
## 1. Usage
|
65
67
|
|
@@ -119,6 +121,28 @@ Finally, read in configuration back again:
|
|
119
121
|
config.read
|
120
122
|
```
|
121
123
|
|
124
|
+
### 1.1 app
|
125
|
+
|
126
|
+
An example of an application configuration:
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
class App
|
130
|
+
attr_reader :config
|
131
|
+
|
132
|
+
def initialize
|
133
|
+
@config = TTY::Config.new
|
134
|
+
@config.filename = 'investments'
|
135
|
+
@config.extname = '.toml'
|
136
|
+
@config.append_path Dir.pwd
|
137
|
+
@config.append_path Dir.home
|
138
|
+
end
|
139
|
+
|
140
|
+
def self.config
|
141
|
+
@config ||= self.class.new.config
|
142
|
+
end
|
143
|
+
end
|
144
|
+
```
|
145
|
+
|
122
146
|
## 2. Interface
|
123
147
|
|
124
148
|
### 2.1 set
|
@@ -282,7 +306,36 @@ config.delete(:settings, :base)
|
|
282
306
|
# "USD"
|
283
307
|
```
|
284
308
|
|
285
|
-
### 2.9
|
309
|
+
### 2.9 validate
|
310
|
+
|
311
|
+
To ensure consistency of the data, you can validate values being set at arbitrarily deep keys using `validate` method, that takes an arbitrarily nested key as its argument and a validation block.
|
312
|
+
|
313
|
+
```ruby
|
314
|
+
config.validate(:settings, :base) do |key, value|
|
315
|
+
if value.length != 3
|
316
|
+
raise TTY::Config::ValidationError, "Currency code needs to be 3 chars long."
|
317
|
+
end
|
318
|
+
end
|
319
|
+
```
|
320
|
+
|
321
|
+
You can assign multiple validations for a given key and each of them will be run in the order they were registered when checking a value.
|
322
|
+
|
323
|
+
When setting value all the validaitons will be run:
|
324
|
+
|
325
|
+
```ruby
|
326
|
+
config.set(:settings, :base, value: 'PL')
|
327
|
+
# raises TTY::Config::ValidationError, 'Currency code needs to be 3 chars long.'
|
328
|
+
```
|
329
|
+
|
330
|
+
If the value s provided as a proc or a block then the validation will be delayed until the value is actually read:
|
331
|
+
|
332
|
+
```ruby
|
333
|
+
config.set(:settings, :base) { 'PL' }
|
334
|
+
config.fetch(:settings, :base)
|
335
|
+
# raises TTY::Config::ValidationError, 'Currency code needs to be 3 chars long.'
|
336
|
+
```
|
337
|
+
|
338
|
+
### 2.10 filename=
|
286
339
|
|
287
340
|
By default, **TTY::Config** searches for `config` named configuration file. To change this use `filename=` method without the extension name:
|
288
341
|
|
@@ -292,7 +345,7 @@ config.filename = 'investments'
|
|
292
345
|
|
293
346
|
Then any supported extensions will be search for such as `.yml`, `.json` and `.toml`.
|
294
347
|
|
295
|
-
### 2.
|
348
|
+
### 2.11 extname=
|
296
349
|
|
297
350
|
By default '.yml' extension is used to write configuration out to a file but you can change that with `extname=`:
|
298
351
|
|
@@ -300,7 +353,7 @@ By default '.yml' extension is used to write configuration out to a file but you
|
|
300
353
|
config.extname = '.toml'
|
301
354
|
```
|
302
355
|
|
303
|
-
### 2.
|
356
|
+
### 2.12 append_path
|
304
357
|
|
305
358
|
You need to tell the **TTY::Config** where to search for configuration files. To search multiple paths for a configuration file use `append_path` or `prepend_path` methods.
|
306
359
|
|
@@ -314,7 +367,7 @@ config.append_path(Dir.pwd) # look in current working directory
|
|
314
367
|
|
315
368
|
None of these paths are required, but you should provide at least one path if you wish to read configuration file.
|
316
369
|
|
317
|
-
### 2.
|
370
|
+
### 2.13 prepend_path
|
318
371
|
|
319
372
|
The `prepend_path` allows you to add configuration search paths that should be searched first.
|
320
373
|
|
@@ -323,7 +376,7 @@ config.append_path(Dir.pwd) # look in current working directory second
|
|
323
376
|
config.prepend_path(Dir.home) # look in user's home directory first
|
324
377
|
```
|
325
378
|
|
326
|
-
### 2.
|
379
|
+
### 2.14 read
|
327
380
|
|
328
381
|
There are two ways for reading configuration files and both use the `read` method.
|
329
382
|
|
@@ -346,7 +399,7 @@ However, you can also specify directly the file to read without setting up any s
|
|
346
399
|
config.read('./investments.toml')
|
347
400
|
```
|
348
401
|
|
349
|
-
### 2.
|
402
|
+
### 2.15 write
|
350
403
|
|
351
404
|
By default **TTY::Config**, persists configuration file in the current working directory with a `config.yml` name. However, you can change that by specifying the filename and extension type:
|
352
405
|
|
@@ -376,7 +429,7 @@ config.write(force: true) # overwrite any found config fi
|
|
376
429
|
config.write('./investments.toml', force: true) # overwrite specific config file
|
377
430
|
```
|
378
431
|
|
379
|
-
### 2.
|
432
|
+
### 2.16 persisted?
|
380
433
|
|
381
434
|
To check if a configuration file exists within the configured search paths use `persisted?` method:
|
382
435
|
|
data/lib/tty/config.rb
CHANGED
@@ -12,6 +12,8 @@ module TTY
|
|
12
12
|
WriteError = Class.new(StandardError)
|
13
13
|
# Erorrr raised when setting unknown file extension
|
14
14
|
UnsupportedExtError = Class.new(StandardError)
|
15
|
+
# Error raised when validation assertion fails
|
16
|
+
ValidationError = Class.new(StandardError)
|
15
17
|
|
16
18
|
def self.coerce(hash, &block)
|
17
19
|
new(normalize_hash(hash), &block)
|
@@ -44,6 +46,10 @@ module TTY
|
|
44
46
|
# @api public
|
45
47
|
attr_reader :extname
|
46
48
|
|
49
|
+
# The validations for this configuration
|
50
|
+
# @api public
|
51
|
+
attr_reader :validators
|
52
|
+
|
47
53
|
def initialize(settings = {})
|
48
54
|
@location_paths = []
|
49
55
|
@settings = settings
|
@@ -88,10 +94,21 @@ module TTY
|
|
88
94
|
# @api public
|
89
95
|
def set(*keys, value: nil, &block)
|
90
96
|
assert_either_value_or_block(value, block)
|
97
|
+
|
91
98
|
keys = convert_to_keys(keys)
|
99
|
+
key = flatten_keys(keys)
|
100
|
+
value_to_eval = block || value
|
101
|
+
|
102
|
+
if validators.key?(key)
|
103
|
+
if callable_without_params?(value_to_eval)
|
104
|
+
value_to_eval = delay_validation(key, value_to_eval)
|
105
|
+
else
|
106
|
+
assert_valid(key, value)
|
107
|
+
end
|
108
|
+
end
|
92
109
|
|
93
110
|
deepest_setting = deep_set(@settings, *keys[0...-1])
|
94
|
-
deepest_setting[keys.last] =
|
111
|
+
deepest_setting[keys.last] = value_to_eval
|
95
112
|
deepest_setting[keys.last]
|
96
113
|
end
|
97
114
|
|
@@ -165,6 +182,36 @@ module TTY
|
|
165
182
|
deep_delete(*keys, @settings)
|
166
183
|
end
|
167
184
|
|
185
|
+
# Register validation for a nested key
|
186
|
+
#
|
187
|
+
# @api public
|
188
|
+
def validate(*keys, &validator)
|
189
|
+
key = flatten_keys(keys)
|
190
|
+
values = validators[key] || []
|
191
|
+
values << validator
|
192
|
+
validators[key] = values
|
193
|
+
end
|
194
|
+
|
195
|
+
# Check if key passes all registered validations
|
196
|
+
#
|
197
|
+
# @api private
|
198
|
+
def assert_valid(key, value)
|
199
|
+
validators[key].each do |validator|
|
200
|
+
validator.call(key, value)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
# Delay key validation
|
205
|
+
#
|
206
|
+
# @api private
|
207
|
+
def delay_validation(key, callback)
|
208
|
+
-> do
|
209
|
+
val = callback.()
|
210
|
+
assert_valid(key, val)
|
211
|
+
val
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
168
215
|
# @api private
|
169
216
|
def find_file
|
170
217
|
@location_paths.each do |location_path|
|
@@ -245,8 +292,11 @@ module TTY
|
|
245
292
|
end
|
246
293
|
|
247
294
|
def assert_either_value_or_block(value, block)
|
248
|
-
|
249
|
-
|
295
|
+
if value.nil? && block.nil?
|
296
|
+
raise ArgumentError, "Need to set either value or block"
|
297
|
+
elsif !(value.nil? || block.nil?)
|
298
|
+
raise ArgumentError, "Can't set both value and block"
|
299
|
+
end
|
250
300
|
end
|
251
301
|
|
252
302
|
# Set value under deeply nested keys
|
@@ -295,6 +345,15 @@ module TTY
|
|
295
345
|
end
|
296
346
|
end
|
297
347
|
|
348
|
+
def flatten_keys(keys)
|
349
|
+
first_key = keys[0]
|
350
|
+
if first_key.to_s.include?(key_delim)
|
351
|
+
first_key
|
352
|
+
else
|
353
|
+
keys.join(key_delim)
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
298
357
|
# Fetch value under deeply nested keys with indiffernt key access
|
299
358
|
#
|
300
359
|
# @param [Hash] settings
|
data/lib/tty/config/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tty-config
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Murach
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-05-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|