env_parser 0.8.0 → 1.3.1

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.
Files changed (43) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +7 -6
  3. data/.rubocop.yml +56 -57
  4. data/.ruby-version +1 -1
  5. data/Gemfile.lock +58 -28
  6. data/README.md +252 -176
  7. data/docs/EnvParser.html +305 -169
  8. data/docs/EnvParser/AutoregisterFileNotFound.html +143 -0
  9. data/docs/EnvParser/Error.html +9 -9
  10. data/docs/EnvParser/TypeAlreadyDefinedError.html +143 -0
  11. data/docs/EnvParser/Types.html +128 -0
  12. data/docs/EnvParser/Types/BaseTypes.html +177 -0
  13. data/docs/EnvParser/Types/ChronologyTypes.html +159 -0
  14. data/docs/EnvParser/Types/InternetTypes.html +159 -0
  15. data/docs/EnvParser/UnknownTypeError.html +143 -0
  16. data/docs/EnvParser/UnparseableAutoregisterSpec.html +143 -0
  17. data/docs/EnvParser/ValueNotAllowedError.html +143 -0
  18. data/docs/EnvParser/ValueNotConvertibleError.html +143 -0
  19. data/docs/EnvParserTypes.html +129 -0
  20. data/docs/EnvParserTypes/BaseTypes.html +178 -0
  21. data/docs/EnvParserTypes/ChronologyTypes.html +159 -0
  22. data/docs/EnvParserTypes/InternetTypes.html +159 -0
  23. data/docs/EnvParserTypes/TimeTypes.html +158 -0
  24. data/docs/_index.html +108 -9
  25. data/docs/class_list.html +3 -3
  26. data/docs/css/style.css +7 -9
  27. data/docs/file.README.html +215 -226
  28. data/docs/file_list.html +2 -2
  29. data/docs/frames.html +2 -2
  30. data/docs/index.html +215 -226
  31. data/docs/js/app.js +69 -3
  32. data/docs/method_list.html +13 -5
  33. data/docs/top-level-namespace.html +9 -9
  34. data/env_parser.gemspec +6 -2
  35. data/lib/env_parser.rb +111 -83
  36. data/lib/env_parser/autoregister.rb +3 -0
  37. data/lib/env_parser/errors.rb +40 -0
  38. data/lib/env_parser/types.rb +3 -0
  39. data/lib/env_parser/types/base_types.rb +99 -26
  40. data/lib/env_parser/types/chronology_types.rb +104 -0
  41. data/lib/env_parser/types/internet_types.rb +99 -0
  42. data/lib/env_parser/version.rb +1 -1
  43. metadata +85 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: a70a46c16cd38925dcbae5621e61fa57fc5099cd
4
- data.tar.gz: 0da0da7bd7ddfd45a114e25847eac28126840759
2
+ SHA256:
3
+ metadata.gz: 6d6d57f56549ef5746444f13eb1b306f6d9e2b46de648a0b218ea890e0b59a79
4
+ data.tar.gz: 981d6ca140586a772801ff1b705508e30c211bfe412f63260192d89fe8630e2c
5
5
  SHA512:
6
- metadata.gz: 69c0ccf1c123fafa029834608a2937b06e7a4fa3a8e499bddfbc6440a358dff88a8e09b9ea235053be8fe5abe79f0ea4970cdb4499196f345b04fd289590cf2c
7
- data.tar.gz: 263da8e5617b3d92107cb0a937785f0e9acfe2ef9d8eda6f36c111a9268d64c2826f2874836ecff1bd7a630876a8d02f91e4793b6c8b9e2c73a0baa646bb4778
6
+ metadata.gz: 2220164e6600e4f4112cdd3d575454aee82cde8a01e3fde5ab06314f6788d414d513296a75c6fe89ea074c1ccf65d418c8a8d1855057bbe06162fca374a61b06
7
+ data.tar.gz: ba9946219aa484356e80e1dcac0ebbcd745f6c1cd9d94fdf24a06ca35a4deb0ce91fae9cd67ea268509820fdbc30ed2b3f03698a060008d568c87e1f45f130ce
@@ -7,7 +7,7 @@ jobs:
7
7
  build:
8
8
  docker:
9
9
  # specify the version you desire here
10
- - image: circleci/ruby:2.4.1-node-browsers
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
- --format RspecJunitFormatter \
53
- --out /tmp/test-results/rspec.xml \
54
- --format progress \
55
- "${TEST_FILES}"
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:
@@ -1,78 +1,77 @@
1
1
  AllCops:
