env_parser 0.8.0 → 1.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.circleci/config.yml +7 -6
- data/.rubocop.yml +56 -57
- data/.ruby-version +1 -1
- data/Gemfile.lock +58 -28
- data/README.md +252 -176
- data/docs/EnvParser.html +305 -169
- data/docs/EnvParser/AutoregisterFileNotFound.html +143 -0
- data/docs/EnvParser/Error.html +9 -9
- data/docs/EnvParser/TypeAlreadyDefinedError.html +143 -0
- data/docs/EnvParser/Types.html +128 -0
- data/docs/EnvParser/Types/BaseTypes.html +177 -0
- data/docs/EnvParser/Types/ChronologyTypes.html +159 -0
- data/docs/EnvParser/Types/InternetTypes.html +159 -0
- data/docs/EnvParser/UnknownTypeError.html +143 -0
- data/docs/EnvParser/UnparseableAutoregisterSpec.html +143 -0
- data/docs/EnvParser/ValueNotAllowedError.html +143 -0
- data/docs/EnvParser/ValueNotConvertibleError.html +143 -0
- data/docs/EnvParserTypes.html +129 -0
- data/docs/EnvParserTypes/BaseTypes.html +178 -0
- data/docs/EnvParserTypes/ChronologyTypes.html +159 -0
- data/docs/EnvParserTypes/InternetTypes.html +159 -0
- data/docs/EnvParserTypes/TimeTypes.html +158 -0
- data/docs/_index.html +108 -9
- data/docs/class_list.html +3 -3
- data/docs/css/style.css +7 -9
- data/docs/file.README.html +215 -226
- data/docs/file_list.html +2 -2
- data/docs/frames.html +2 -2
- data/docs/index.html +215 -226
- data/docs/js/app.js +69 -3
- data/docs/method_list.html +13 -5
- data/docs/top-level-namespace.html +9 -9
- data/env_parser.gemspec +6 -2
- data/lib/env_parser.rb +111 -83
- data/lib/env_parser/autoregister.rb +3 -0
- data/lib/env_parser/errors.rb +40 -0
- data/lib/env_parser/types.rb +3 -0
- data/lib/env_parser/types/base_types.rb +99 -26
- data/lib/env_parser/types/chronology_types.rb +104 -0
- data/lib/env_parser/types/internet_types.rb +99 -0
- data/lib/env_parser/version.rb +1 -1
- metadata +85 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 6d6d57f56549ef5746444f13eb1b306f6d9e2b46de648a0b218ea890e0b59a79
|
4
|
+
data.tar.gz: 981d6ca140586a772801ff1b705508e30c211bfe412f63260192d89fe8630e2c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2220164e6600e4f4112cdd3d575454aee82cde8a01e3fde5ab06314f6788d414d513296a75c6fe89ea074c1ccf65d418c8a8d1855057bbe06162fca374a61b06
|
7
|
+
data.tar.gz: ba9946219aa484356e80e1dcac0ebbcd745f6c1cd9d94fdf24a06ca35a4deb0ce91fae9cd67ea268509820fdbc30ed2b3f03698a060008d568c87e1f45f130ce
|
data/.circleci/config.yml
CHANGED
@@ -7,7 +7,7 @@ jobs:
|
|
7
7
|
build:
|
8
8
|
docker:
|
9
9
|
# specify the version you desire here
|
10
|
-
- image: circleci/ruby:2.
|
10
|
+
- image: circleci/ruby:2.7.2
|
11
11
|
|
12
12
|
# Specify service dependencies here if necessary
|
13
13
|
# CircleCI maintains a library of pre-built images
|
@@ -48,11 +48,12 @@ jobs:
|
|
48
48
|
mkdir /tmp/test-results
|
49
49
|
TEST_FILES="$(circleci tests glob "spec/**/*_spec.rb" | circleci tests split --split-by=timings)"
|
50
50
|
|
51
|
-
bundle exec rspec --format progress
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
51
|
+
bundle exec rspec --format progress \
|
52
|
+
--format RspecJunitFormatter \
|
53
|
+
--out /tmp/test-results/rspec.xml \
|
54
|
+
--format progress \
|
55
|
+
-- \
|
56
|
+
$TEST_FILES
|
56
57
|
|
57
58
|
# collect reports
|
58
59
|
- store_test_results:
|
data/.rubocop.yml
CHANGED
@@ -1,78 +1,77 @@
|
|
1
1
|
AllCops:
|
2
|
-
TargetRubyVersion: 2.
|
2
|
+
TargetRubyVersion: 2.7
|
3
|
+
NewCops: enable
|
4
|
+
SuggestExtensions: false
|
3
5
|
Include:
|
6
|
+
- "**/*.rb"
|
4
7
|
- "**/*.rake"
|
5
8
|
- "**/Gemfile"
|
6
|
-
- "**/Rakefile"
|
7
|
-
- "**/Capfile"
|
8
|
-
- "**/Berksfile"
|
9
|
-
- "**/Cheffile"
|
10
9
|
Exclude:
|
11
|
-
- "
|
12
|
-
- "db/**/*"
|
10
|
+
- ".git/**/*"
|
13
11
|
- "tmp/**/*"
|
14
12
|
- "true/**/*"
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
Metrics/LineLength:
|
21
|
-
Description: Limit lines to 100 characters.
|
13
|
+
- "vendor/**/*"
|
14
|
+
|
15
|
+
|
16
|
+
Layout/EmptyLineAfterGuardClause:
|
17
|
+
# Add empty line after guard clause.
|
22
18
|
Enabled: false
|
19
|
+
|
20
|
+
Layout/LineLength:
|
21
|
+
# Limit lines to 100 characters.
|
23
22
|
Max: 100
|
24
|
-
Metrics/BlockLength:
|
25
23
|
Exclude:
|
26
24
|
- 'spec/**/*.rb'
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
25
|
+
|
26
|
+
|
27
|
+
Lint/ConstantDefinitionInBlock:
|
28
|
+
# Do not define constants within a block.
|
29
|
+
Exclude:
|
30
|
+
- 'spec/**/*.rb'
|
31
|
+
|
32
|
+
|
33
33
|
Metrics/AbcSize:
|
34
|
-
|
34
|
+
# A calculated magnitude based on number of assignments, branches, and conditions.
|
35
35
|
Enabled: false
|
36
|
-
|
36
|
+
|
37
|
+
Metrics/BlockLength:
|
38
|
+
# Avoid long blocks with many lines.
|
39
|
+
Exclude:
|
40
|
+
- 'spec/**/*.rb'
|
41
|
+
|
37
42
|
Metrics/CyclomaticComplexity:
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
Enabled: false
|
47
|
-
Style/SymbolArray:
|
48
|
-
Description: Use %i or %I for arrays of symbols.
|
49
|
-
Enabled: false
|
50
|
-
Style/RegexpLiteral:
|
51
|
-
Description: Enforces using / or %r around regular expressions.
|
52
|
-
EnforcedStyle: percent_r
|
43
|
+
# A complexity metric that is strongly correlated to the number of test cases needed to validate a method.
|
44
|
+
Max: 10
|
45
|
+
|
46
|
+
Metrics/MethodLength:
|
47
|
+
# Avoid methods longer than 25 lines of code.
|
48
|
+
Max: 25
|
49
|
+
|
50
|
+
|
53
51
|
Style/AsciiComments:
|
54
|
-
#
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
Description: This cop checks for big numeric literals without _ between groups of digits in them.
|
59
|
-
Enabled: false
|
60
|
-
Style/Documentation:
|
61
|
-
Description: Document classes and non-namespace modules.
|
52
|
+
# This cop checks for non-ascii (non-English) characters in comments.
|
53
|
+
#
|
54
|
+
# NLC: Disabling this so we can use non-breaking spaces (' ') in documentation comments, preventing browsers from collapsing
|
55
|
+
# multiple spaces in code blocks.
|
62
56
|
Enabled: false
|
57
|
+
|
58
|
+
Style/BlockDelimiters:
|
59
|
+
# Check for uses of braces or do/end around single line or multi-line blocks.
|
60
|
+
Exclude:
|
61
|
+
- 'spec/**/*.rb'
|
62
|
+
|
63
63
|
Style/ClassAndModuleChildren:
|
64
|
-
|
64
|
+
# Use nested modules/class definitions instead of compact style.
|
65
65
|
Enabled: false
|
66
|
+
|
66
67
|
Style/FrozenStringLiteralComment:
|
68
|
+
# Add the frozen_string_literal comment to the top of files to help transition to frozen string literals by default.
|
67
69
|
Enabled: false
|
68
|
-
|
70
|
+
|
71
|
+
Style/NumericLiterals:
|
72
|
+
# his cop checks for big numeric literals without _ between groups of digits in them.
|
69
73
|
Enabled: false
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
Style/BlockDelimiters:
|
75
|
-
Description: Check for uses of braces or do/end around single line or multi-line blocks.
|
76
|
-
Enabled: true
|
77
|
-
Exclude:
|
78
|
-
- 'spec/**/*.rb'
|
74
|
+
|
75
|
+
Style/RegexpLiteral:
|
76
|
+
# Enforces using / or %r around regular expressions.
|
77
|
+
EnforcedStyle: percent_r
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.7
|
data/Gemfile.lock
CHANGED
@@ -1,51 +1,81 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
env_parser (
|
4
|
+
env_parser (1.3.1)
|
5
5
|
activesupport (>= 5.0.0)
|
6
|
+
chronic
|
7
|
+
chronic_duration
|
6
8
|
|
7
9
|
GEM
|
8
10
|
remote: https://rubygems.org/
|
9
11
|
specs:
|
10
|
-
activesupport (
|
12
|
+
activesupport (6.1.0)
|
11
13
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
12
|
-
i18n (
|
13
|
-
minitest (
|
14
|
-
tzinfo (~>
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
i18n (>= 1.6, < 2)
|
15
|
+
minitest (>= 5.1)
|
16
|
+
tzinfo (~> 2.0)
|
17
|
+
zeitwerk (~> 2.3)
|
18
|
+
ast (2.4.1)
|
19
|
+
chronic (0.10.2)
|
20
|
+
chronic_duration (0.10.6)
|
21
|
+
numerizer (~> 0.1.1)
|
22
|
+
concurrent-ruby (1.1.7)
|
23
|
+
diff-lcs (1.4.4)
|
24
|
+
i18n (1.8.6)
|
18
25
|
concurrent-ruby (~> 1.0)
|
19
|
-
minitest (5.
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
26
|
+
minitest (5.14.2)
|
27
|
+
numerizer (0.1.1)
|
28
|
+
parallel (1.20.1)
|
29
|
+
parser (3.0.0.0)
|
30
|
+
ast (~> 2.4.1)
|
31
|
+
rainbow (3.0.0)
|
32
|
+
rake (13.0.3)
|
33
|
+
regexp_parser (2.0.3)
|
34
|
+
rexml (3.2.4)
|
35
|
+
rspec (3.10.0)
|
36
|
+
rspec-core (~> 3.10.0)
|
37
|
+
rspec-expectations (~> 3.10.0)
|
38
|
+
rspec-mocks (~> 3.10.0)
|
39
|
+
rspec-core (3.10.1)
|
40
|
+
rspec-support (~> 3.10.0)
|
41
|
+
rspec-expectations (3.10.1)
|
28
42
|
diff-lcs (>= 1.2.0, < 2.0)
|
29
|
-
rspec-support (~> 3.
|
30
|
-
rspec-mocks (3.
|
43
|
+
rspec-support (~> 3.10.0)
|
44
|
+
rspec-mocks (3.10.1)
|
31
45
|
diff-lcs (>= 1.2.0, < 2.0)
|
32
|
-
rspec-support (~> 3.
|
33
|
-
rspec-support (3.
|
34
|
-
rspec_junit_formatter (0.
|
46
|
+
rspec-support (~> 3.10.0)
|
47
|
+
rspec-support (3.10.1)
|
48
|
+
rspec_junit_formatter (0.4.1)
|
35
49
|
rspec-core (>= 2, < 4, != 2.12.0)
|
36
|
-
|
37
|
-
|
38
|
-
|
50
|
+
rubocop (1.7.0)
|
51
|
+
parallel (~> 1.10)
|
52
|
+
parser (>= 2.7.1.5)
|
53
|
+
rainbow (>= 2.2.2, < 4.0)
|
54
|
+
regexp_parser (>= 1.8, < 3.0)
|
55
|
+
rexml
|
56
|
+
rubocop-ast (>= 1.2.0, < 2.0)
|
57
|
+
ruby-progressbar (~> 1.7)
|
58
|
+
unicode-display_width (>= 1.4.0, < 2.0)
|
59
|
+
rubocop-ast (1.4.0)
|
60
|
+
parser (>= 2.7.1.5)
|
61
|
+
ruby-progressbar (1.11.0)
|
62
|
+
tzinfo (2.0.4)
|
63
|
+
concurrent-ruby (~> 1.0)
|
64
|
+
unicode-display_width (1.7.0)
|
65
|
+
yard (0.9.26)
|
66
|
+
zeitwerk (2.4.2)
|
39
67
|
|
40
68
|
PLATFORMS
|
41
69
|
ruby
|
42
70
|
|
43
71
|
DEPENDENCIES
|
44
|
-
bundler (~>
|
72
|
+
bundler (~> 2.0)
|
45
73
|
env_parser!
|
46
|
-
rake
|
74
|
+
rake
|
47
75
|
rspec (~> 3.0)
|
48
76
|
rspec_junit_formatter
|
77
|
+
rubocop (= 1.7)
|
78
|
+
yard
|
49
79
|
|
50
80
|
BUNDLED WITH
|
51
|
-
1.
|
81
|
+
2.1.4
|
data/README.md
CHANGED
@@ -1,240 +1,316 @@
|
|
1
|
-
|
1
|
+
[![Gem Version](https://img.shields.io/github/v/release/nestor-custodio/env_parser?color=green&label=gem%20version)](https://rubygems.org/gems/env_parser)
|
2
|
+
[![MIT License](https://img.shields.io/github/license/nestor-custodio/env_parser)](https://github.com/nestor-custodio/env_parser/blob/master/LICENSE.txt)
|
2
3
|
|
3
|
-
If your code uses environment variables, you know that `ENV` will always surface these as strings. Interpreting these strings as the value you *actually* want to see/use takes some work, however: for numbers you need to cast with `#to_i`/`#to_f`, for booleans you need to check for a specific value (`ENV['SOME_VAR'] == 'true'`), etc. Maybe you want to set non-trivial defaults (something other than `0` or `''`)? Maybe you only want to allow values from a limited set? ...
|
4
4
|
|
5
|
-
|
5
|
+
# EnvParser
|
6
6
|
|
7
|
+
If your code uses environment variables, you know that `ENV` will always surface these as strings. Interpreting these strings as the value you *actually* want to see/use takes some work, however: for numbers you need to cast with `to_i` or `to_f` ... for booleans you need to check for a specific value (`ENV['SOME_VAR'] == 'true'`) ... maybe you want to set non-trivial defaults (something other than `0` or `''`)? ... maybe you only want to allow values from a limited set? ...
|
7
8
|
|
8
|
-
|
9
|
+
Things can get out of control pretty fast, especially as the number of environment variables in play grows. Tools like [dotenv](https://github.com/bkeepers/dotenv) help to make sure you're loading the correct **set** of variables, but [EnvParser](https://github.com/nestor-custodio/env_parser) makes **the values themselves** usable with a minimum of effort.
|
9
10
|
|
10
|
-
|
11
|
+
[Full documentation is available here](http://nestor-custodio.github.io/env_parser/EnvParser.html), but do read below for a crash course on availble featues!
|
11
12
|
|
12
|
-
```ruby
|
13
|
-
gem 'env_parser'
|
14
|
-
```
|
15
13
|
|
16
|
-
|
17
|
-
|
18
|
-
$ bundle
|
14
|
+
## Installation
|
19
15
|
|
20
|
-
|
16
|
+
- If your project uses [Bundler](https://github.com/bundler/bundler):
|
17
|
+
- Add one of the following to your application's Gemfile:
|
18
|
+
```ruby
|
19
|
+
## For on-demand usage ...
|
20
|
+
##
|
21
|
+
gem 'env_parser'
|
21
22
|
|
22
|
-
|
23
|
+
## To automatically register ENV
|
24
|
+
## constants per ".env_parser.yml" ...
|
25
|
+
##
|
26
|
+
gem 'env_parser', require: 'env_parser/autoregister'
|
27
|
+
```
|
28
|
+
- And then run a:
|
29
|
+
```shell
|
30
|
+
$ bundle install
|
31
|
+
```
|
23
32
|
|
33
|
+
- Or, you can keep things simple with a manual install:
|
34
|
+
```shell
|
35
|
+
$ gem install env_parser
|
36
|
+
```
|
24
37
|
|
25
|
-
## Using EnvParser
|
26
38
|
|
27
|
-
|
39
|
+
## Syntax Cheat Sheet
|
28
40
|
|
29
41
|
```ruby
|
30
|
-
## Returns ENV
|
31
|
-
## Yields 0 if ENV['TIMEOUT_MS'] is unset or nil.
|
42
|
+
## Returns an ENV value parsed "as" a specific type:
|
32
43
|
##
|
33
|
-
|
44
|
+
EnvParser.parse env_key_as_a_symbol
|
45
|
+
as: … ## ➜ required
|
46
|
+
if_unset: … ## ➜ optional; default value
|
47
|
+
from_set: … ## ➜ optional; an Array or Range
|
48
|
+
validated_by: ->(value) { … } ## ➜ optional; may also be given as a block
|
34
49
|
|
35
|
-
##
|
36
|
-
## If you pass in a Symbol instead of a String, EnvParser
|
37
|
-
## will use the value behind the matching String key in ENV.
|
38
|
-
## (i.e. passing in ENV['X'] is equivalent to passing in :X)
|
50
|
+
## Parse an ENV value and register it as a constant:
|
39
51
|
##
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
<tbody>
|
49
|
-
<tr>
|
50
|
-
<th><code>:as</code> value</th>
|
51
|
-
<th>type returned</th>
|
52
|
-
</tr>
|
53
|
-
</tbody>
|
54
|
-
<tbody>
|
55
|
-
<tr>
|
56
|
-
<td>:string</td>
|
57
|
-
<td>String</td>
|
58
|
-
</tr>
|
59
|
-
<tr>
|
60
|
-
<td>:symbol</td>
|
61
|
-
<td>Symbol</td>
|
62
|
-
</tr>
|
63
|
-
<tr>
|
64
|
-
<td>:boolean</td>
|
65
|
-
<td>TrueValue / FalseValue</td>
|
66
|
-
</tr>
|
67
|
-
<tr>
|
68
|
-
<td>:int / :integer</td>
|
69
|
-
<td>Integer</td>
|
70
|
-
</tr>
|
71
|
-
<tr>
|
72
|
-
<td>:float / :decimal / :number</td>
|
73
|
-
<td>Float</td>
|
74
|
-
</tr>
|
75
|
-
<tr>
|
76
|
-
<td>:json</td>
|
77
|
-
<td>< depends on JSON given ></td>
|
78
|
-
</tr>
|
79
|
-
<tr>
|
80
|
-
<td>:array</td>
|
81
|
-
<td>Array</td>
|
82
|
-
</tr>
|
83
|
-
<tr>
|
84
|
-
<td>:hash</td>
|
85
|
-
<td>Hash</td>
|
86
|
-
</tr>
|
87
|
-
</tbody>
|
88
|
-
</table>
|
89
|
-
|
90
|
-
|
91
|
-
Note JSON is parsed using *quirks-mode* (meaning 'true', '25', and 'null' are all considered valid, parseable JSON).
|
92
|
-
|
93
|
-
|
94
|
-
#### Setting Non-Trivial Defaults
|
95
|
-
|
96
|
-
```ruby
|
97
|
-
## If the ENV variable you want is unset (nil) or blank (''),
|
98
|
-
## the return value is a sensible default for the given "as" type
|
99
|
-
## (0 or 0.0 for numbers, an empty tring, an empty Array or Hash, etc).
|
100
|
-
## Sometimes you want a non-trivial default, however.
|
52
|
+
EnvParser.register env_key_as_a_symbol
|
53
|
+
as: … ## ➜ required
|
54
|
+
within: … ## ➜ optional; Class or Module
|
55
|
+
if_unset: … ## ➜ optional; default value
|
56
|
+
from_set: … ## ➜ optional; an Array or Range
|
57
|
+
validated_by: ->(value) { … } ## ➜ optional; may also be given as a block
|
58
|
+
|
59
|
+
## Registers all ENV variables as spec'ed in ".env_parser.yml":
|
101
60
|
##
|
102
|
-
EnvParser.
|
103
|
-
|
61
|
+
EnvParser.autoregister ## Note this is automatically called if your
|
62
|
+
## Gemfile included the "env_parser" gem with
|
63
|
+
## the "require: 'env_parser/autoregister'" option.
|
104
64
|
|
105
|
-
##
|
65
|
+
## Lets you call "parse" and "register" on ENV itself:
|
106
66
|
##
|
107
|
-
EnvParser.parse
|
67
|
+
EnvParser.add_env_bindings ## ENV.parse will now be a proxy for EnvParser.parse
|
68
|
+
## and ENV.register will now be a proxy for EnvParser.register
|
108
69
|
```
|
109
70
|
|
110
71
|
|
111
|
-
|
72
|
+
## Extended How-To-Use
|
112
73
|
|
113
|
-
|
114
|
-
## Sometimes setting the type alone is a bit too open-ended.
|
115
|
-
## The "from_set" option lets you restrict the set of allowed values.
|
116
|
-
##
|
117
|
-
EnvParser.parse :API_TO_USE, as: :symbol, from_set: %i[internal external]
|
118
|
-
EnvParser.parse :SOME_CUSTOM_NETWORK_PORT, as: :integer, from_set: (1..65535), if_unset: 80
|
74
|
+
#### Basic Usage
|
119
75
|
|
120
|
-
|
121
|
-
##
|
122
|
-
EnvParser.parse :NEGATIVE_NUMBER, as: :integer, from_set: (1..5) ## => raises EnvParser::ValueNotAllowed
|
76
|
+
- **Parsing `ENV` Values**
|
123
77
|
|
78
|
+
At its core, EnvParser is a straight-forward parser for string values (since that's all `ENV` ever gives you), allowing you to read a given string **_as_** a variety of types.
|
124
79
|
|
125
|
-
|
126
|
-
##
|
127
|
-
|
80
|
+
```ruby
|
81
|
+
## Returns ENV['TIMEOUT_MS'] as an Integer,
|
82
|
+
## or a sensible default (0) if ENV['TIMEOUT_MS'] is unset.
|
83
|
+
##
|
84
|
+
timeout_ms = EnvParser.parse ENV['TIMEOUT_MS'], as: :integer
|
85
|
+
```
|
128
86
|
|
129
|
-
|
130
|
-
EnvParser.parse(:MUST_BE_LOWERCASE, as: :string) { |value| value == value.downcase }
|
131
|
-
EnvParser.parse(:CONNECTION_RETRIES, as: :integer, &:nonzero?)
|
132
|
-
```
|
87
|
+
You can check the full documentation for [a list of all **_as_** types available right out of the box](http://nestor-custodio.github.io/env_parser/EnvParser/Types.html).
|
133
88
|
|
89
|
+
- **How About Less Typing?**
|
134
90
|
|
135
|
-
|
91
|
+
EnvParser is all about ~~simplification~~ ~~less typing~~ *laziness*. If you pass in a symbol instead of a string, EnvParser will look to `ENV` and use the value from the corresponding (string) key.
|
136
92
|
|
137
|
-
```ruby
|
138
|
-
##
|
139
|
-
##
|
140
|
-
|
141
|
-
EnvParser.
|
142
|
-
|
93
|
+
```ruby
|
94
|
+
## YAY, LESS TYPING! 😃
|
95
|
+
## These two are the same:
|
96
|
+
##
|
97
|
+
more_typing = EnvParser.parse ENV['TIMEOUT_MS'], as: :integer
|
98
|
+
less_typing = EnvParser.parse :TIMEOUT_MS, as: :integer
|
99
|
+
```
|
143
100
|
|
144
|
-
|
145
|
-
##
|
146
|
-
ENV['ULTIMATE_LINK'] ## => 'https://youtu.be/L_jWHffIx5E' (Set elsewhere, like a ".env" file.)
|
147
|
-
EnvParser.register :ULTIMATE_LINK, as: :string, within: URI
|
148
|
-
URI::ULTIMATE_LINK ## => 'https://youtu.be/L_jWHffIx5E' (You know you want to check it out!)
|
149
|
-
ULTIMATE_LINK ## => raises NameError (the un-namespaced constant is only in scope within the URI module)
|
101
|
+
- **Registering Constants From `ENV` Values**
|
150
102
|
|
103
|
+
The `EnvParser.register` method lets you "promote" `ENV` variables into their own constants, already parsed into the correct type.
|
151
104
|
|
152
|
-
|
153
|
-
##
|
154
|
-
EnvParser.register :A, as: :string
|
155
|
-
EnvParser.register :B, as: :integer, if_unset: 25
|
156
|
-
EnvParser.register :C, as: :boolean, if_unset: true
|
105
|
+
```ruby
|
106
|
+
ENV['API_KEY'] ## => 'unbreakable p4$$w0rd'
|
157
107
|
|
158
|
-
|
159
|
-
##
|
160
|
-
|
161
|
-
A: { as: :string },
|
162
|
-
B: { as: :integer, if_unset: 25 },
|
163
|
-
C: { as: :boolean, if_unset: true }
|
164
|
-
)
|
165
|
-
```
|
108
|
+
EnvParser.register :API_KEY, as: :string
|
109
|
+
API_KEY ## => 'unbreakable p4$$w0rd'
|
110
|
+
```
|
166
111
|
|
112
|
+
By default, `EnvParser.register` will create the requested constant within the Kernel module (making it available everywhere), but you can specify any class or module you like.
|
167
113
|
|
168
|
-
|
114
|
+
```ruby
|
115
|
+
ENV['BEST_VIDEO'] ## => 'https://youtu.be/L_jWHffIx5E'
|
169
116
|
|
170
|
-
|
171
|
-
##
|
172
|
-
##
|
173
|
-
|
174
|
-
EnvParser.add_env_bindings ## Sets up the proxy methods.
|
117
|
+
EnvParser.register :BEST_VIDEO, as: :string, within: URI
|
118
|
+
URI::BEST_VIDEO ## => 'https://youtu.be/L_jWHffIx5E'
|
119
|
+
BEST_VIDEO ## => raises NameError
|
120
|
+
```
|
175
121
|
|
176
|
-
|
177
|
-
## attempt to interpret any value given as an ENV key (converting to a String, if necessary).
|
178
|
-
##
|
179
|
-
ENV['SHORT_PI'] ## => '3.1415926'
|
180
|
-
ENV.parse :SHORT_PI, as: :float ## => 3.1415926
|
181
|
-
ENV.register :SHORT_PI, as: :float ## Your constant is set, my man!
|
182
|
-
```
|
122
|
+
You can also register multiple constants with a single call, which is a bit cleaner.
|
183
123
|
|
124
|
+
```ruby
|
125
|
+
EnvParser.register :USERNAME, as: :string
|
126
|
+
EnvParser.register :PASSWORD, as: :string
|
127
|
+
EnvParser.register :MOCK_API, as: :boolean, within: MyClassOrModule }
|
184
128
|
|
185
|
-
|
129
|
+
## ... is equivalent to ... ##
|
186
130
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
a = EnvParser.parse :A, as: :int, if_unset: nil
|
192
|
-
raise unless passes_all_my_checks?(a)
|
131
|
+
EnvParser.register USERNAME: { as: :string },
|
132
|
+
PASSWORD: { as: :string },
|
133
|
+
MOCK_API: { as: :boolean, within: MyClassOrModule }
|
134
|
+
```
|
193
135
|
|
194
|
-
|
195
|
-
raise unless passes_all_my_checks?(b)
|
136
|
+
- **Okay, But... How About Even Less Typing?**
|
196
137
|
|
197
|
-
|
198
|
-
##
|
199
|
-
EnvParser.define_type(:my_special_type_of_number, if_unset: nil) do |value|
|
200
|
-
value = value.to_i
|
201
|
-
raise(StandardError, 'this is not a "special type" number') unless passes_all_my_checks?(value)
|
138
|
+
Calling `EnvParser.add_env_bindings` binds proxy `parse` and `register` methods onto `ENV`. With these bindings in place, you can call `parse` or `register` on `ENV` itself, which is more legible and feels more straight-forward.
|
202
139
|
|
203
|
-
|
204
|
-
|
140
|
+
```ruby
|
141
|
+
ENV['SHORT_PI'] ## => '3.1415926'
|
142
|
+
ENV['BETTER_PI'] ## => '["flaky crust", "strawberry filling"]'
|
205
143
|
|
206
|
-
|
207
|
-
|
144
|
+
## Bind the proxy methods.
|
145
|
+
##
|
146
|
+
EnvParser.add_env_bindings
|
208
147
|
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
148
|
+
ENV.parse :SHORT_PI, as: :float ## => 3.1415926
|
149
|
+
ENV.register :BETTER_PI, as: :array ## Your constant is set!
|
150
|
+
```
|
151
|
+
|
152
|
+
Note that the proxy `ENV.parse` method will (naturally) *always* interpret the value given as an `ENV` key (converting it to a string, if necessary), which is slightly different from the original `EnvParser.parse` method.
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
ENV['SHORT_PI'] ## => '3.1415926'
|
156
|
+
|
157
|
+
EnvParser.parse 'SHORT_PI', as: :float ## => 'SHORT_PI' as a float: 0.0
|
158
|
+
EnvParser.parse :SHORT_PI , as: :float ## => ENV['SHORT_PI'] as a float: 3.1415926
|
159
|
+
|
160
|
+
## Bind the proxy methods.
|
161
|
+
##
|
162
|
+
EnvParser.add_env_bindings
|
163
|
+
|
164
|
+
ENV.parse 'SHORT_PI', as: :float ## => ENV['SHORT_PI'] as a float: 3.1415926
|
165
|
+
ENV.parse :SHORT_PI , as: :float ## => ENV['SHORT_PI'] as a float: 3.1415926
|
166
|
+
```
|
167
|
+
|
168
|
+
Note also that the `ENV.parse` and `ENV.register` binding is done safely and without polluting the method space for other objects.
|
169
|
+
|
170
|
+
**All additional examples below will assume that `ENV` bindings are already in place, for brevity's sake.**
|
171
|
+
|
172
|
+
|
173
|
+
#### Ensuring Usable Values
|
213
174
|
|
214
|
-
|
175
|
+
- **Sensible Defaults**
|
215
176
|
|
216
|
-
|
177
|
+
If the `ENV` variable you want is unset (`nil`) or blank (`''`), the return value is a sensible default for the given **_as_** type: 0 or 0.0 for numbers, an empty string/array/hash, etc. Sometimes you want a non-trivial default, however. The **_if_unset_** option lets you specify a default that better meets your needs.
|
178
|
+
|
179
|
+
```ruby
|
180
|
+
ENV.parse :MISSING_VAR, as: :integer ## => 0
|
181
|
+
ENV.parse :MISSING_VAR, as: :integer, if_unset: 250 ## => 250
|
182
|
+
```
|
183
|
+
|
184
|
+
Note these default values are used as-is with no type conversion, so exercise caution.
|
185
|
+
|
186
|
+
```ruby
|
187
|
+
ENV.parse :MISSING_VAR, as: :integer, if_unset: 'Careful!' ## => 'Careful!' (NOT AN INTEGER)
|
188
|
+
```
|
189
|
+
|
190
|
+
- **Selecting From A Set**
|
191
|
+
|
192
|
+
Sometimes setting the **_as_** type is a bit too open-ended. The **_from_set_** option lets you restrict the domain of allowed values.
|
193
|
+
|
194
|
+
```ruby
|
195
|
+
ENV.parse :API_TO_USE, as: :symbol, from_set: %i[internal external]
|
196
|
+
ENV.parse :NETWORK_PORT, as: :integer, from_set: (1..65535), if_unset: 80
|
197
|
+
|
198
|
+
## And if the value is not in the allowed set ...
|
199
|
+
##
|
200
|
+
ENV.parse :TWELVE, as: :integer, from_set: (1..5) ## => raises EnvParser::ValueNotAllowedError
|
201
|
+
```
|
202
|
+
|
203
|
+
- **Custom Validation Of Parsed Values**
|
204
|
+
|
205
|
+
You can write your own, more complex validations by passing in a **_validated_by_** lambda or an equivalent block. The lambda/block should take one value and return true if the given value passes the custom validation.
|
206
|
+
|
207
|
+
```ruby
|
208
|
+
## Via a "validated_by" lambda ...
|
209
|
+
##
|
210
|
+
ENV.parse :MUST_BE_LOWERCASE, as: :string, validated_by: ->(value) { value == value.downcase }
|
211
|
+
|
212
|
+
## ... or with a block!
|
213
|
+
##
|
214
|
+
ENV.parse(:MUST_BE_LOWERCASE, as: :string) { |value| value == value.downcase }
|
215
|
+
ENV.parse(:CONNECTION_RETRIES, as: :integer, &:positive?)
|
216
|
+
```
|
217
|
+
|
218
|
+
- **Defining Your Own EnvParser "*as*" Types**
|
219
|
+
|
220
|
+
If you use a particular validation many times or are often manipulating values in the same way after EnvParser has done its thing, you may want to register a new type altogether. Defining a new type makes your code both more maintainable (all the logic for your special type is only defined once) and more readable (your `parse` calls aren't littered with type-checking cruft).
|
221
|
+
|
222
|
+
Something as repetitive as:
|
223
|
+
|
224
|
+
```ruby
|
225
|
+
a = ENV.parse :A, as: :int, if_unset: 6
|
226
|
+
raise unless passes_all_my_checks?(a)
|
227
|
+
|
228
|
+
b = ENV.parse :B, as: :int, if_unset: 6
|
229
|
+
raise unless passes_all_my_checks?(b)
|
230
|
+
```
|
231
|
+
|
232
|
+
... is perhaps best handled by defining a new type:
|
233
|
+
|
234
|
+
```ruby
|
235
|
+
EnvParser.define_type(:my_special_type_of_number, if_unset: 6) do |value|
|
236
|
+
value = value.to_i
|
237
|
+
unless passes_all_my_checks?(value)
|
238
|
+
raise(EnvParser::ValueNotConvertibleError, 'cannot parse as a "special type number"')
|
239
|
+
end
|
240
|
+
|
241
|
+
value
|
242
|
+
end
|
243
|
+
|
244
|
+
a = ENV.parse :A, as: :my_special_type_of_number
|
245
|
+
b = ENV.parse :B, as: :my_special_type_of_number
|
246
|
+
```
|
247
|
+
|
248
|
+
|
249
|
+
#### Auto-Registering Constants
|
250
|
+
|
251
|
+
- **The `autoregister` Call**
|
252
|
+
|
253
|
+
Consolidating all of your `EnvParser.register` calls into a single place only makes sense. A single `EnvParser.autoregister` call take a filename to read and process as a series of constant registration requests. If no filename is given, the default `".env_parser.yml"` is assumed.
|
254
|
+
|
255
|
+
You'll normally want to call `EnvParser.autoregister` as early in your application as possible. For Rails applications (and other frameworks that call `require 'bundler/setup'`), requiring the EnvParser gem via ...
|
256
|
+
|
257
|
+
```ruby
|
258
|
+
gem 'env_parser', require: 'env_parser/autoregister'
|
259
|
+
```
|
260
|
+
|
261
|
+
... will automatically make the autoregistration call for you as soon as the gem is loaded (which should be early enough for most uses). If this is *still* not early enough for your needs, you can always `require 'env_parser/autoregister'` yourself even before `bundler/setup` is invoked.
|
262
|
+
|
263
|
+
- **The ".env_parser.yml" File**
|
264
|
+
|
265
|
+
If you recall, multiple constants can be registered via a single `EnvParser.register` call:
|
266
|
+
|
267
|
+
```ruby
|
268
|
+
EnvParser.register :USERNAME, as: :string
|
269
|
+
EnvParser.register :PASSWORD, as: :string
|
270
|
+
EnvParser.register :MOCK_API, as: :boolean, within: MyClassOrModule }
|
271
|
+
|
272
|
+
## ... is equivalent to ... ##
|
273
|
+
|
274
|
+
EnvParser.register USERNAME: { as: :string },
|
275
|
+
PASSWORD: { as: :string },
|
276
|
+
MOCK_API: { as: :boolean, within: MyClassOrModule }
|
277
|
+
```
|
278
|
+
|
279
|
+
The autoregistraton file is intended to read as a YAML version of what you'd pass to the single-call version of `EnvParser.register`: a single hash with keys for each of the constants you'd like to register, with each value being the set of options to parse that constant.
|
280
|
+
|
281
|
+
The equivalent autoregistration file for the above would be:
|
282
|
+
|
283
|
+
```yaml
|
284
|
+
USERNAME:
|
285
|
+
as: :string
|
286
|
+
|
287
|
+
PASSWORD:
|
288
|
+
as: :string
|
289
|
+
|
290
|
+
MOCK_API:
|
291
|
+
as: :boolean
|
292
|
+
within: MyClassOrModule
|
293
|
+
```
|
294
|
+
|
295
|
+
Because no Ruby *statements* can be safely represented via YAML, the set of `EnvParser.register` options available via autoregistration is limited to **_as_**, **_within_**, **_if_unset_**, and **_from_set_**. As an additional restriction, **_from_set_** (if given) must be an array, as ranges cannot be represented in YAML.
|
217
296
|
|
218
297
|
|
219
298
|
## Feature Roadmap / Future Development
|
220
299
|
|
221
|
-
Additional features
|
300
|
+
Additional features coming in the future:
|
222
301
|
|
223
|
-
-
|
224
|
-
- ... ?
|
302
|
+
- Continue to round out the **_as_** type selection as ideas come to mind, suggestions are made, and pull requests are submitted.
|
225
303
|
|
226
304
|
|
227
305
|
## Contribution / Development
|
228
306
|
|
229
|
-
Bug reports and pull requests are welcome
|
230
|
-
|
231
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
307
|
+
Bug reports and pull requests are welcome at: [https://github.com/nestor-custodio/env_parser](https://github.com/nestor-custodio/env_parser)
|
232
308
|
|
233
|
-
|
309
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
234
310
|
|
235
|
-
|
311
|
+
Linting is courtesy of [Rubocop](https://docs.rubocop.org/) (`bundle exec rubocop`) and documentation is built using [Yard](https://yardoc.org/) (`bundle exec yard`). Please ensure you have a clean bill of health from Rubocop and that any new features and/or changes to behaviour are reflected in the documentation before submitting a pull request.
|
236
312
|
|
237
313
|
|
238
314
|
## License
|
239
315
|
|
240
|
-
|
316
|
+
EnvParser is available as open source under the terms of the [MIT License](https://tldrlegal.com/license/mit-license).
|