environment_helpers 1.2.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 71bfb123e7f90d29f9e038849bc995207b9c11b166aae7e0938cf162e7ed70f5
4
- data.tar.gz: bb88e8d31c0c343a54f7be6a6919af08446a2a9fff973868b9ba22a9f1fc3f9a
3
+ metadata.gz: 977bcb9a26d78cbddc4857274e59ed796d9454993fa5bc307c3643af08ed53e2
4
+ data.tar.gz: 4696a62fd389365b56c79e952a1f4ac947970483faf17122e21cc312a1eff2c4
5
5
  SHA512:
6
- metadata.gz: f9adafc223d6c2edff2c4179bb86d172e2febe28d8761a2d55b9b76db02d6076ce981229cd8f758c905c4e4e524ad4b6b6e589ff55ced624fbc510ad8a183ed1
7
- data.tar.gz: 7d6ae5d630de28a2d5db1776d06ed7d2a6117a905b66c12aa61b2b7fe5c4dd64dd8cd5e764c450fcf846b077ee23c7f74f6bd393d3cec8b161f6365a27cd498b
6
+ metadata.gz: 1fca3efa7549d3464b174bb84fdaab9d5f0a6c150121d50cf715891eafcca4f097f24c2624f8cab10812260e0c1358928eac811cf299b232afd0a4971641f084
7
+ data.tar.gz: 2240bb669c7d0852c581b4ab0c0c343cdc1c1dece4da9b8b1d34c2b08658c9aa4e5a8ddfb6e6c864751ee4f6fd82d1ad351721213b005270faa233aa0f957a79
@@ -0,0 +1,29 @@
1
+ name: Quiet Quality
2
+
3
+ on: push
4
+ permissions: write-all
5
+
6
+ jobs:
7
+ check:
8
+ runs-on: ubuntu-latest
9
+ steps:
10
+ - uses: actions/checkout@v3
11
+ with:
12
+ fetch-depth: 0
13
+
14
+ - name: Show the merge-base
15
+ run: git merge-base origin/main ${{ github.sha }}
16
+ if: github.branch != 'main'
17
+
18
+ - name: Set up Ruby
19
+ uses: ruby/setup-ruby@v1
20
+ with:
21
+ ruby-version: 3.2
22
+
23
+ - name: Install gems
24
+ run: bundle install --jobs 4 --retry 3
25
+
26
+ - name: Run QuietQuality
27
+ run: |
28
+ gem install quiet_quality standard rubocop
29
+ qq -C .quiet_quality.ci-cd.yml
@@ -8,7 +8,7 @@ jobs:
8
8
  strategy:
9
9
  fail-fast: false
10
10
  matrix:
11
- ruby-version: ['2.6', '2.7', '3.0', '3.1', '3.2', 'head']
11
+ ruby-version: ['2.7', '3.0', '3.1', '3.2', 'head']
12
12
 
13
13
  steps:
14
14
  - uses: actions/checkout@v3