2
- TargetRubyVersion: 2.4
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
- - "vendor/**/*"
12
- - "db/**/*"
10
+ - ".git/**/*"
13
11
  - "tmp/**/*"
14
12
  - "true/**/*"
15
- Metrics/ClassLength:
16
- Description: Avoid classes longer than 100 lines of code.
17
- Enabled: false
18
- CountComments: false
19
- Max: 100
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
- Metrics/MethodLength:
28
- Description: Avoid methods longer than 10 lines of code.
29
- StyleGuide: https://github.com/bbatsov/ruby-style-guide#short-methods
30
- Enabled: false
31
- CountComments: false
32
- Max: 10
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
- Description: A calculated magnitude based on number of assignments, branches, and conditions.
34
+ # A calculated magnitude based on number of assignments, branches, and conditions.
35
35
  Enabled: false
36
- Max: 15
36
+
37
+ Metrics/BlockLength:
38
+ # Avoid long blocks with many lines.
39
+ Exclude:
40
+ - 'spec/**/*.rb'
41
+
37
42
  Metrics/CyclomaticComplexity:
38
- Description: A complexity metric that is strongly correlated to the number of test cases needed to validate a method.
39
- Enabled: false
40
- Max: 6
41
- Lint/Debugger:
42
- Description: Warn in debugger entries
43
- Enabled: false
44
- Lint/RescueWithoutErrorClass:
45
- Description: Avoid rescuing without specifying an error class.
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
- # Disabling this so we can use non-breaking spaces (' ') in documentation comments, preventing browsers from collapsing multiple spaces in code blocks.
55
- Description: This cop checks for non-ascii (non-English) characters in comments.
56
- Enabled: false
57
- Style/NumericLiterals:
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
- Description: Use nested modules/class definitions instead of compact style.
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
- Style/EmptyMethod:
70
+
71
+ Style/NumericLiterals:
72
+ # his cop checks for big numeric literals without _ between groups of digits in them.
69
73
  Enabled: false
70
- Style/StderrPuts:
71
- Enabled: true
72
- Exclude:
73
- - 'bin/**/*'
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
@@ -1 +1 @@
1
- 2.4.2
1
+ 2.7
@@ -1,51 +1,81 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- env_parser (0.8.0)
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 (5.1.4)
12
+ activesupport (6.1.0)
11
13
  concurrent-ruby (~> 1.0, >= 1.0.2)
