Skip to content

Commit

Permalink
re-add env defaults support
Browse files Browse the repository at this point in the history
  • Loading branch information
svenfuchs committed Oct 4, 2015
1 parent eec61f1 commit fe01837
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 37 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ defaults from environment variables:

```ruby
class Config < Hashr
extend Hashr::EnvDefaults
extend Hashr::Env

self.env_namespace = 'foo'

Expand Down
6 changes: 3 additions & 3 deletions lib/hashr.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
class Hashr < BasicObject
require 'hashr/core_ext/ruby/hash'
require 'hashr/env_defaults'
require 'hashr/env'

class << self
attr_reader :defaults
Expand Down Expand Up @@ -46,7 +46,7 @@ def [](key)
end

def []=(key, value)
@data.store(to_key(key), value.is_a?(::Hash) ? self.class.new(value, {}) : value)
@data.store(to_key(key), value.is_a?(::Hash) ? ::Hashr.new(value, {}) : value)
end

def values_at(*keys)
Expand Down Expand Up @@ -95,7 +95,7 @@ def is_a?(const)
alias kind_of? is_a?

def inspect
"<Hashr #{@data.inspect}>"
"<#{self.class.name} #{@data.inspect}>"
end

private
Expand Down
48 changes: 48 additions & 0 deletions lib/hashr/env.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
class Hashr
module Env
class Vars < Struct.new(:defaults, :namespace)
FALSE = [false, nil, 'false', 'nil', '']

def to_h
defaults.deep_merge(read_env(defaults, namespace.dup))
end

private

def read_env(defaults, namespace)
defaults.inject({}) do |result, (key, default)|
keys = namespace + [key]
value = default.is_a?(Hash) ? read_env(default, keys) : var(keys, default)
result.merge(key => value)
end
end

def var(keys, default)
key = keys.map(&:upcase).join('_')
value = ENV.fetch(key, default)
cast(value, default, keys)
end

def cast(value, default, keys)
case default
when Array
value.respond_to?(:split) ? value.split(',') : Array(value)
when true, false
not FALSE.include?(value)
else
value
end
end

def namespace
Array(super && super.upcase)
end
end

attr_accessor :env_namespace

def defaults
Vars.new(super, env_namespace).to_h
end
end
end
33 changes: 0 additions & 33 deletions lib/hashr/env_defaults.rb

This file was deleted.

64 changes: 64 additions & 0 deletions spec/hashr/env_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
describe Hashr::Env do
let(:klass) do
Class.new(Hashr) do
extend Hashr::Env

self.env_namespace = 'hashr'

define string: 'string',
hash: { key: 'value' },
array: ['foo', 'bar'],
bool: false
end
end

after do
ENV.keys.each { |key| ENV.delete(key) if key.start_with?('HASHR_') }
end

it 'defaults to an env var' do
ENV['HASHR_STRING'] = 'env string'
expect(klass.new.string).to eq('env string')
end

it 'defaults to a nested env var' do
ENV['HASHR_HASH_KEY'] = 'env value'
expect(klass.new.hash.key).to eq('env value')
end

describe 'type casts based on the default' do
describe 'to boolean' do
it 'true given' do
ENV['HASHR_BOOL'] = 'true'
expect(klass.new.bool).to eq(true)
end

it 'false given' do
ENV['HASHR_BOOL'] = 'false'
expect(klass.new.bool).to eq(false)
end

it 'empty string given' do
ENV['HASHR_BOOL'] = ''
expect(klass.new.bool).to eq(false)
end
end

describe 'to an array' do
it 'splits a comma-separated string' do
ENV['HASHR_ARRAY'] = 'env foo,env bar'
expect(klass.new.array).to eq(['env foo', 'env bar'])
end

it 'returns an empty array for an empty string' do
ENV['HASHR_ARRAY'] = ''
expect(klass.new.array).to eq([])
end
end
end

it 'data takes precedence over an env var' do
ENV['HASHR_STRING'] = 'env string'
expect(klass.new(string: 'data string').string).to eq('data string')
end
end

0 comments on commit fe01837

Please sign in to comment.