env_bang 1.0.0.pre.rc.1 → 2.0.0.alpha.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9876284297bbe55660d78e4d62bb83ec54e40ec83ddc94ef56907020805945c1
4
- data.tar.gz: 1ef016e91711a660eee17849a8ac28c1ba8d303e5d6a645415f66d51ab648fb6
3
+ metadata.gz: '094ce7c346a763599ef55ab0256e99cdbed2d4f3059782cb2078ce8f5ff42502'
4
+ data.tar.gz: 353125d00af13bcb825fba521115a53d414d78bfc2e80cc7c8573051ee7c45a7
5
5
  SHA512:
6
- metadata.gz: aa240511a3e7a4b4ea6437ec61f35fadbea111bfb191eeda6d25eee91818380cfc99d36a22734b48a66f945e53c3710e2909c9d4e132f64fb7df4c83bad1cdfc
7
- data.tar.gz: d67dc205e27c91f1abe43b43d1745b432b6dfb2d9c495800c23b06a3e3616a89dabdde5513ce66d796074e346963b9fedb03f387fbb061fcea5e077efd557934
6
+ metadata.gz: 878b656b6090bdbbca837f260032a99edb2a34a50890681d2d88f9ce0e071df2a9c860778288478b7f1627acee4ce7f38efe5f55f469da1806e5fe2ed1850090
7
+ data.tar.gz: c9045031fd3209dc99605ec3a59c67e579d937b658250e4dbd29b958ddd8ed0fe0483f1c850ae59f0cf93e558420674e10ed32bc506a122186978cdd10cddfa5
@@ -0,0 +1,39 @@
1
+ # Use the latest 2.1 version of CircleCI pipeline process engine.
2
+ # See: https://circleci.com/docs/2.0/configuration-reference
3
+ version: 2.1
4
+
5
+ orbs:
6
+ ruby: circleci/ruby@2.0.0
7
+ coveralls: coveralls/coveralls@2.1.0
8
+
9
+ # Define a job to be invoked later in a workflow.
10
+ # See: https://circleci.com/docs/2.0/configuration-reference/#jobs
11
+ jobs:
12
+ test:
13
+ parameters:
14
+ ruby-version:
15
+ type: string
16
+ docker:
17
+ # replace with your preferred image
18
+ - image: cimg/ruby:<< parameters.ruby-version >>
19
+ resource_class: small
20
+ environment:
21
+ COVERAGE: Summary
22
+ steps:
23
+ - checkout
24
+ - run: bundle install
25
+ - run: bundle exec rake
26
+ - coveralls/upload:
27
+ coverage_file: coverage/lcov.info
28
+
29
+ # Invoke jobs via workflows
30
+ # See: https://circleci.com/docs/2.0/configuration-reference/#workflows
31
+ workflows:
32
+ buidle_and_test:
33
+ jobs:
34
+ - test:
35
+ matrix:
36
+ parameters:
37
+ # https://github.com/CircleCI-Public/cimg-ruby
38
+ # only supports the last three ruby versions
39
+ ruby-version: ["2.6", "2.7", "3.0", "3.2"]
data/Gemfile CHANGED
@@ -2,6 +2,7 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec name: 'env_bang'
4
4
 
5
- group :metrics do
6
- gem 'coveralls', require: false
5
+ group :test do
6
+ gem 'simplecov'
7
+ gem 'simplecov-lcov'
7
8
  end
data/README.md CHANGED
@@ -1,19 +1,17 @@
1
1
  # ENV!
2
2
 
3
- Do a bang-up job managing your environment variables.
3
+ Verify correctness of environment configuration at startup time.
4
4
 