12
- i18n (~> 0.7)
13
- minitest (~> 5.1)
14
- tzinfo (~> 1.1)
15
- concurrent-ruby (1.0.5)
16
- diff-lcs (1.3)
17
- i18n (0.9.1)
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.10.1)
20
- rake (10.5.0)
21
- rspec (3.7.0)
22
- rspec-core (~> 3.7.0)
23
- rspec-expectations (~> 3.7.0)
24
- rspec-mocks (~> 3.7.0)
25
- rspec-core (3.7.0)
26
- rspec-support (~> 3.7.0)
27
- rspec-expectations (3.7.0)
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.7.0)
30
- rspec-mocks (3.7.0)
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.7.0)
33
- rspec-support (3.7.0)
34
- rspec_junit_formatter (0.3.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
- thread_safe (0.3.6)
37
- tzinfo (1.2.4)
38
- thread_safe (~> 0.1)
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 (~> 1.16)
72
+ bundler (~> 2.0)
45
73
  env_parser!
46
- rake (~> 10.0)
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.16.0
81
+ 2.1.4
data/README.md CHANGED
@@ -1,240 +1,316 @@
1
- # EnvParser [![Gem Version](https://badge.fury.io/rb/env_parser.svg)](https://badge.fury.io/rb/env_parser)
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
- 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 makes *the values themselves* usable with a minimum of effort.
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
- ## Installation
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
- Add this line to your application's Gemfile:
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
- And then execute:
17
-
18
- $ bundle
14
+ ## Installation
19
15
 
20
- Or install it yourself as:
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
- $ gem install env_parser
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
- #### Basic Usage
39
+ ## Syntax Cheat Sheet
28
40
 
29
41
  ```ruby
30
- ## Returns ENV['TIMEOUT_MS'] as an Integer.
31
- ## Yields 0 if ENV['TIMEOUT_MS'] is unset or nil.
42
+ ## Returns an ENV value parsed "as" a specific type:
32
43
  ##
33
- timeout_ms = EnvParser.parse ENV['TIMEOUT_MS'], as: :integer
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
- ## LESS TYPING, PLZ! :(
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
- timeout_ms = EnvParser.parse :TIMEOUT_MS, as: :integer
41
- ```
42
-
43
- ---
44
-
45
- The named `:as` parameter is required. The list of allowed values is user-expandable, but allowed values out-of-the-box are:
46
-
47
- <table>
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>&lt; depends on JSON given &gt;</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.parse :MISSING_ENV_VARIABLE, as: :integer ## => 0
103
- EnvParser.parse :MISSING_ENV_VARIABLE, as: :integer, if_unset: 250 ## => 250
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
- ## Note that "if_unset" values are used as-is, with no type conversion.
65
+ ## Lets you call "parse" and "register" on ENV itself:
106
66
  ##
107
- EnvParser.parse :MISSING_ENV_VARIABLE, as: :integer, if_unset: 'Whoops!' ## => 'Whoops!'
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
- #### Validating Parsed ENV Values
72
+ ## Extended How-To-Use
112
73
 
113
- ```ruby
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
- ## And if the value is not allowed...
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
- ## The "validated_by" option allows for more complex validation.
126
- ##
127
- EnvParser.parse :MUST_BE_LOWERCASE, as: :string, validated_by: ->(value) { value == value.downcase }
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
- ## ... but a block will also do the trick!
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
- #### Setting Constants From ENV Values
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
- ## Global constants...
139
- ##
140
- ENV['API_KEY'] ## => 'unbreakable p4$$w0rd' (Set elsewhere, like a ".env" file.)
141
- EnvParser.register :API_KEY, as: :string
142
- API_KEY ## => 'unbreakable p4$$w0rd' (registered within the Kernel module, so it's available everywhere)
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
- ## ... and class/module constants!
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
- ## You can also set multiple constants in one call, which is considerably cleaner to read:
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
- ## ... is equivalent to ...
159
- ##
160
- EnvParser.register(
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
- #### Binding EnvParser Proxies Onto ENV
114
+ ```ruby
115
+ ENV['BEST_VIDEO'] ## => 'https://youtu.be/L_jWHffIx5E'
169
116
 
170
- ```ruby
171
- ## To allow for even cleaner usage, you can bind proxy "parse" and "register" methods onto ENV.
172
- ## This is done cleanly and without polluting the method space for any other objects.
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
- ## Now you can call "parse" and "register" on ENV itself. Note that ENV's proxy "parse" method will
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
- #### Defining your own types for use with EnvParser
129
+ ## ... is equivalent to ... ##
186
130
 
187
- ```ruby
188
- ## If you use a particular validation many times, or are often manipulating values in the same way
189
- ## after EnvParser has done its thing, you may want to register a new type altogether.
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
- b = EnvParser.parse :B, as: :int, if_unset: nil
195
- raise unless passes_all_my_checks?(b)
136
+ - **Okay, But... How About Even Less Typing?**
196
137
 
197
- ## ... is perhaps best handled by defining a new type:
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
- value
204
- end
140
+ ```ruby
141
+ ENV['SHORT_PI'] ## => '3.1415926'
142
+ ENV['BETTER_PI'] ## => '["flaky crust", "strawberry filling"]'
205
143
 
206
- a = EnvParser.parse :A, as: :my_special_type_of_number
207
- b = EnvParser.parse :B, as: :my_special_type_of_number
144
+ ## Bind the proxy methods.
145
+ ##
146
+ EnvParser.add_env_bindings
208
147
 
209
- ## Defining a new type makes your code both more maintainable (all the logic for your special type
210
- ## is only defined once) and more readable (your "parse" calls aren't littered with type-checking
211
- ## cruft).
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
- [Consult the repo docs](http://nestor-custodio.github.io/env_parser) for the full EnvParser documentation.
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/options coming in the future:
300
+ Additional features coming in the future:
222
301
 
223
- - Round out the "as" type selection with things like `:url`, `:email`, etc.
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 on GitHub at https://github.com/nestor-custodio/env_parser.
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
- Linting is courtesy of [Rubocop](https://github.com/bbatsov/rubocop) and documentation is built using [Yard](https://yardoc.org/). Neither is included in the Gemspec; you'll need to install these locally to take advantage.
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
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
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
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
316
+ EnvParser is available as open source under the terms of the [MIT License](https://tldrlegal.com/license/mit-license).