hashr 0.0.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.
- data/Gemfile +2 -0
- data/Gemfile.lock +16 -0
- data/README +0 -0
- data/Rakefile +10 -0
- data/lib/hashr.rb +61 -0
- data/lib/hashr/env_defaults.rb +21 -0
- data/lib/hashr/version.rb +3 -0
- data/test/hashr_test.rb +63 -0
- data/test/test_helper.rb +4 -0
- metadata +66 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/README
ADDED
File without changes
|
data/Rakefile
ADDED
data/lib/hashr.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
class Hashr < Hash
|
2
|
+
autoload :EnvDefaults, 'hashr/env_defaults'
|
3
|
+
|
4
|
+
TEMPLATE = new
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def define(definition)
|
8
|
+
@definition = definition
|
9
|
+
end
|
10
|
+
|
11
|
+
def definition
|
12
|
+
@definition ||= {}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(data = {})
|
17
|
+
replace(deep_includize(deep_hasherize(deep_merge(self.class.definition, data))))
|
18
|
+
end
|
19
|
+
|
20
|
+
def []=(key, value)
|
21
|
+
super(key, value.is_a?(Hash) ? self.class.new(value) : value)
|
22
|
+
end
|
23
|
+
|
24
|
+
def respond_to?(name)
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
def method_missing(name, *args, &block)
|
29
|
+
case name.to_s[-1]
|
30
|
+
when '?'
|
31
|
+
!!self[name.to_s[0..-2].to_sym]
|
32
|
+
when '='
|
33
|
+
self[name.to_s[0..-2].to_sym] = args.first
|
34
|
+
else
|
35
|
+
self[name]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
protected
|
40
|
+
|
41
|
+
def deep_merge(left, right)
|
42
|
+
merger = proc { |key, v1, v2| v1.is_a?(Hash) && v2.is_a?(Hash) ? self.class.new(v1.merge(v2, &merger)) : v2 }
|
43
|
+
left.merge(right || {}, &merger)
|
44
|
+
end
|
45
|
+
|
46
|
+
def deep_hasherize(hash)
|
47
|
+
hash.inject(TEMPLATE.dup) do |result, (key, value)|
|
48
|
+
result.merge(key.to_sym => value.is_a?(Hash) ? deep_hasherize(value) : value)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def deep_includize(hash)
|
53
|
+
if modules = hash.delete(:_include)
|
54
|
+
meta_class = (class << hash; self end)
|
55
|
+
Array(modules).each { |mod| meta_class.send(:include, mod) }
|
56
|
+
end
|
57
|
+
hash.inject(hash) do |hash, (key, value)|
|
58
|
+
hash.merge(key => value.is_a?(Hash) ? deep_includize(value) : value)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class Hashr < Hash
|
2
|
+
module EnvDefaults
|
3
|
+
def definition
|
4
|
+
deep_enverize(super)
|
5
|
+
end
|
6
|
+
|
7
|
+
protected
|
8
|
+
|
9
|
+
def deep_enverize(hash, nesting = ['WORKER'])
|
10
|
+
hash.each do |key, value|
|
11
|
+
nesting << key.to_s.upcase
|
12
|
+
hash[key] = case value
|
13
|
+
when Hash
|
14
|
+
deep_enverize(value, nesting)
|
15
|
+
else
|
16
|
+
ENV.fetch(nesting.join('_'), value)
|
17
|
+
end.tap { nesting.pop }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/test/hashr_test.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class HashrTest < Test::Unit::TestCase
|
4
|
+
def teardown
|
5
|
+
ENV.keys.select { |key| key =~ /^WORKER_/ }.each { |key| ENV.delete(key) }
|
6
|
+
end
|
7
|
+
|
8
|
+
test 'method access on an existing key returns the value' do
|
9
|
+
assert_equal 'foo', Hashr.new({ :foo => 'foo' }).foo
|
10
|
+
end
|
11
|
+
|
12
|
+
test 'method access on a non-existing key returns nil' do
|
13
|
+
assert_nil Hashr.new({ :foo => 'foo' }).bar
|
14
|
+
end
|
15
|
+
|
16
|
+
test 'method access on an existing nested key returns the value' do
|
17
|
+
assert_equal 'bar', Hashr.new({ :foo => { :bar => 'bar' } }).foo.bar
|
18
|
+
end
|
19
|
+
|
20
|
+
test 'method access on a non-existing nested key returns nil' do
|
21
|
+
assert_nil Hashr.new({ :foo => { :bar => 'bar' } }).foo.baz
|
22
|
+
end
|
23
|
+
|
24
|
+
test 'method access with a question mark returns true if the key has a value' do
|
25
|
+
assert_equal true, Hashr.new({ :foo => { :bar => 'bar' } }).foo.bar?
|
26
|
+
end
|
27
|
+
|
28
|
+
test 'method access with a question mark returns false if the key does not have a value' do
|
29
|
+
assert_equal false, Hashr.new({ :foo => { :bar => 'bar' } }).foo.baz?
|
30
|
+
end
|
31
|
+
|
32
|
+
test 'method assignment works' do
|
33
|
+
hashr = Hashr.new
|
34
|
+
hashr.foo = 'foo'
|
35
|
+
assert_equal 'foo', hashr.foo
|
36
|
+
end
|
37
|
+
|
38
|
+
test 'defining defaults' do
|
39
|
+
klass = Class.new(Hashr)
|
40
|
+
klass.define(:foo => 'foo', :bar => { :baz => 'baz' })
|
41
|
+
assert_equal 'foo', klass.new.foo
|
42
|
+
assert_equal 'baz', klass.new.bar.baz
|
43
|
+
end
|
44
|
+
|
45
|
+
test 'defaults to env vars' do
|
46
|
+
klass = Class.new(Hashr)
|
47
|
+
klass.extend Hashr::EnvDefaults
|
48
|
+
klass.define(:foo => 'foo', :bar => { :baz => 'baz' })
|
49
|
+
|
50
|
+
ENV['WORKER_FOO'] = 'env foo'
|
51
|
+
ENV['WORKER_BAR_BAZ'] = 'env bar baz'
|
52
|
+
|
53
|
+
assert_equal 'env foo', klass.new.foo
|
54
|
+
assert_equal 'env bar baz', klass.new.bar.baz
|
55
|
+
end
|
56
|
+
|
57
|
+
test 'a key :_include includes the given modules' do
|
58
|
+
klass = Class.new(Hashr)
|
59
|
+
klass.define(:foo => { :_include => Module.new { def helper; 'helper'; end } })
|
60
|
+
assert_equal 'helper', klass.new.foo.helper
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hashr
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Sven Fuchs
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-07-23 00:00:00.000000000 +02:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: test_declarative
|
17
|
+
requirement: &2165879540 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.0.2
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *2165879540
|
26
|
+
description: Simple Hash extension targetted at configuration.
|
27
|
+
email: svenfuchs@artweb-design.de
|
28
|
+
executables: []
|
29
|
+
extensions: []
|
30
|
+
extra_rdoc_files: []
|
31
|
+
files:
|
32
|
+
- lib/hashr/env_defaults.rb
|
33
|
+
- lib/hashr/version.rb
|
34
|
+
- lib/hashr.rb
|
35
|
+
- test/hashr_test.rb
|
36
|
+
- test/test_helper.rb
|
37
|
+
- Gemfile
|
38
|
+
- Gemfile.lock
|
39
|
+
- Rakefile
|
40
|
+
- README
|
41
|
+
has_rdoc: true
|
42
|
+
homepage: http://github.com/svenfuchs/hashr
|
43
|
+
licenses: []
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options: []
|
46
|
+
require_paths:
|
47
|
+
- lib
|
48
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ! '>='
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
requirements: []
|
61
|
+
rubyforge_project: ! '[none]'
|
62
|
+
rubygems_version: 1.6.2
|
63
|
+
signing_key:
|
64
|
+
specification_version: 3
|
65
|
+
summary: Simple Hash extension targetted at configuration
|
66
|
+
test_files: []
|