5
- [![Gem Version](https://img.shields.io/gem/v/env_bang.svg?style=flat)](https://rubygems.org/gems/env_bang)
6
- [![Build Status](https://img.shields.io/travis/jcamenisch/ENV_BANG/master.svg?style=flat)](https://travis-ci.org/jcamenisch/ENV_BANG)
7
- [![Maintainability](https://api.codeclimate.com/v1/badges/58ba2167873ed46687f9/maintainability)](https://codeclimate.com/github/jcamenisch/ENV_BANG/maintainability)
8
- [![Coverage Status](https://img.shields.io/coveralls/jcamenisch/ENV_BANG/master.svg?style=flat)](https://coveralls.io/r/jcamenisch/ENV_BANG)
5
+ [![Gem Version](https://img.shields.io/gem/v/env_bang?logo=rubygems)](https://rubygems.org/gems/env_bang)
6
+ [![Build Status](https://img.shields.io/circleci/build/github/jcamenisch/ENV_BANG/main)](https://dl.circleci.com/status-badge/redirect/gh/jcamenisch/ENV_BANG/tree/main)
7
+ [![Maintainability](https://img.shields.io/codeclimate/maintainability/jcamenisch/ENV_BANG?logo=codeclimate)](https://codeclimate.com/github/jcamenisch/ENV_BANG)
8
+ [![Coverage Status](https://img.shields.io/coverallsCoverage/github/jcamenisch/ENV_BANG?logo=coveralls)](https://coveralls.io/r/jcamenisch/ENV_BANG)
9
9
 
10
10
  ENV! provides a thin wrapper around ENV to accomplish a few things:
11
11
 
12
12
  - Provide a central place to specify all your app’s environment variables.
13
- - Fail loudly and helpfully if any environment variables are missing.
14
- - Prevent an application from starting up with missing environment variables.
15
- (This is especially helpful in environments like Heroku, as your app will
16
- continue running the old code until the server is configured for a new revision.)
13
+ - Fail loudly and helpfully if any environment variables are missing or invalid.
14
+ - Prevent an application from starting up with invalid environment variables.
17
15
 
18
16
  ## Installation
19
17
 
@@ -1,3 +1,3 @@
1
1
  class ENV_BANG
2
- VERSION = "1.0.0-rc.1"
2
+ VERSION = "2.0.0.alpha.1"
3
3
  end
data/lib/env_bang.rb CHANGED
@@ -1,9 +1,13 @@
1
1
  require "env_bang/version"
2
2
  require "env_bang/classes"
3
3
  require "env_bang/formatter"
4
+ require "forwardable"
4
5
 
5
6
  class ENV_BANG
6
7
  class << self
8
+ extend Forwardable
9
+ include Enumerable
10
+
7
11
  def config(&block)
8
12
  instance_eval(&block)
9
13
  end
@@ -48,10 +52,6 @@ class ENV_BANG
48
52
  Classes.cast ENV[var], vars[var]
49
53
  end
50
54
 
51
- def method_missing(method, *args, &block)
52
- ENV.send(method, *args, &block)
53
- end
54
-
55
55
  def add_class(klass, &block)
56
56
  Classes.send :define_singleton_method, klass.to_s, &block
57
57
  end
@@ -63,6 +63,36 @@ class ENV_BANG
63
63
  Classes.default_class
64
64
  end
65
65
  end
66
+
67
+ def to_h
68
+ keys.map { |k| [k, self[k]] }.to_h
69
+ end
70
+
71
+ alias to_hash to_h
72
+
73
+ ####################################
74
+ # Implement Hash-like read methods #
75
+ ####################################
76
+
77
+ def_delegators :to_h,
78
+ :each, :assoc, :each_pair, :each_value, :empty?, :fetch,
79
+ :invert, :key, :rassoc, :values_at
80
+
81
+ def_delegators :vars, :each_key, :has_key?, :key?, :length, :size
82
+
83
+ def slice(*requested_keys)
84
+ (requested_keys & keys).map { |k| [k, self[k]] }.to_h
85
+ end
86
+
87
+ def except(*exceptions)
88
+ slice(*(keys - exceptions))
89
+ end
90
+
91
+ def value?(value)
92
+ values.include?(value)
93
+ end
94
+
95
+ alias has_value? value?
66
96
  end
67
97
  end
68
98
 
@@ -8,13 +8,13 @@ describe ENV_BANG do
8
8
 
9
9
  it "Raises exception if unconfigured ENV var requested" do
10
10
  ENV['UNCONFIGURED'] = 'unconfigured'
11
- proc { ENV!['UNCONFIGURED'] }.must_raise KeyError
11
+ _{ ENV!['UNCONFIGURED'] }.must_raise KeyError
12
12
  end
13
13
 
14
14
  it "Raises exception if configured ENV var is not present" do
15
15
  ENV.delete('NOT_PRESENT')
16
16
 
17
- proc {
17
+ _{
18
18
  ENV!.config do
19
19
  use 'NOT_PRESENT'
20
20
  end
@@ -22,12 +22,12 @@ describe ENV_BANG do
22
22
  end
23
23
 
24
24
  it "Raises exception immediately if value is invalid for the required type" do
25
- proc {
25
+ _{
26
26
  ENV['NOT_A_DATE'] = '2017-02-30'
27
27
  ENV!.use 'NOT_A_DATE', class: Date
28
28
  }.must_raise ArgumentError
29
29
 
30
- proc {
30
+ _{
31
31
  ENV!.use 'NOT_A_DATE_DEFAULT', class: Date, default: '2017-02-31'
32
32
  }.must_raise ArgumentError
33
33
  end
@@ -38,7 +38,7 @@ describe ENV_BANG do
38
38
  ENV!.config do
39
39
  use 'WASNT_PRESENT', default: 'a default value'
40
40
  end
41
- ENV!['WASNT_PRESENT'].must_equal 'a default value'
41
+ _(ENV!['WASNT_PRESENT']).must_equal 'a default value'
42
42
  end
43
43
 
44
44
  it "Returns actual value from ENV if present" do
@@ -47,7 +47,7 @@ describe ENV_BANG do
47
47
  ENV!.config do
48
48
  use 'PRESENT', default: "You won't need this."
49
49
  end
50
- ENV!['PRESENT'].must_equal 'present in environment'
50
+ _(ENV!['PRESENT']).must_equal 'present in environment'
51
51
  end
52
52
 
53
53
  describe "Type casting" do
@@ -61,14 +61,14 @@ describe ENV_BANG do
61
61
  ENV['INTEGER'] = integer
62
62
  ENV!.use 'INTEGER', class: Integer
63
63
 
64
- ENV!['INTEGER'].must_equal integer.to_i
64
+ _(ENV!['INTEGER']).must_equal integer.to_i
65
65
  end
66
66
 
67
67
  it "Casts Symbols" do
68
68
  ENV['SYMBOL'] = 'symbol'
69
69
  ENV!.use 'SYMBOL', class: Symbol
70
70
 
71
- ENV!['SYMBOL'].must_equal :symbol
71
+ _(ENV!['SYMBOL']).must_equal :symbol
72
72
  end
73
73
 
74
74
  it "Casts Floats" do
@@ -76,29 +76,29 @@ describe ENV_BANG do
76
76
  ENV['FLOAT'] = float
77
77
  ENV!.use 'FLOAT', class: Float
78
78
 
79
- ENV!['FLOAT'].must_equal float.to_f
80
- ENV!['FLOAT'].class.must_equal Float
79
+ _(ENV!['FLOAT']).must_equal float.to_f
80
+ _(ENV!['FLOAT'].class).must_equal Float
81
81
  end
82
82
 
83
83
  it "Casts Arrays" do
84
84
  ENV['ARRAY'] = 'one,two , three, four'
85
85
  ENV!.use 'ARRAY', class: Array
86
86
 
87
- ENV!['ARRAY'].must_equal %w[one two three four]
87
+ _(ENV!['ARRAY']).must_equal %w[one two three four]
88
88
  end
89
89
 
90
90
  it "Casts Arrays of Integers" do
91
91
  ENV['INTEGERS'] = integers.join(',')
92
92
  ENV!.use 'INTEGERS', class: Array, of: Integer
93
93
 
94
- ENV!['INTEGERS'].must_equal integers.map(&:to_i)
94
+ _(ENV!['INTEGERS']).must_equal integers.map(&:to_i)
95
95
  end
96
96
 
97
97
  it "Casts Arrays of Floats" do
98
98
  ENV['FLOATS'] = floats.join(',')
99
99
  ENV!.use 'FLOATS', class: Array, of: Float
100
100
 
101
- ENV!['FLOATS'].must_equal floats.map(&:to_f)
101
+ _(ENV!['FLOATS']).must_equal floats.map(&:to_f)
102
102
  end
103
103
 
104
104
  it "regression: Casting Array always returns Array" do
@@ -106,7 +106,7 @@ describe ENV_BANG do
106
106
  ENV!.use 'ARRAY', class: Array
107
107
 
108
108
  2.times do
109
- ENV!['ARRAY'].must_equal %w[one two three four]
109
+ _(ENV!['ARRAY']).must_equal %w[one two three four]
110
110
  end
111
111
  end
112
112
 
@@ -114,80 +114,80 @@ describe ENV_BANG do
114
114
  ENV['HASH'] = 'one: two, three: http://four.com'
115
115
  ENV!.use 'HASH', class: Hash
116
116
 
117
- ENV!['HASH'].must_equal({one: 'two', three: 'http://four.com'})
117
+ _(ENV!['HASH']).must_equal({one: 'two', three: 'http://four.com'})
118
118
  end
119
119
 
120
120
  it 'Casts Hashes of Integers' do
121
121
  ENV['INT_HASH'] = 'one: 111, two: 222'
122
122
  ENV!.use 'INT_HASH', class: Hash, of: Integer
123
123
 
124
- ENV!['INT_HASH'].must_equal({one: 111, two: 222})
124
+ _(ENV!['INT_HASH']).must_equal({one: 111, two: 222})
125
125
  end
126
126
 
127
127
  it 'Casts Hashes with String keys' do
128
128
  ENV['STRKEY_HASH'] = 'one: two, three: four'
129
129
  ENV!.use 'STRKEY_HASH', class: Hash, keys: String
130
130
 
131
- ENV!['STRKEY_HASH'].must_equal({'one' => 'two', 'three' => 'four'})
131
+ _(ENV!['STRKEY_HASH']).must_equal({'one' => 'two', 'three' => 'four'})
132
132
  end
133
133
 
134
134
  it 'Casts Hashes with alternate separators' do
135
135
  ENV['ALT_HASH'] = 'one:two = three; four,five=six'
136
136
  ENV!.use 'ALT_HASH', class: Hash, sep: ';', val_sep: '='
137
137
 
138
- ENV!['ALT_HASH'].must_equal({:'one:two' => 'three', :'four,five' => 'six'})
138
+ _(ENV!['ALT_HASH']).must_equal({:'one:two' => 'three', :'four,five' => 'six'})
139
139
  end
140
140
 
141
141
  it "Casts true" do
142
142
  ENV['TRUE'] = truthy_values.sample
143
143
  ENV!.use 'TRUE', class: :boolean
144
144
 
145
- ENV!['TRUE'].must_equal true
145
+ _(ENV!['TRUE']).must_equal true
146
146
  end
147
147
 
148
148
  it "Casts false" do
149
149
  ENV['FALSE'] = falsey_values.sample
150
150
  ENV!.use 'FALSE', class: :boolean
151
151
 
152
- ENV!['FALSE'].must_equal false
152
+ _(ENV!['FALSE']).must_equal false
153
153
  end
154
154
 
155
155
  it "converts falsey or empty string to false by default" do
156
156
  ENV['FALSE'] = falsey_values.sample
157
157
  ENV!.use 'FALSE'
158
158
 
159
- ENV!['FALSE'].must_equal false
159
+ _(ENV!['FALSE']).must_equal false
160
160
  end
161
161
 
162
162
  it "leaves falsey string as string if specified" do
163
163
  ENV['FALSE'] = falsey_values.sample
164
164
  ENV!.use 'FALSE', class: String
165
165
 
166
- ENV!['FALSE'].class.must_equal String
166
+ _(ENV!['FALSE'].class).must_equal String
167
167
  end
168
168
 
169
169
  it "casts Dates" do
170
170
  ENV['A_DATE'] = '2005-05-05'
171
171
  ENV!.use 'A_DATE', class: Date
172
172
 
173
- ENV!['A_DATE'].class.must_equal Date
174
- ENV!['A_DATE'].must_equal Date.new(2005, 5, 5)
173
+ _(ENV!['A_DATE'].class).must_equal Date
174
+ _(ENV!['A_DATE']).must_equal Date.new(2005, 5, 5)
175
175
  end
176
176
 
177
177
  it "casts DateTimes" do
178
178
  ENV['A_DATETIME'] = '2005-05-05 5:05pm'
179
179
  ENV!.use 'A_DATETIME', class: DateTime
180
180
 
181
- ENV!['A_DATETIME'].class.must_equal DateTime
182
- ENV!['A_DATETIME'].must_equal DateTime.new(2005, 5, 5, 17, 5)
181
+ _(ENV!['A_DATETIME'].class).must_equal DateTime
182
+ _(ENV!['A_DATETIME']).must_equal DateTime.new(2005, 5, 5, 17, 5)
183
183
  end
184
184
 
185
185
  it "casts Times" do
186
186
  ENV['A_TIME'] = '2005-05-05 5:05pm'
187
187
  ENV!.use 'A_TIME', class: Time
188
188
 
189
- ENV!['A_TIME'].class.must_equal Time
190
- ENV!['A_TIME'].must_equal Time.new(2005, 5, 5, 17, 5)
189
+ _(ENV!['A_TIME'].class).must_equal Time
190
+ _(ENV!['A_TIME']).must_equal Time.new(2005, 5, 5, 17, 5)
191
191
  end
192
192
 
193
193
  it "casts Regexps" do
@@ -195,51 +195,51 @@ describe ENV_BANG do
195
195
  ENV['A_REGEX'] = '^(this|is|a|[^tes.*\|]t.\.\*/\\\)$'
196
196
  ENV!.use 'A_REGEX', class: Regexp
197
197
 
198
- ENV!['A_REGEX'].class.must_equal Regexp
199
- ENV!['A_REGEX'].must_equal(/^(this|is|a|[^tes.*\|]t.\.\*\/\\)$/)
198
+ _(ENV!['A_REGEX'].class).must_equal Regexp
199
+ _(ENV!['A_REGEX']).must_equal(/^(this|is|a|[^tes.*\|]t.\.\*\/\\)$/)
200
200
  end
201
201
 
202
202
  it "casts inclusive Ranges of Integers by default" do
203
203
  ENV['A_RANGE'] = '1..100'
204
204
  ENV!.use 'A_RANGE', class: Range
205
205
 
206
- ENV!['A_RANGE'].class.must_equal Range
207
- ENV!['A_RANGE'].must_equal 1..100
206
+ _(ENV!['A_RANGE'].class).must_equal Range
207
+ _(ENV!['A_RANGE']).must_equal 1..100
208
208
  end
209
209
 
210
210
  it "casts exclusive Ranges as directed" do
211
211
  ENV['EXCLUSIVE_RANGE'] = '1..100'
212
212
  ENV!.use 'EXCLUSIVE_RANGE', class: Range, exclusive: true
213
213
 
214
- ENV!['EXCLUSIVE_RANGE'].must_equal 1...100
214
+ _(ENV!['EXCLUSIVE_RANGE']).must_equal 1...100
215
215
 
216
216
  ENV['ANOTHER_EXCLUSIVE_RANGE'] = '1...100'
217
217
  ENV!.use 'ANOTHER_EXCLUSIVE_RANGE', class: Range, exclusive: true
218
218
 
219
- ENV!['ANOTHER_EXCLUSIVE_RANGE'].must_equal 1...100
219
+ _(ENV!['ANOTHER_EXCLUSIVE_RANGE']).must_equal 1...100
220
220
  end
221
221
 
222
222
  it "casts Ranges of floats" do
223
223
  ENV['FLOAT_RANGE'] = '1.5..100.7'
224
224
  ENV!.use 'FLOAT_RANGE', class: Range, of: Float
225
225
 
226
- ENV!['FLOAT_RANGE'].must_equal 1.5..100.7
226
+ _(ENV!['FLOAT_RANGE']).must_equal 1.5..100.7
227
227
  end
228
228
 
229
229
  it "casts Ranges of strings" do
230
230
  ENV['FLOAT_RANGE'] = 'az..za'
231
231
  ENV!.use 'FLOAT_RANGE', class: Range, of: String
232
232
 
233
- ENV!['FLOAT_RANGE'].must_equal 'az'..'za'
233
+ _(ENV!['FLOAT_RANGE']).must_equal 'az'..'za'
234
234
  end
235
235
 
236
236
  it "allows default class to be overridden" do
237
- ENV!.default_class.must_equal :StringUnlessFalsey
237
+ _(ENV!.default_class).must_equal :StringUnlessFalsey
238
238
  ENV!.config { default_class String }
239
239
  ENV['FALSE'] = falsey_values.sample
240
240
  ENV!.use 'FALSE', class: String
241
241
 
242
- ENV!['FALSE'].class.must_equal String
242
+ _(ENV!['FALSE'].class).must_equal String
243
243
  end
244
244
 
245
245
  it "allows addition of custom types" do
@@ -254,7 +254,7 @@ describe ENV_BANG do
254
254
  use :NUMBER_SET, class: Set, of: Integer
255
255
  end
256
256
 
257
- ENV!['NUMBER_SET'].must_equal Set.new [1, 3, 5, 7, 9]
257
+ _(ENV!['NUMBER_SET']).must_equal Set.new [1, 3, 5, 7, 9]
258
258
  end
259
259
 
260
260
  describe "Kernel casting delegators" do
@@ -262,53 +262,53 @@ describe ENV_BANG do
262
262
  ENV['A_INTEGER'] = '-123'
263
263
  ENV!.use 'A_INTEGER', class: Integer
264
264
 
265
- ENV!['A_INTEGER'].must_equal(-123)
265
+ _(ENV!['A_INTEGER']).must_equal(-123)
266
266
  end
267
267
 
268
268
  it "casts Floats" do
269
269
  ENV['A_FLOAT'] = '123.456'
270
270
  ENV!.use 'A_FLOAT', class: Float
271
271
 
272
- ENV!['A_FLOAT'].must_equal 123.456
272
+ _(ENV!['A_FLOAT']).must_equal 123.456
273
273
  end
274
274
 
275
275
  it "casts Strings" do
276
276
  ENV['A_STRING'] = 'What do I write here?'
277
277
  ENV!.use 'A_STRING', class: String
278
- ENV!['A_STRING'].must_equal 'What do I write here?'
278
+ _(ENV!['A_STRING']).must_equal 'What do I write here?'
279
279
  end
280
280
 
281
281
  it "casts Rationals" do
282
282
  ENV['A_RATIONAL'] = '3/32'
283
283
  ENV!.use 'A_RATIONAL', class: Rational
284
284
 
285
- ENV!['A_RATIONAL'].class.must_equal Rational
286
- ENV!['A_RATIONAL'].must_equal 3.to_r/32
287
- ENV!['A_RATIONAL'].to_s.must_equal '3/32'
285
+ _(ENV!['A_RATIONAL'].class).must_equal Rational
286
+ _(ENV!['A_RATIONAL']).must_equal 3.to_r/32
287
+ _(ENV!['A_RATIONAL'].to_s).must_equal '3/32'
288
288
  end
289
289
 
290
290
  it "casts Complexes" do
291
291
  ENV['A_COMPLEX'] = '123+4i'
292
292
  ENV!.use 'A_COMPLEX', class: Complex
293
293
 
294
- ENV!['A_COMPLEX'].class.must_equal Complex
295
- ENV!['A_COMPLEX'].to_s.must_equal '123+4i'
294
+ _(ENV!['A_COMPLEX'].class).must_equal Complex
295
+ _(ENV!['A_COMPLEX'].to_s).must_equal '123+4i'
296
296
  end
297
297
 
298
298
  it "casts Pathnames" do
299
299
  ENV['A_PATHNAME'] = '~/.git/config'
300
300
  ENV!.use 'A_PATHNAME', class: Pathname
301
301
 
302
- ENV!['A_PATHNAME'].class.must_equal Pathname
303
- ENV!['A_PATHNAME'].to_s.must_equal '~/.git/config'
302
+ _(ENV!['A_PATHNAME'].class).must_equal Pathname
303
+ _(ENV!['A_PATHNAME'].to_s).must_equal '~/.git/config'
304
304
  end
305
305
 
306
306
  it "casts URIs" do
307
307
  ENV['A_URI'] = 'http://www.example.com/path/to/nowhere'
308
308
  ENV!.use 'A_URI', class: URI
309
309
 
310
- ENV!['A_URI'].class.must_equal URI::HTTP
311
- ENV!['A_URI'].to_s.must_equal 'http://www.example.com/path/to/nowhere'
310
+ _(ENV!['A_URI'].class).must_equal URI::HTTP
311
+ _(ENV!['A_URI'].to_s).must_equal 'http://www.example.com/path/to/nowhere'
312
312
  end
313
313
  end
314
314
  end
@@ -320,7 +320,7 @@ describe ENV_BANG do
320
320
  ENV!.use 'VAR1'
321
321
  ENV!.use 'VAR2'
322
322
 
323
- ENV!.keys.must_equal %w[VAR1 VAR2]
323
+ _(ENV!.keys).must_equal %w[VAR1 VAR2]
324
324
  end
325
325
 
326
326
  it "provides configured values" do
@@ -329,7 +329,7 @@ describe ENV_BANG do
329
329
  ENV!.use 'VAR1'
330
330
  ENV!.use 'VAR2'
331
331
 
332
- ENV!.values.must_equal %w[something something\ else]
332
+ _(ENV!.values).must_equal %w[something something\ else]
333
333
  end
334
334
  end
335
335
 
@@ -337,18 +337,18 @@ describe ENV_BANG do
337
337
  it "Includes provided description in error message" do
338
338
  ENV.delete('NOT_PRESENT')
339
339
 
340
- e = proc {
340
+ e = _{
341
341
  ENV!.config do
342
342
  use 'NOT_PRESENT', 'You need a NOT_PRESENT var in your ENV'
343
343
  end
344
344
  }.must_raise(KeyError)
345
- e.message.must_include 'You need a NOT_PRESENT var in your ENV'
345
+ _(e.message).must_include 'You need a NOT_PRESENT var in your ENV'
346
346
  end
347
347
 
348
348
  it "Removes indentation from provided descriptions" do
349
349
  ENV.delete('NOT_PRESENT')
350
350
 
351
- e = proc {
351
+ e = _{
352
352
  ENV!.config do
353
353
  use 'NOT_PRESENT', <<-DESC
354
354
  This multiline description
@@ -358,7 +358,7 @@ describe ENV_BANG do
358
358
  DESC
359
359
  end
360
360
  }.must_raise(KeyError)
361
- e.message.must_include <<-UNINDENTED
361
+ _(e.message).must_include <<-UNINDENTED
362
362
  This multiline description
363
363
  has a lot of indentation
364
364
  varying from line to line
@@ -366,4 +366,173 @@ describe ENV_BANG do
366
366
  UNINDENTED
367
367
  end
368
368
  end
369
+
370
+ describe "Enumerable methods" do
371
+ before do
372
+ ENV['ONE'] = '1'
373
+ ENV['A'] = 'A'
374
+ ENV['INT_HASH'] = 'one: 1, two: 2'
375
+ ENV['FLOAT'] = '1.234'
376
+
377
+ ENV!.config do
378
+ use 'ONE', class: Integer
379
+ use 'A', class: String
380
+ use 'INT_HASH', class: Hash, of: Integer
381
+ use 'FLOAT', class: Float
382
+ end
383
+ end
384
+
385
+ it "converts keys and parsed values to a Hash" do
386
+ _(ENV!.to_h).must_equal({
387
+ 'ONE' => 1,
388
+ 'A' => 'A',
389
+ 'INT_HASH' => { one: 1, two: 2 },
390
+ 'FLOAT' => 1.234,
391
+ })
392
+ end
393
+
394
+ it "Doesn't allow write access via the hash (It's not a reference to internal values)" do
395
+ h = ENV!.to_h
396
+ h['A'] = 'changed'
397
+ _(ENV!['A']).must_equal 'A'
398
+ end
399
+
400
+ it "returns an Array representation of the hash too" do
401
+ _(ENV!.to_a).must_equal [
402
+ ['ONE', 1],
403
+ ['A', 'A'],
404
+ ['INT_HASH', { one: 1, two: 2 }],
405
+ ['FLOAT', 1.234],
406
+ ]
407
+ end
408
+
409
+ it "implements other Enumerable methods too" do
410
+ _(ENV!.each.to_a).must_equal [
411
+ ['ONE', 1],
412
+ ['A', 'A'],
413
+ ['INT_HASH', { one: 1, two: 2 }],
414
+ ['FLOAT', 1.234],
415
+ ]
416
+
417
+ _(ENV!.to_enum.to_a).must_equal ENV!.to_a
418
+ end
419
+ end
420
+
421
+ describe "Hash-like read methods" do
422
+ before do
423
+ ENV['ONE'] = '1'
424
+ ENV['A'] = 'A'
425
+ ENV['INT_HASH'] = 'one: 1, two: 2'
426
+ ENV['FLOAT'] = '1.234'
427
+
428
+ ENV!.config do
429
+ use 'ONE', class: Integer
430
+ use 'A', class: String
431
+ use 'INT_HASH', class: Hash, of: Integer
432
+ use 'FLOAT', class: Float
433
+ end
434
+ end
435
+
436
+ it "implements .assoc and .rassoc correctly" do
437
+ _(ENV!.assoc('ONE')).must_equal ['ONE', 1]
438
+ _(ENV!.rassoc(1)).must_equal ['ONE', 1]
439
+ end
440
+
441
+ it "implements .each_key correctly" do
442
+ _(ENV!.each_key.to_a).must_equal(%w[ONE A INT_HASH FLOAT])
443
+ keys = []
444
+ ENV!.each_key do |key|
445
+ keys << key
446
+ end
447
+ _(keys).must_equal(%w[ONE A INT_HASH FLOAT])
448
+ end
449
+
450
+ it "implements .each_pair correctly" do
451
+ _(ENV!.each_pair.to_a).must_equal(ENV!.to_a)
452
+ pairs = []
453
+ ENV!.each_pair do |pair|
454
+ pairs << pair
455
+ end
456
+ _(pairs).must_equal(ENV!.to_a)
457
+ end
458
+
459
+ it "implements .each_value correctly" do
460
+ _(ENV!.each_value.to_a).must_equal [1, 'A', { one: 1, two: 2 }, 1.234]
461
+ values = []
462
+ ENV!.each_value do |value|
463
+ values << value
464
+ end
465
+ _(values).must_equal [1, 'A', { one: 1, two: 2 }, 1.234]
466
+ end
467
+
468
+ it "implements .empty? correctly" do
469
+ _(ENV!.empty?).must_equal(false)
470
+ end
471
+
472
+ it "implements .except correctly" do
473
+ _(ENV!.except('INT_HASH', 'FLOAT', 'NOTATHING')).must_equal({
474
+ 'ONE' => 1,
475
+ 'A' => 'A',
476
+ })
477
+ end
478
+
479
+ it "implements .fetch correctly" do
480
+ _(ENV!.fetch('ONE')).must_equal 1
481
+ _{
482
+ ENV!.fetch('TWO')
483
+ }.must_raise KeyError
484
+ _(ENV!.fetch('TWO', 2)).must_equal 2
485
+ _(ENV!.fetch('TWO') { 22 }).must_equal 22
486
+ end
487
+
488
+ it "implements .invert correctly" do
489
+ _(ENV!.invert).must_equal({
490
+ 1 => 'ONE',
491
+ 'A' => 'A',
492
+ { one: 1, two: 2 } => 'INT_HASH',
493
+ 1.234 => 'FLOAT',
494
+ })
495
+ end
496
+
497
+ it "implements .key correctly" do
498
+ _(ENV!.key(1)).must_equal 'ONE'
499
+ end
500
+
501
+ it "implements .key?/.has_key? correctly" do
502
+ _(ENV!.key?('ONE')).must_equal true
503
+ _(ENV!.has_key?('ONE')).must_equal true
504
+
505
+ _(ENV!.key?('TWO')).must_equal false
506
+ _(ENV!.has_key?('TWO')).must_equal false
507
+ end
508
+
509
+ it "implements .length correctly" do
510
+ _(ENV!.length).must_equal 4
511
+ _(ENV!.size).must_equal 4
512
+ end
513
+
514
+ it "implements .slice correctly" do
515
+ _(ENV!.slice('INT_HASH', 'FLOAT', 'NOTATHING')).must_equal({
516
+ 'INT_HASH' => { one: 1, two: 2 },
517
+ 'FLOAT' => 1.234,
518
+ })
519
+ end
520
+
521
+ it "implements .to_hash correctly" do
522
+ _(ENV!.to_hash).must_equal ENV!.to_h
523
+ end
524
+
525
+ it "implements .value?/has_value? correctly" do
526
+ _(ENV!.value?(1)).must_equal true
527
+ _(ENV!.value?(2)).must_equal false
528
+ _(ENV!.has_value?(1)).must_equal true
529
+ _(ENV!.has_value?(2)).must_equal false
530
+ end
531
+
532
+ it "implements .values_at correctly" do
533
+ _(ENV!.values_at('INT_HASH', 'FLOAT', 'NOTATHING')).must_equal [
534
+ { one: 1, two: 2 }, 1.234, nil
535
+ ]
536
+ end
537
+ end
369
538
  end
data/test/test_helper.rb CHANGED
@@ -1,13 +1,21 @@
1
- require 'simplecov'
2
- require 'coveralls'
3
-
4
1
  require 'minitest/autorun'
5
2
  require 'minitest/spec'
6
3
 
7
- SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
8
- SimpleCov::Formatter::HTMLFormatter,
9
- Coveralls::SimpleCov::Formatter
10
- ]
11
- SimpleCov.start
4
+ require 'simplecov'
5
+
6
+ SimpleCov.start 'rails' do
7
+ if ENV['CI']
8
+ require 'simplecov-lcov'
9
+
10
+ SimpleCov::Formatter::LcovFormatter.config do |c|
11
+ c.report_with_single_file = true
12
+ c.single_report_path = 'coverage/lcov.info'
13
+ end
14
+
15
+ formatter SimpleCov::Formatter::LcovFormatter
16
+ end
17
+
18
+ add_filter %w[version.rb initializer.rb]
19
+ end
12
20
 
13
21
  require 'env_bang'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: env_bang
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre.rc.1
4
+ version: 2.0.0.alpha.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Camenisch
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-09 00:00:00.000000000 Z
11
+ date: 2023-03-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -46,8 +46,8 @@ executables: []
46
46
  extensions: []
47
47
  extra_rdoc_files: []
48
48
  files:
49
+ - ".circleci/config.yml"
49
50
  - ".gitignore"
50
- - ".travis.yml"
51
51
  - Gemfile
52
52
  - LICENSE.txt
53
53
  - README.md
data/.travis.yml DELETED
@@ -1,14 +0,0 @@
1
- language: ruby
2
- dist: trusty
3
-
4
- rvm:
5
- - 2.0.0
6
- - 2.3.3
7
- - 2.4.0
8
- - ruby-head
9
- - rbx-3.69
10
-
11
- matrix:
12
- fast_finish: true
13
- allow_failures:
14
- - rvm: rbx-3.69