hashr 0.0.6 → 0.0.7

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.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- hashr (0.0.5)
4
+ hashr (0.0.6)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
@@ -1,3 +1,5 @@
1
+ require 'hashr/core_ext/ruby/hash'
2
+
1
3
  class Hashr < Hash
2
4
  autoload :EnvDefaults, 'hashr/env_defaults'
3
5
 
@@ -7,7 +9,7 @@ class Hashr < Hash
7
9
  attr_accessor :raise_missing_keys
8
10
 
9
11
  def define(definition)
10
- @definition = definition
12
+ @definition = definition.deep_symbolize_keys
11
13
  end
12
14
 
13
15
  def definition
@@ -15,13 +17,12 @@ class Hashr < Hash
15
17
  end
16
18
  end
17
19
 
18
- def initialize(data = {})
19
- include_modules(data.delete(:_include)) if data
20
- replace(deep_hasherize(deep_merge(self.class.definition, data)))
20
+ def initialize(data = {}, definition = self.class.definition)
21
+ replace(deep_hashrize(definition.deep_merge(data.deep_symbolize_keys)))
21
22
  end
22
23
 
23
24
  def []=(key, value)
24
- super(key, value.is_a?(Hash) ? self.class.new(value) : value)
25
+ super(key, value.is_a?(Hash) ? self.class.new(value, {}) : value)
25
26
  end
26
27
 
27
28
  def respond_to?(name)
@@ -40,24 +41,23 @@ class Hashr < Hash
40
41
  end
41
42
  end
42
43
 
43
- protected
44
-
45
- def include_modules(modules)
46
- Array(modules).each { |mod| meta_class.send(:include, mod) } if modules
47
- end
44
+ def include_modules(modules)
45
+ Array(modules).each { |mod| meta_class.send(:include, mod) } if modules
46
+ end
48
47
 
49
- def meta_class
50
- class << self; self end
51
- end
48
+ def meta_class
49
+ class << self; self end
50
+ end
52
51
 
53
- def deep_merge(left, right)
54
- merger = proc { |key, v1, v2| v1.is_a?(Hash) && v2.is_a?(Hash) ? self.class.new(v1.merge(v2, &merger)) : v2 }
55
- left.merge(right || {}, &merger)
56
- end
52
+ protected
57
53
 
58
- def deep_hasherize(hash)
54
+ def deep_hashrize(hash)
59
55
  hash.inject(TEMPLATE.dup) do |result, (key, value)|
60
- result[key.to_sym] = value.is_a?(Hash) ? deep_hasherize(value) : value
56
+ if key.to_sym == :_include
57
+ result.include_modules(value)
58
+ else
59
+ result.store(key.to_sym, value.is_a?(Hash) ? deep_hashrize(value) : value)
60
+ end
61
61
  result
62
62
  end
63
63
  end
@@ -0,0 +1,28 @@
1
+ class Hash
2
+ def slice(*keep_keys)
3
+ h = {}
4
+ keep_keys.each { |key| h[key] = fetch(key) }
5
+ h
6
+ end unless Hash.method_defined?(:slice)
7
+
8
+ def except(*less_keys)
9
+ slice(*keys - less_keys)
10
+ end unless Hash.method_defined?(:except)
11
+
12
+ def deep_symbolize_keys
13
+ inject({}) { |result, (key, value)|
14
+ value = value.deep_symbolize_keys if value.is_a?(Hash)
15
+ result[(key.to_sym rescue key) || key] = value
16
+ result
17
+ }
18
+ end unless Hash.method_defined?(:deep_symbolize_keys)
19
+
20
+ # deep_merge_hash! by Stefan Rusterholz, see http://www.ruby-forum.com/topic/142809
21
+ MERGER = proc do |key, v1, v2|
22
+ Hash === v1 && Hash === v2 ? v1.merge(v2, &MERGER) : v2
23
+ end
24
+
25
+ def deep_merge(other)
26
+ merge(other, &MERGER)
27
+ end unless Hash.method_defined?(:deep_merge)
28
+ end
@@ -1,3 +1,3 @@
1
1
  class Hashr < Hash
2
- VERSION = "0.0.6"
2
+ VERSION = "0.0.7"
3
3
  end
@@ -41,6 +41,24 @@ class HashrTest < Test::Unit::TestCase
41
41
  assert_equal false, Hashr.new({ :foo => { :bar => 'bar' } }).foo.baz?
42
42
  end
43
43
 
44
+ test 'mixing symbol and string keys in defaults and data' do
45
+ Symbolized = Class.new(Hashr) { define :foo => 'foo' }
46
+ Stringified = Class.new(Hashr) { define 'foo' => 'foo' }
47
+ NoDefault = Class.new(Hashr)
48
+
49
+ assert_equal 'foo', Symbolized.new.foo
50
+ assert_equal 'foo', Stringified.new.foo
51
+ assert_nil NoDefault.new.foo
52
+
53
+ assert_equal 'foo', Symbolized.new(:foo => 'foo').foo
54
+ assert_equal 'foo', Stringified.new(:foo => 'foo').foo
55
+ assert_equal 'foo', NoDefault.new(:foo => 'foo').foo
56
+
57
+ assert_equal 'foo', Symbolized.new('foo' => 'foo').foo
58
+ assert_equal 'foo', Stringified.new('foo' => 'foo').foo
59
+ assert_equal 'foo', NoDefault.new('foo' => 'foo').foo
60
+ end
61
+
44
62
  test 'method assignment works' do
45
63
  hashr = Hashr.new
46
64
  hashr.foo = 'foo'
@@ -94,6 +112,14 @@ class HashrTest < Test::Unit::TestCase
94
112
  end
95
113
 
96
114
  test 'a key :_include includes the given modules' do
115
+ klass = Class.new(Hashr) do
116
+ define :foo => { :_include => Module.new { def helper; 'helper'; end } }
117
+ end
118
+ hashr = klass.new(:foo => { 'helper' => 'foo' })
119
+ assert_equal 'helper', klass.new(:foo => { 'helper' => 'foo' }).foo.helper
120
+ end
121
+
122
+ test 'a key :_include includes the given modules (using defaults)' do
97
123
  klass = Class.new(Hashr) do
98
124
  define :foo => { :_include => Module.new { def helper; 'helper'; end } }
99
125
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hashr
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 17
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 6
10
- version: 0.0.6
9
+ - 7
10
+ version: 0.0.7
11
11
  platform: ruby
12
12
  authors:
13
13
  - Sven Fuchs
@@ -57,6 +57,7 @@ extensions: []
57
57
  extra_rdoc_files: []
58
58
 
59
59
  files:
60
+ - lib/hashr/core_ext/ruby/hash.rb
60
61
  - lib/hashr/env_defaults.rb
61
62
  - lib/hashr/version.rb
62
63
  - lib/hashr.rb