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 ADDED
@@ -0,0 +1,2 @@
1
+ source :rubygems
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,16 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ hashr (0.0.1)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ test_declarative (0.0.5)
10
+
11
+ PLATFORMS
12
+ ruby
13
+
14
+ DEPENDENCIES
15
+ hashr!
16
+ test_declarative (>= 0.0.2)
data/README ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'lib' << 'test'
6
+ t.pattern = 'test/**/*_test.rb'
7
+ t.verbose = false
8
+ end
9
+
10
+ task :default => :test
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
@@ -0,0 +1,3 @@
1
+ class Hashr < Hash
2
+ VERSION = "0.0.1"
3
+ end
@@ -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
+
@@ -0,0 +1,4 @@
1
+ require 'bundler/setup'
2
+ require 'test/unit'
3
+ require 'test_declarative'
4
+ require 'hashr'
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: []