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.
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).