data/.mdl_rules.rb ADDED
@@ -0,0 +1,2 @@
1
+ all
2
+ rule "MD013", ignore_code_blocks: true
data/.mdlrc ADDED
@@ -0,0 +1,2 @@
1
+ style File.expand_path("../.mdl_rules.rb", __FILE__)
2
+ git_recurse true
@@ -0,0 +1,7 @@
1
+ ---
2
+ default_tools: ["standardrb", "rubocop", "markdown_lint", "rspec"]
3
+ executor: concurrent
4
+ comparison_branch: origin/main
5
+ annotator: github_stdout
6
+ changed_files: false
7
+ filter_messages: false
@@ -0,0 +1,7 @@
1
+ ---
2
+ default_tools: ["standardrb", "rubocop", "markdown_lint", "rspec"]
3
+ executor: concurrent
4
+ comparison_branch: origin/main
5
+ logging: light
6
+ changed_files: false
7
+ filter_messages: false
data/CHANGELOG.md ADDED
@@ -0,0 +1,32 @@
1
+ # Changelog
2
+
3
+ ## Release 1.4.0
4
+
5
+ * Drop support for ruby 2.6
6
+ * Setup `quiet_quality` through the gemspec
7
+ * Setup `markdownlint` and comply with its rules (#25)
8
+ * Setup `rspec-cover_it` to enforce test-coverage (#24)
9
+
10
+ ## Release 1.3.0
11
+
12
+ * Support `ENV.date_time` (#19, resolves #6)
13
+
14
+ ## Release 1.2.1
15
+
16
+ * Require `set` before loading the gem, since we support rubies before 3.2 (#18)
17
+
18
+ ## Release 1.2.0
19
+
20
+ * Support `ENV.file_path` returning Pathname objects (#16, resolves #13)
21
+
22
+ ## Release 1.1.0
23
+
24
+ * Support `ENV.integer_range` (#15, resolves #5)
25
+
26
+ ## Release 1.0.1
27
+
28
+ * Specify dependencies more tightly (#14)
29
+
30
+ ## Release 1.0.0
31
+
32
+ (Initial release)
data/README.md CHANGED
@@ -1,36 +1,40 @@
1
1
  # EnvironmentHelpers
2
- This gem adds a set of convenience helpers to `ENV`, allowing you to access environment variables
3
- in a more structures and consistent way. Have you seen any line like these?
4
2
 
5
- ```
3
+ This gem adds a set of convenience helpers to `ENV`, allowing you to access
4
+ environment variables in a more structures and consistent way. Have you seen
5
+ any line like these?
6
+
7
+ ```ruby
6
8
  enable_bar = ENV.fetch("ENABLE_BAR", "false") == "true"
7
9
  foo_count = ENV.fetch("FOO_TOTAL", "100").to_i
8
10
  ```
9
11
 
10
- This works okay! And it's not really that complicated, working out what's going on here isn't
11
- that difficult. How about this?
12
+ This works okay! And it's not really that complicated, working out what's going
13
+ on here isn't that difficult. How about this?
12
14
 
13
- ```
15
+ ```ruby
14
16
  enable_foo = ENV.fetch("ENABLE_FOO", "false") != "true"
15
17
  ```
16
18
 
17
- That.. looks very similar, but means the opposite thing. Also not that tricky. You don't start
18
- to _wish_ for a tool like EnvironmentHelpers until these constructions get complex and compounded.
19
- But.. if you're using a 12-factor style of configuration, you probably have these ENV-fetches
20
- sprinkled _everywhere_, so making them moderately clearer or simpler can pay off fairly quickly.
19
+ That.. looks very similar, but means the opposite thing. Also not that tricky.
20
+ You don't start to _wish_ for a tool like EnvironmentHelpers until these
21
+ constructions get complex and compounded. But.. if you're using a 12-factor
22
+ style of configuration, you probably have these ENV-fetches sprinkled
23
+ _everywhere_, so making them moderately clearer or simpler can pay off fairly
24
+ quickly.
21
25
 
22
26
  ## Installation
23
27
 
24
- ```
28
+ ```ruby
25
29
  gem "environment_helper"
26
30
  ```
27
31
 
28
- There's not much to it - add the gem to your gemfile and when it's loaded it'll add some extra
29
- methods onto `ENV` for your use.
32
+ There's not much to it - add the gem to your gemfile and when it's loaded it'll
33
+ add some extra methods onto `ENV` for your use.
30
34
 
31
35
  ## Usage
32
36
 
33
- ```shell
37
+ ```ruby
34
38
  ENV.string("APP_NAME", default: "local")
35
39
  ENV.symbol("BUSINESS_DOMAIN", default: :engineering, required: true)
36
40
  ENV.boolean("ENABLE_FEATURE_FOO", default: false)
@@ -38,29 +42,44 @@ ENV.integer_range("ID_RANGE", default: (500..6000))
38
42
  ENV.integer("MAX_THREAD_COUNT", default: 5)
39
43
  ENV.file_path("FILE_PATH", default: "/some/path", required: true)
40
44
  ENV.date("SCHEDULED_DATE", required: true, format: "%Y-%m-%d")
45
+ ENV.date_time("RUN_AT", required: true, default: DateTime.now)
41
46
  ```
42
47
 
43
- Each of the supplied methods takes a positional parameter for the name of the environment variable,
44
- and then two optional named parameters `default` and `required` (there's no point in supplying
45
- both, but nothing stops you from doing so). The `default` value is the value used if the variable
46
- isn't present in the environment. If `required` is set to a truthy value, then if the variable isn't
47
- present in the environment, an `EnvironmentHelpers::MissingVariableError` is raised.
48
+ Each of the supplied methods takes a positional parameter for the name of the
49
+ environment variable, and then two optional named parameters `default` and
50
+ `required` (there's no point in supplying both, but nothing stops you from doing
51
+ so). The `default` value is the value used if the variable isn't present in the
52
+ environment. If `required` is set to a truthy value, then if the variable isn't
53
+ present in the environment, an `EnvironmentHelpers::MissingVariableError` is
54
+ raised.
48
55
 
49
56
  The available methods added to `ENV`:
50
57
 
51
- * `string` - environment values are already strings, so this is the simplest of the methods.
52
- * `symbol` - produces a symbol, and enforces that the default value is either `nil` or a Symbol.
53
- * `boolean` - produces `nil`, `true`, or `false` (and only allows those as defaults). Supports..
54
- a fair variety of strings to map onto those boolean value, though you should probably just use
55
- "true" and "false" really. If you specify `required: true` and get a value like "maybe?", it'll
56
- raise an `EnvironmentHelpers::InvalidBooleanText` exception.
57
- * `integer_range` - produces an integer Range object. It accepts `N-N`, `N..N`, or `N...N`, (the
58
- latter means 'excluding the upper bound, as in ruby).
59
- * `integer` - produces an integer from the environment variable, by calling `to_i` on it (if it's
60
- present). Note that this means that providing a value like "hello" means you'll get `0`, since
61
- that's what ruby does when you call `"hello".to_i`.
62
- * `file_path` - produces a `Pathname` initialized with the path specified by the environment variable.
63
- * `date` - produces a `Date` object, using `Date.strptime`. The default format string is `%Y-%m-%d`,
64
- which would parse a date like `2023-12-25`. It will handle invalid values (or format strings) like
65
- the variable not being present, though if it's specified as `required`, you will see a different
66
- exception in each case.
58
+ * `string` - environment values are already strings, so this is the simplest of
59
+ the methods.
60
+ * `symbol` - produces a symbol, and enforces that the default value is either
61
+ `nil` or a Symbol.
62
+ * `boolean` - produces `nil`, `true`, or `false` (and only allows those as
63
+ defaults). Supports.. a fair variety of strings to map onto those boolean
64
+ value, though you should probably just use "true" and "false" really. If you
65
+ specify `required: true` and get a value like "maybe?", it'll raise an
66
+ `EnvironmentHelpers::InvalidBooleanText` exception.
67
+ * `integer_range` - produces an integer Range object. It accepts `N-N`, `N..N`,
68
+ or `N...N`, (the latter means 'excluding the upper bound, as in ruby).
69
+ * `integer` - produces an integer from the environment variable, by calling
70
+ `to_i` on it (if it's present). Note that this means that providing a value
71
+ like "hello" means you'll get `0`, since that's what ruby does when you call
72
+ `"hello".to_i`.
73
+ * `file_path` - produces a `Pathname` initialized with the path specified by the
74
+ environment variable.
75
+ * `date` - produces a `Date` object, using `Date.strptime`. The default format
76
+ string is `%Y-%m-%d`, which would parse a date like `2023-12-25`. It will
77
+ handle invalid values (or format strings) like the variable not being present,
78
+ though if it's specified as `required`, you will see a different exception in
79
+ each case.
80
+ * `date_time` - produces a `DateTime` object, using either `DateTime.strptime`
81
+ or `DateTime.iso8601`. The default format is `:iso8601`, and `:unix` is also
82
+ an allowed 'format'. But if it is supplied as a _string_, it will be handled
83
+ as a strptime format string (the `:unix` format is equivalent to the format
84
+ string `"%s"`). It handles invalid or unparseable values like `ENV.date` does,
85
+ in that they are treated as if not supplied.
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
13
13
  DESC
14
14
  spec.homepage = "https://github.com/nevinera/environment_helpers"
15
15
  spec.license = "MIT"
16
- spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
16
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
17
17
 
18
18
  spec.metadata["homepage_uri"] = spec.homepage
19
19
  spec.metadata["source_code_uri"] = spec.homepage
@@ -30,7 +30,10 @@ Gem::Specification.new do |spec|
30
30
 
31
31
  spec.add_development_dependency "rspec", "~> 3.10"
32
32
  spec.add_development_dependency "simplecov", "~> 0.22.0"
33
+ spec.add_development_dependency "rspec-cover_it", "~> 0.1.0"
33
34
  spec.add_development_dependency "pry", "~> 0.14"
34
35
  spec.add_development_dependency "standard", "~> 1.28"
35
36
  spec.add_development_dependency "rubocop", "~> 1.50"
37
+ spec.add_development_dependency "quiet_quality", "~> 1.3.0"
38
+ spec.add_development_dependency "mdl", "~> 0.12"
36
39
  end
@@ -12,6 +12,16 @@ module EnvironmentHelpers
12
12
  fail(InvalidDateText, "Required date environment variable #{name} had inappropriate content '#{text}'")
13
13
  end
14
14
 
15
+ def date_time(name, format: :iso8601, default: nil, required: false)
16
+ check_default_type(:date_time, default, DateTime)
17
+ text = fetch_value(name, required: required)
18
+ dt = parse_date_time_from(text, format: format)
19
+
20
+ return dt if dt
21
+ return default unless required
22
+ fail(InvalidDateTimeText, "Require date_time environment variable #{name} had inappropriate content '#{text}'")
23
+ end
24
+
15
25
  private
16
26
 
17
27
  def parse_date_from(text, format:)
@@ -20,5 +30,37 @@ module EnvironmentHelpers
20
30
  rescue ArgumentError
21
31
  nil
22
32
  end
33
+
34
+ def parse_date_time_from(text, format:)
35
+ if text.nil?
36
+ nil
37
+ elsif format == :iso8601
38
+ iso8601_date_time(text)
39
+ elsif format == :unix
40
+ unix_date_time(text)
41
+ elsif format.is_a?(String)
42
+ strptime_date_time(text, format: format)
43
+ else
44
+ fail(BadFormat, "ENV.date_time requires either a strptime format string, :unix, or :iso8601")
45
+ end
46
+ end
47
+
48
+ def iso8601_date_time(text)
49
+ DateTime.iso8601(text)
50
+ rescue
51
+ nil
52
+ end
53
+
54
+ def unix_date_time(text)
55
+ DateTime.strptime(text, "%s")
56
+ rescue
57
+ nil
58
+ end
59
+
60
+ def strptime_date_time(text, format:)
61
+ DateTime.strptime(text, format)
62
+ rescue
63
+ nil
64
+ end
23
65
  end
24
66
  end
@@ -0,0 +1,44 @@
1
+ module EnvironmentHelpers
2
+ module EnumerableHelpers
3
+ VALID_TYPES = %i[strings symbols integers]
4
+
5
+ def array(key, of: :strings, delimiter: ",", default: nil, required: false)
6
+ check_default_type(:array, default, Array)
7
+ check_valid_data_type!(of)
8
+ check_default_data_types!(default, of)
9
+
10
+ values = fetch_value(key, required: required)
11
+ return default if values.nil?
12
+
13
+ values.split(delimiter).map { |value| value.send(TYPE_HANDLERS[of]) }
14
+ end
15
+
16
+ private
17
+
18
+ def check_valid_data_type!(type)
19
+ unless VALID_TYPES.include?(type)
20
+ fail(InvalidType, "Valid types: #{VALID_TYPES.join(", ")}. Got: #{type}.")
21
+ end
22
+ end
23
+
24
+ def check_default_data_types!(default, type)
25
+ invalid = Array(default).reject { |val| val.is_a? TYPE_MAP[type] }
26
+
27
+ unless invalid.empty?
28
+ fail(BadDefault, "Default array contains values not of type `#{type}': #{invalid.join(", ")}")
29
+ end
30
+ end
31
+
32
+ TYPE_HANDLERS = {
33
+ integers: :to_i,
34
+ strings: :to_s,
35
+ symbols: :to_sym
36
+ }
37
+
38
+ TYPE_MAP = {
39
+ integers: Integer,
40
+ strings: String,
41
+ symbols: Symbol
42
+ }
43
+ end
44
+ end
@@ -1,3 +1,3 @@
1
1
  module EnvironmentHelpers
2
- VERSION = "1.2.1"
2
+ VERSION = "1.4.0"
3
3
  end
@@ -9,17 +9,21 @@ require_relative "./environment_helpers/range_helpers"
9
9
  require_relative "./environment_helpers/numeric_helpers"
10
10
  require_relative "./environment_helpers/file_helpers"
11
11
  require_relative "./environment_helpers/datetime_helpers"
12
+ require_relative "./environment_helpers/enumerable_helpers"
12
13
 
13
14
  module EnvironmentHelpers
14
15
  Error = Class.new(::StandardError)
15
16
  MissingVariableError = Class.new(Error)
16
17
  BadDefault = Class.new(Error)
18
+ BadFormat = Class.new(Error)
17
19
 
20
+ InvalidType = Class.new(Error)
18
21
  InvalidValue = Class.new(Error)
19
22
  InvalidBooleanText = Class.new(InvalidValue)
20
23
  InvalidRangeText = Class.new(InvalidValue)
21
24
  InvalidIntegerText = Class.new(InvalidValue)
22
25
  InvalidDateText = Class.new(InvalidValue)
26
+ InvalidDateTimeText = Class.new(InvalidValue)
23
27
 
24
28
  include AccessHelpers
25
29
  include StringHelpers
@@ -28,6 +32,7 @@ module EnvironmentHelpers
28
32
  include NumericHelpers
29
33
  include FileHelpers
30
34
  include DatetimeHelpers
35
+ include EnumerableHelpers
31
36
  end
32
37
 
33
38
  ENV.extend(EnvironmentHelpers)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: environment_helpers
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Mueller
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-28 00:00:00.000000000 Z
11
+ date: 2023-06-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 0.22.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec-cover_it
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.1.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.1.0
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: pry
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +94,34 @@ dependencies:
80
94
  - - "~>"
81
95
  - !ruby/object:Gem::Version
82
96
  version: '1.50'
97
+ - !ruby/object:Gem::Dependency
98
+ name: quiet_quality
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 1.3.0
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 1.3.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: mdl
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '0.12'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '0.12'
83
125
  description: |
84
126
  Convenience helpers for more simply accessing data passed to applications through the
85
127
  environment that may have types and/or defaults
@@ -89,11 +131,16 @@ executables: []
89
131
  extensions: []
90
132
  extra_rdoc_files: []
91
133
  files:
92
- - ".github/workflows/lint.yml"
134
+ - ".github/workflows/quality.yml"
93
135
  - ".github/workflows/rspec.yml"
94
136
  - ".gitignore"
137
+ - ".mdl_rules.rb"
138
+ - ".mdlrc"
139
+ - ".quiet_quality.ci-cd.yml"
140
+ - ".quiet_quality.yml"
95
141
  - ".rspec"
96
142
  - ".rubocop.yml"
143
+ - CHANGELOG.md
97
144
  - Gemfile
98
145
  - LICENSE
99
146
  - README.md
@@ -102,6 +149,7 @@ files:
102
149
  - lib/environment_helpers/access_helpers.rb
103
150
  - lib/environment_helpers/boolean_helpers.rb
104
151
  - lib/environment_helpers/datetime_helpers.rb
152
+ - lib/environment_helpers/enumerable_helpers.rb
105
153
  - lib/environment_helpers/file_helpers.rb
106
154
  - lib/environment_helpers/numeric_helpers.rb
107
155
  - lib/environment_helpers/range_helpers.rb
@@ -121,14 +169,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
121
169
  requirements:
122
170
  - - ">="
123
171
  - !ruby/object:Gem::Version
124
- version: 2.6.0
172
+ version: 2.7.0
125
173
  required_rubygems_version: !ruby/object:Gem::Requirement
126
174
  requirements:
127
175
  - - ">="
128
176
  - !ruby/object:Gem::Version
129
177
  version: '0'
130
178
  requirements: []
131
- rubygems_version: 3.3.26
179
+ rubygems_version: 3.4.10
132
180
  signing_key:
133
181
  specification_version: 4
134
182
  summary: A set of convenience methods for accessing environment data
@@ -1,30 +0,0 @@
1
- name: Linters
2
-
3
- on: [push]
4
-
5
- jobs:
6
- StandardRB:
7
- runs-on: ubuntu-latest
8
- steps:
9
- - uses: actions/checkout@v2
10
-
11
- - name: Set up ruby
12
- uses: ruby/setup-ruby@v1
13
- with:
14
- ruby-version: 3.2
15
-
16
- - name: Cache gems
17
- uses: actions/cache@v1
18
- with:
19
- path: vendor/bundle
20
- key: ${{ runner.os }}-linters-${{ hashFiles('Gemfile.lock') }}
21
- restore-keys:
22
- ${{ runner.os }}-linters-
23
- - name: Install gems
24
- run: bundle install --jobs 4 --retry 3
25
-
26
- - name: Run standard
27
- run: bundle exec standardrb
28
-
29
- - name: Run rubocop (complexity checks)
30
- run: bundle exec rubocop --parallel