envied 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +5 -0
- data/CHANGELOG.md +37 -0
- data/README.md +96 -17
- data/lib/envied/version.rb +3 -0
- data/lib/envied.rb +135 -100
- data/spec/envied_spec.rb +127 -32
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d3ba3eb81e06018962bb52faa7caf1fdf044aca
|
4
|
+
data.tar.gz: a92a83a6a9272771f39eca36b3f0126aac9fd439
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d4643b26e39b59b534285cc8f58f0228285468ec3860c3479b0a1cd3b5041a2d7fae2b40ce176c985105d4a793f705d226eef3ccf9591bc1c87a50f9d1b90a5
|
7
|
+
data.tar.gz: 2407bd5bf9a1700b76d81d77de7a4de9b2b7da1fba44257119444afb9e0e08ed2e4badf19d0f8d7cdecdf314c9a3affb4ef89119d42e0f3a9426bd0ac1d10bae
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# 0.4.0 / 2014-05-16
|
2
|
+
|
3
|
+
* groups added
|
4
|
+
|
5
|
+
This allows for more fine-grained requiring.
|
6
|
+
See the section in the [README](https://github.com/eval/envied/tree/v0.4.0#groups).
|
7
|
+
|
8
|
+
* configuring is now simpler:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
ENVied.configure { variable :RACK_ENV }
|
12
|
+
# vs
|
13
|
+
ENVied.configure {|env| env.variable :RACK_ENV }
|
14
|
+
```
|
15
|
+
|
16
|
+
* Deprecate `require!`. Use `require` instead.
|
17
|
+
|
18
|
+
Just like requiring groups with Bundler.
|
19
|
+
|
20
|
+
* Deprecate lowercase methods for uppercase ENV-variables.
|
21
|
+
|
22
|
+
`ENV['RACK_ENV']` is no longer accessible as `ENVied.rack_env`, only as `ENVied.RACK_ENV`.
|
23
|
+
This is not only what you would expect, but it also reduces the chance of clashing with existing class-methods.
|
24
|
+
|
25
|
+
# 0.3.0 / 2014-03-14
|
26
|
+
|
27
|
+
* defaults need to be enabled explicitly:
|
28
|
+
|
29
|
+
`ENVied.configure(enable_defaults: Rails.env.development?) { ... }`
|
30
|
+
|
31
|
+
# 0.2.0 / 2014-03-14
|
32
|
+
|
33
|
+
* add defaults
|
34
|
+
|
35
|
+
# 0.1.0 / 2014-03-13
|
36
|
+
|
37
|
+
* add defaults
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# ENVied
|
1
|
+
# ENVied [![travis](https://secure.travis-ci.org/eval/envied.png?branch=master)](https://secure.travis-ci.org/#!/eval/envied)
|
2
2
|
|
3
3
|
### TL;DR ensure presence and type of your app's ENV-variables.
|
4
4
|
|
@@ -20,33 +20,61 @@ Let's configure the ENV-variables we need:
|
|
20
20
|
|
21
21
|
```ruby
|
22
22
|
# e.g. config/application.rb
|
23
|
-
ENVied.configure do
|
24
|
-
|
25
|
-
|
23
|
+
ENVied.configure do
|
24
|
+
variable :FORCE_SSL, :Boolean
|
25
|
+
variable :PORT, :Integer
|
26
26
|
end
|
27
27
|
```
|
28
28
|
|
29
29
|
### 2) Check for presence and type
|
30
30
|
|
31
31
|
```ruby
|
32
|
-
ENVied.require
|
32
|
+
ENVied.require
|
33
33
|
```
|
34
|
-
Excecution will halt unless ENV is something like
|
35
|
-
`{'FORCE_SSL' => 'false', 'PORT' => '3001'}`.
|
36
34
|
|
37
|
-
|
35
|
+
This will throw an error if not:
|
36
|
+
* both `ENV['FORCE_SSL']` and `ENV['PORT']` are present
|
37
|
+
* both the values of `ENV['FORCE_SSL']` and `ENV['PORT']` can be coerced (to resp. Boolean or Integer).
|
38
|
+
|
39
|
+
(The error contains exactly what ENV-variables are missing/faulty.)
|
38
40
|
|
39
41
|
### 3) Use typed variables
|
40
42
|
|
41
43
|
Variables accessed via ENVied have the configured type:
|
42
44
|
|
43
45
|
```ruby
|
44
|
-
ENVied.
|
45
|
-
ENVied.
|
46
|
+
ENVied.PORT # => 3001
|
47
|
+
ENVied.FORCE_SSL # => false
|
46
48
|
```
|
47
49
|
|
48
50
|
## Configuration
|
49
51
|
|
52
|
+
### Groups
|
53
|
+
|
54
|
+
Groups give you more flexibility to define when variables are needed.
|
55
|
+
It's just like you Gemfile:
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
ENVied.configure do
|
59
|
+
variable :FORCE_SSL, :Boolean
|
60
|
+
|
61
|
+
group :production do
|
62
|
+
variable :NEW_RELIC_LICENSE_KEY
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# For local development you would typically do:
|
67
|
+
ENVied.require(:default) #=> Only ENV['FORCE_SSL'] is required
|
68
|
+
# On the server:
|
69
|
+
ENVied.require(:default, :production) #=> ...also ENV['NEW_RELIC_LICENSE_KEY'] is required
|
70
|
+
|
71
|
+
# BTW the following are equivalent:
|
72
|
+
ENVied.require
|
73
|
+
ENVied.require(:default)
|
74
|
+
ENVied.require('default')
|
75
|
+
ENVied.require(nil)
|
76
|
+
```
|
77
|
+
|
50
78
|
### Types
|
51
79
|
|
52
80
|
The following types are supported:
|
@@ -63,20 +91,71 @@ The following types are supported:
|
|
63
91
|
In order to let other developers easily bootstrap the application, you can assign defaults to variables.
|
64
92
|
Defaults can be a value or a `Proc` (see example below).
|
65
93
|
|
66
|
-
Note that 'easily bootstrap' is quite the opposite of 'fail-fast when not all ENV-variables are present'. Therefor
|
94
|
+
Note that 'easily bootstrap' is quite the opposite of 'fail-fast when not all ENV-variables are present'. Therefor you should explicitly state whén defaults are allowed:
|
67
95
|
|
68
96
|
```ruby
|
69
|
-
ENVied.configure(enable_defaults:
|
70
|
-
|
71
|
-
|
97
|
+
ENVied.configure(enable_defaults: ENV['RACK_ENV'] == 'development') do
|
98
|
+
variable :FORCE_SSL, :Boolean, default: false
|
99
|
+
variable :PORT, :Integer, default: proc {|envied| envied.FORCE_SSL ? 443 : 80 }
|
72
100
|
end
|
73
101
|
```
|
74
102
|
|
75
|
-
Please remember that ENVied only **reads** from ENV;
|
76
|
-
|
77
|
-
|
103
|
+
Please remember that ENVied only **reads** from ENV; it doesn't set ENV-variables.
|
104
|
+
Don't let setting a default for, say `RAILS_ENV`, give you the impression that `ENV['RAILS_ENV']` is set.
|
105
|
+
As a rule of thumb you should only use defaults:
|
106
|
+
* for local development
|
78
107
|
* for ENV-variables that your application introduces (i.e. for `ENV['DEFAULT_SENDER']` not for `ENV['REDIS_URL']`)
|
79
108
|
|
109
|
+
### A more extensive example:
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
# We allow defaults for local development (and local tests), but want our CI
|
113
|
+
# to mimic our production as much as possible.
|
114
|
+
# New developers that don't have RACK_ENV set, will in this way not be presented with a huge
|
115
|
+
# list of missing variables, as defaults are still enabled.
|
116
|
+
not_production_nor_ci = ->{ !(ENV['RACK_ENV'] == 'production' || ENV['CI']) }
|
117
|
+
ENVied.configure(enable_defaults: ¬_production_nor_ci) do
|
118
|
+
# Your code will likely not use ENVied.RACK_ENV (better use Rails.env),
|
119
|
+
# we want it to be present though; heck, we're using it in this file!
|
120
|
+
variable :RACK_ENV
|
121
|
+
|
122
|
+
variable :FORCE_SSL, :Boolean, default: false
|
123
|
+
variable :PORT, :Integer, default: 3000
|
124
|
+
# generate the default value using the value of PORT:
|
125
|
+
variable :PUBLIC_HOST_WITH_PORT, :String, default: proc {|envied| "localhost:#{envied.PORT}" }
|
126
|
+
|
127
|
+
group :production do
|
128
|
+
variable :MAIL_PAAS_USERNAME
|
129
|
+
variable :DATABASE_URL, :Symbol
|
130
|
+
end
|
131
|
+
|
132
|
+
group :ci do
|
133
|
+
# ci-only stuff
|
134
|
+
end
|
135
|
+
|
136
|
+
group :not_ci do
|
137
|
+
# CI needs no puma-threads, and sidekiq-stuff etc.
|
138
|
+
# Define that here:
|
139
|
+
variable :MIN_THREADS, :Integer, default: 1
|
140
|
+
# more...
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# Depending on our situation, we can now require the groups needed:
|
145
|
+
# At local machines:
|
146
|
+
ENVied.require(:default, :development, :not_ci) or
|
147
|
+
ENVied.require(:default, :test, :not_ci)
|
148
|
+
|
149
|
+
# At the server:
|
150
|
+
ENVied.require(:default, :production, :not_ci)
|
151
|
+
|
152
|
+
# At CI:
|
153
|
+
ENVied.require(:default, :test, :ci)
|
154
|
+
|
155
|
+
# All in one line:
|
156
|
+
ENVied.require(:default, ENV['RACK_ENV'], (ENV['CI'] ? :ci : :not_ci))
|
157
|
+
```
|
158
|
+
|
80
159
|
|
81
160
|
## Installation
|
82
161
|
|
data/lib/envied.rb
CHANGED
@@ -1,137 +1,172 @@
|
|
1
|
+
require 'virtus'
|
2
|
+
|
1
3
|
class ENVied
|
2
|
-
|
3
|
-
|
4
|
+
class Configuration
|
5
|
+
include Virtus.model
|
4
6
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
end
|
7
|
+
def self.variable(name, type = :String, options = {})
|
8
|
+
options = { strict: true, group: self.current_group }.merge(options)
|
9
|
+
attribute(name, type, options)
|
10
|
+
end
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
def self.group(name, &block)
|
13
|
+
self.current_group = name.to_sym
|
14
|
+
yield
|
15
|
+
ensure
|
16
|
+
self.current_group = :default
|
14
17
|
end
|
15
18
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
19
|
+
def self.enable_defaults
|
20
|
+
@enable_defaults.respond_to?(:call) ?
|
21
|
+
@enable_defaults.call :
|
22
|
+
@enable_defaults
|
20
23
|
end
|
21
24
|
|
22
|
-
class
|
23
|
-
|
24
|
-
|
25
|
-
|
25
|
+
class << self
|
26
|
+
attr_writer :enable_defaults
|
27
|
+
alias_method :defaults_enabled?, :enable_defaults
|
28
|
+
attr_accessor :current_group
|
26
29
|
end
|
27
30
|
|
28
|
-
def self.
|
29
|
-
|
30
|
-
|
31
|
+
def self.current_group
|
32
|
+
@current_group ||= :default
|
33
|
+
end
|
34
|
+
end
|
31
35
|
|
32
|
-
|
33
|
-
|
34
|
-
|
36
|
+
def self.configuration(options = {}, &block)
|
37
|
+
if block_given?
|
38
|
+
@configuration = build_configuration(&block).tap do |c|
|
39
|
+
options.each{|k, v| c.public_send("#{k}=", v) }
|
35
40
|
end
|
36
|
-
base.extend ClassMethods
|
37
41
|
end
|
42
|
+
@configuration ||= build_configuration
|
43
|
+
end
|
38
44
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
#
|
44
|
-
# Will raise VariableTypeError for variables whose ENV-value can't be coerced to the configured type.
|
45
|
-
#
|
46
|
-
# @param env [Hash] the env
|
47
|
-
def parse_env(env)
|
48
|
-
atts = attribute_set.map(&:name).each_with_object({}) do |name, result|
|
49
|
-
variable = attribute_set[name]
|
50
|
-
default = variable.options[:default]
|
51
|
-
value = env[name.to_s] || env[name.to_s.upcase]
|
52
|
-
if !(value || default)
|
53
|
-
raise VariableMissingError, variable
|
54
|
-
end
|
55
|
-
|
56
|
-
try_coercion(variable, value, default)
|
57
|
-
result[name] = value if value
|
58
|
-
end
|
59
|
-
|
60
|
-
new(atts)
|
61
|
-
end
|
45
|
+
class << self
|
46
|
+
alias_method :configure, :configuration
|
47
|
+
attr_accessor :required_groups
|
48
|
+
end
|
62
49
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
50
|
+
def self.build_configuration(&block)
|
51
|
+
Class.new(Configuration).tap do |c|
|
52
|
+
c.instance_eval(&block) if block_given?
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.require(*groups)
|
57
|
+
groups.compact!
|
58
|
+
@instance = nil
|
59
|
+
if groups.any?
|
60
|
+
self.required_groups = groups.map(&:to_sym)
|
61
|
+
else
|
62
|
+
self.required_groups = [:default]
|
63
|
+
end
|
64
|
+
error_on_missing_variables!
|
65
|
+
error_on_uncoercible_variables!
|
77
66
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
end
|
83
|
-
return unless value
|
84
|
-
@variable = variable
|
85
|
-
|
86
|
-
variable.coerce(value)
|
87
|
-
rescue Virtus::CoercionError => e
|
88
|
-
raise VariableTypeError.new(@variable)
|
67
|
+
_required_variables = required_variables
|
68
|
+
group_configuration = build_configuration do
|
69
|
+
_required_variables.each do |v|
|
70
|
+
@attribute_set << v
|
89
71
|
end
|
90
72
|
end
|
73
|
+
@instance = group_configuration.new(ENV.to_hash)
|
91
74
|
end
|
92
75
|
|
93
|
-
|
94
|
-
|
76
|
+
def self.error_on_missing_variables!
|
77
|
+
if missing_variable_names.any?
|
78
|
+
raise "Please set the following ENV-variables: #{missing_variable_names.sort.join(',')}"
|
79
|
+
end
|
95
80
|
end
|
96
81
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
82
|
+
def self.error_on_uncoercible_variables!
|
83
|
+
if non_coercible_variables.any?
|
84
|
+
single_error = "ENV['%{name}'] ('%{value}' can't be coerced to %{type})"
|
85
|
+
errors = non_coercible_variables.map do |v|
|
86
|
+
var_type = v.type.to_s.split("::").last
|
87
|
+
single_error % { name: v.name, value: env_value_or_default(v), type: var_type }
|
88
|
+
end.join ", "
|
89
|
+
|
90
|
+
raise "Some ENV-variables are not coercible: #{errors}"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.env_value(variable)
|
95
|
+
ENV[variable.name.to_s]
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.env_value_or_default(variable)
|
99
|
+
env_value(variable) || default_value(variable)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Yields the assigned default for the variable.
|
103
|
+
# When defaults are disabled, nil is returned.
|
104
|
+
def self.default_value(variable)
|
105
|
+
defaults_enabled? ? variable.default_value.value : nil
|
106
|
+
end
|
107
|
+
|
108
|
+
# A list of all configured variable names.
|
101
109
|
#
|
102
110
|
# @example
|
103
|
-
# ENVied.
|
104
|
-
#
|
105
|
-
# end
|
111
|
+
# ENVied.configured_variable_names
|
112
|
+
# # => [:DATABASE_URL]
|
106
113
|
#
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
k.enable_defaults = options[:enable_defaults]
|
111
|
-
k.instance_eval(&block)
|
112
|
-
end
|
113
|
-
# or define this thing as ENVied::Configuration? prolly not threadsafe
|
114
|
-
ensure
|
115
|
-
@instance = nil
|
114
|
+
# @return [Array<Symbol>] the list of variable names
|
115
|
+
def self.required_variable_names
|
116
|
+
required_variables.map(&:name).map(&:to_sym)
|
116
117
|
end
|
117
118
|
|
118
|
-
def self.
|
119
|
-
|
119
|
+
def self.required_variables
|
120
|
+
from_required_group = ->(var){ self.required_groups.include?(var.options[:group]) }
|
121
|
+
configured_variables.to_a.keep_if(&from_required_group)
|
120
122
|
end
|
121
|
-
|
122
|
-
|
123
|
+
|
124
|
+
def self.configured_variables
|
125
|
+
configuration.attribute_set.dup#.to_a.keep_if(&var_from_required_group)
|
126
|
+
end
|
127
|
+
|
128
|
+
def self.provided_variable_names
|
129
|
+
ENV.keys.map(&:to_sym)
|
130
|
+
end
|
131
|
+
|
132
|
+
def self.non_coercible_variables
|
133
|
+
required_variables.reject(&method(:variable_coercible?))
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.variable_coercible?(variable)
|
137
|
+
var_value = env_value_or_default(variable)
|
138
|
+
return true if var_value.respond_to?(:call)
|
139
|
+
|
140
|
+
variable.coerce var_value
|
141
|
+
rescue Virtus::CoercionError
|
142
|
+
return false
|
143
|
+
end
|
144
|
+
|
145
|
+
def self.missing_variable_names
|
146
|
+
unprovided = required_variable_names - provided_variable_names
|
147
|
+
unprovided -= names_of_required_variables_with_defaults if defaults_enabled?
|
148
|
+
unprovided
|
149
|
+
end
|
150
|
+
|
151
|
+
def self.names_of_required_variables_with_defaults
|
152
|
+
required_variables_with_defaults.map(&:name).map(&:to_sym)
|
153
|
+
end
|
154
|
+
|
155
|
+
def self.required_variables_with_defaults
|
156
|
+
required_variables.map do |v|
|
157
|
+
v unless v.default_value.value.nil?
|
158
|
+
end.compact
|
123
159
|
end
|
124
160
|
|
125
|
-
def self.
|
126
|
-
|
127
|
-
#instance[key] # will raise and complain that <class <>> doesn't response; better?
|
161
|
+
def self.defaults_enabled?
|
162
|
+
configuration.enable_defaults
|
128
163
|
end
|
129
164
|
|
130
165
|
def self.method_missing(method, *args, &block)
|
131
|
-
respond_to_missing?(method) ? instance.public_send(method, *args, &block) : super
|
166
|
+
respond_to_missing?(method) ? @instance.public_send(method, *args, &block) : super
|
132
167
|
end
|
133
168
|
|
134
169
|
def self.respond_to_missing?(method, include_private = false)
|
135
|
-
instance.
|
170
|
+
@instance.respond_to?(method) || super
|
136
171
|
end
|
137
172
|
end
|
data/spec/envied_spec.rb
CHANGED
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
describe ENVied do
|
4
4
|
subject { described_class }
|
5
5
|
|
6
|
-
it { should respond_to :require
|
6
|
+
it { should respond_to :require }
|
7
7
|
it { should respond_to :configure }
|
8
8
|
|
9
9
|
context 'configured' do
|
@@ -14,14 +14,16 @@ describe ENVied do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def configure(options = {}, &block)
|
17
|
+
described_class.instance_eval { @configuration = nil }
|
17
18
|
described_class.configure(options, &block)
|
18
19
|
self
|
19
20
|
end
|
20
21
|
|
21
22
|
def configured_with(hash = {})
|
22
|
-
described_class.
|
23
|
+
described_class.instance_eval { @configuration = nil }
|
24
|
+
described_class.configure do
|
23
25
|
hash.each do |name, type|
|
24
|
-
|
26
|
+
variable(name, *type)
|
25
27
|
end
|
26
28
|
end
|
27
29
|
self
|
@@ -37,62 +39,155 @@ describe ENVied do
|
|
37
39
|
end
|
38
40
|
|
39
41
|
it 'responds to configured variables' do
|
40
|
-
configured_with(a: :Integer).and_ENV({'
|
42
|
+
configured_with(a: :Integer).and_ENV({'a' => '1'})
|
43
|
+
described_class.require
|
44
|
+
|
41
45
|
is_expected.to respond_to :a
|
42
46
|
end
|
43
47
|
|
44
48
|
it 'responds not to unconfigured variables' do
|
45
49
|
unconfigured.and_ENV({'A' => '1'})
|
46
|
-
|
50
|
+
described_class.require
|
51
|
+
|
52
|
+
is_expected.to_not respond_to :B
|
47
53
|
end
|
48
54
|
|
49
55
|
context 'ENV contains not all configured variables' do
|
50
56
|
before { configured_with(a: :Integer).and_no_ENV }
|
51
57
|
|
52
|
-
|
53
|
-
expect {
|
54
|
-
ENVied.require!
|
55
|
-
}.to raise_error(ENVied::Configurable::VariableMissingError)
|
56
|
-
end
|
57
|
-
|
58
|
-
it 'raises EnvMissing when interacted with' do
|
58
|
+
specify do
|
59
59
|
expect {
|
60
|
-
ENVied.
|
61
|
-
}.to raise_error
|
60
|
+
ENVied.require
|
61
|
+
}.to raise_error /set the following ENV-variables: a/
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
-
context 'ENV
|
66
|
-
before { configured_with(
|
65
|
+
context 'ENV variables are not coercible' do
|
66
|
+
before { configured_with(A: :Integer).and_ENV('A' => 'NaN') }
|
67
67
|
|
68
68
|
specify do
|
69
69
|
expect {
|
70
|
-
ENVied.
|
71
|
-
}.to raise_error(
|
70
|
+
ENVied.require
|
71
|
+
}.to raise_error /ENV\['A'\] \('NaN' can't be coerced to Integer/
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
75
|
-
describe '
|
76
|
-
|
77
|
-
|
75
|
+
describe 'defaults' do
|
76
|
+
describe 'setting' do
|
77
|
+
subject { described_class.configuration }
|
78
|
+
|
79
|
+
it 'is disabled by default' do
|
80
|
+
expect(subject.enable_defaults).to_not be
|
81
|
+
end
|
78
82
|
|
79
|
-
|
83
|
+
it 'can be enabled via #configure' do
|
84
|
+
configure(enable_defaults: true){ }
|
85
|
+
|
86
|
+
expect(subject.enable_defaults).to be
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'can be enabled via a configure-block' do
|
90
|
+
configure { self.enable_defaults = true }
|
91
|
+
|
92
|
+
expect(subject.enable_defaults).to be
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'can be assigned a Proc' do
|
96
|
+
configure { self.enable_defaults = -> { true } }
|
97
|
+
|
98
|
+
expect(subject.enable_defaults).to be
|
99
|
+
end
|
80
100
|
end
|
81
101
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
102
|
+
describe 'assigning' do
|
103
|
+
it 'can be a value' do
|
104
|
+
configure(enable_defaults: true) do
|
105
|
+
variable :A, :Integer, default: 1
|
106
|
+
end
|
107
|
+
described_class.require
|
108
|
+
|
109
|
+
expect(described_class.A).to eq 1
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'can be a Proc' do
|
113
|
+
configure(enable_defaults: true) do
|
114
|
+
variable :A, :Integer, default: proc { 1 }
|
115
|
+
end
|
116
|
+
described_class.require
|
86
117
|
|
87
|
-
|
118
|
+
expect(described_class.A).to eq 1
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'is ignored if defaults are disabled' do
|
122
|
+
configure(enable_defaults: false) do
|
123
|
+
variable :A, :Integer, default: 1
|
124
|
+
end.and_no_ENV
|
125
|
+
|
126
|
+
expect {
|
127
|
+
described_class.require
|
128
|
+
}.to raise_error
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'is is ignored if ENV is provided' do
|
132
|
+
configure(enable_defaults: true) do
|
133
|
+
variable :A, :Integer, default: 1
|
134
|
+
end.and_ENV('A' => '2')
|
135
|
+
described_class.require
|
136
|
+
|
137
|
+
expect(described_class.A).to eq 2
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'can be defined in terms of other variables' do
|
141
|
+
configure(enable_defaults: true) do
|
142
|
+
variable :A, :Integer
|
143
|
+
variable :B, :Integer, default: proc {|env| env.A * 2 }
|
144
|
+
end.and_ENV('A' => '1')
|
145
|
+
described_class.require
|
146
|
+
|
147
|
+
expect(described_class.B).to eq 2
|
148
|
+
end
|
88
149
|
end
|
150
|
+
end
|
151
|
+
describe "groups" do
|
152
|
+
context 'a variable in a group' do
|
153
|
+
before do
|
154
|
+
configure do
|
155
|
+
variable :moar
|
156
|
+
|
157
|
+
group :foo do
|
158
|
+
variable :bar
|
159
|
+
end
|
160
|
+
end.and_no_ENV
|
161
|
+
end
|
89
162
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
163
|
+
it 'is required when requiring the group' do
|
164
|
+
expect {
|
165
|
+
described_class.require(:foo)
|
166
|
+
}.to raise_error /bar/
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'is not required when requiring another group' do
|
170
|
+
expect {
|
171
|
+
described_class.require(:bat)
|
172
|
+
}.to_not raise_error
|
173
|
+
end
|
94
174
|
|
95
|
-
|
175
|
+
it 'wont define non-required variables on ENVied' do
|
176
|
+
stub_const("ENV", {'moar' => 'yes'})
|
177
|
+
described_class.require(:default)
|
178
|
+
|
179
|
+
expect {
|
180
|
+
described_class.bar
|
181
|
+
}.to raise_error
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'requires variables without a group when requiring the default group' do
|
185
|
+
[:default, 'default'].each do |groups|
|
186
|
+
expect {
|
187
|
+
described_class.require(*groups)
|
188
|
+
}.to raise_error /moar/
|
189
|
+
end
|
190
|
+
end
|
96
191
|
end
|
97
192
|
end
|
98
193
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: envied
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gert Goet
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-05-
|
11
|
+
date: 2014-05-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: virtus
|
@@ -74,12 +74,15 @@ extensions: []
|
|
74
74
|
extra_rdoc_files: []
|
75
75
|
files:
|
76
76
|
- ".gitignore"
|
77
|
+
- ".travis.yml"
|
78
|
+
- CHANGELOG.md
|
77
79
|
- Gemfile
|
78
80
|
- LICENSE.txt
|
79
81
|
- README.md
|
80
82
|
- Rakefile
|
81
83
|
- envied.gemspec
|
82
84
|
- lib/envied.rb
|
85
|
+
- lib/envied/version.rb
|
83
86
|
- spec/envied_spec.rb
|
84
87
|
- spec/spec_helper.rb
|
85
88
|
- underconstruction.gif
|