inherited-hash 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/inherited-hash.rb +36 -23
- data/lib/inherited-hash/version.rb +1 -1
- data/spec/inherited-hash_spec.rb +43 -28
- metadata +4 -4
data/lib/inherited-hash.rb
CHANGED
@@ -1,23 +1,36 @@
|
|
1
1
|
require "inherited-hash/version"
|
2
2
|
|
3
3
|
module InheritedHash
|
4
|
-
def
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
4
|
+
def self.extended(base)
|
5
|
+
base.send(:include, InstanceMethods)
|
6
|
+
base.extend ClassMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
module InstanceMethods
|
10
|
+
def inherited_hashes
|
11
|
+
@inherited_hashes ||= Hash.new do |h,name|
|
12
|
+
h[name] = ConnectedHash.new.connect(self,name)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
include InstanceMethods
|
19
|
+
|
20
|
+
def inherited_hash_accessor *names
|
21
|
+
names.each do |name|
|
22
|
+
[self,class<<self;self;end].each do |context|
|
23
|
+
context.send(%Q{instance_eval}.to_s) do
|
24
|
+
define_method(name) do
|
25
|
+
inherited_hashes[name]
|
26
|
+
end
|
27
|
+
define_method(%Q{#{name}!}.to_sym) do
|
28
|
+
inherited_hashes[name].to_hash!
|
29
|
+
end
|
30
|
+
define_method(%Q{#{name}=}.to_sym) do |hsh|
|
31
|
+
raise ArgumentError, 'Only hashes are allowed' unless hsh.is_a? Hash
|
32
|
+
inherited_hashes[name].replace(hsh)
|
12
33
|
end
|
13
|
-
instance_variable_get( storage)
|
14
|
-
end
|
15
|
-
define_method(%Q{#{name}!}.to_sym) do
|
16
|
-
send(name).to_hash!
|
17
|
-
end
|
18
|
-
define_method(%Q{#{name}=}.to_sym) do |hsh|
|
19
|
-
raise ArgumentError, 'Only hashes are allowed' unless hsh.is_a? Hash
|
20
|
-
send(name).replace(hsh)
|
21
34
|
end
|
22
35
|
end
|
23
36
|
end
|
@@ -37,11 +50,11 @@ module InheritedHash
|
|
37
50
|
def to_hash!
|
38
51
|
verify!
|
39
52
|
return @anchor.class.send(%Q{#{@name}!}.to_sym).merge(self.to_hash) unless @anchor.is_a? Module
|
40
|
-
|
41
|
-
@anchor.ancestors.reverse.
|
42
|
-
|
43
|
-
|
44
|
-
|
53
|
+
|
54
|
+
@anchor.ancestors.reverse.map do |ancestor|
|
55
|
+
next nil unless ancestor.respond_to?(:inherited_hashes)
|
56
|
+
ancestor.inherited_hashes[@name].to_hash
|
57
|
+
end.compact.reduce({},:merge)
|
45
58
|
end
|
46
59
|
|
47
60
|
def to_hash
|
@@ -53,8 +66,8 @@ module InheritedHash
|
|
53
66
|
return @anchor if has_key? key
|
54
67
|
return @anchor.class.send(@name).find_definition_of(key) unless @anchor.is_a? Module
|
55
68
|
@anchor.ancestors.reverse.index do |ancestor|
|
56
|
-
next
|
57
|
-
return ancestor if ancestor.
|
69
|
+
next nil unless ancestor.respond_to?(:inherited_hashes)
|
70
|
+
return ancestor if ancestor.inherited_hashes[@name].has_key?(key)
|
58
71
|
end
|
59
72
|
end
|
60
73
|
end
|
data/spec/inherited-hash_spec.rb
CHANGED
@@ -40,6 +40,12 @@ describe 'InheritedHash' do
|
|
40
40
|
@s[:leaf2_shoot1] = Class.new(@s[:leaf2]) do
|
41
41
|
foo[:existing_key] = 'changed!'
|
42
42
|
end
|
43
|
+
@s[:leaf_with_colliding_module_extended] = Class.new(@s[:leaf1]) do
|
44
|
+
extend Module.new{ def foo() [] end }
|
45
|
+
end
|
46
|
+
@s[:leaf_with_colliding_module_included] = Class.new(@s[:leaf1]) do
|
47
|
+
include Module.new{ def foo() [] end }
|
48
|
+
end
|
43
49
|
|
44
50
|
@s
|
45
51
|
end
|
@@ -71,36 +77,45 @@ describe 'InheritedHash' do
|
|
71
77
|
subject.foo![:not_overridden].should == "don't override me"
|
72
78
|
end
|
73
79
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
80
|
+
[
|
81
|
+
:leaf1,
|
82
|
+
:leaf_with_colliding_module_extended,
|
83
|
+
:leaf_with_colliding_module_included
|
84
|
+
].compact.each do |node|
|
85
|
+
context "instance of #{node}" do
|
86
|
+
subject do
|
87
|
+
s = @s[node].new
|
88
|
+
s.foo = {:another_new_key => 'ooh, shiny'}
|
89
|
+
s
|
90
|
+
end
|
91
|
+
it 'should have access to instance-set key' do
|
92
|
+
subject.foo![:another_new_key].should == 'ooh, shiny'
|
93
|
+
end
|
94
|
+
it 'should have access to keys inherited from class' do
|
95
|
+
subject.foo![:existing_key].should == 'changed'
|
96
|
+
end
|
97
|
+
it 'should have access to keys inherited from root' do
|
98
|
+
subject.foo![:not_overridden].should == "don't override me"
|
99
|
+
end
|
100
|
+
|
101
|
+
# don't run these on colliding, since colliding by definition breaks this
|
102
|
+
if node == :leaf1
|
103
|
+
it 'should be able to find the definition in the object' do
|
104
|
+
subject.foo.find_definition_of(:another_new_key).should be subject
|
105
|
+
end
|
106
|
+
it 'should be able to find the definition in the class' do
|
107
|
+
subject.foo.find_definition_of(:new_key).should be subject.class
|
108
|
+
subject.foo.find_definition_of(:existing_key).should be subject.class
|
109
|
+
end
|
110
|
+
it 'should be able to find the definition in the root' do
|
111
|
+
subject.foo.find_definition_of(:not_overridden).should be @s[:root]
|
112
|
+
end
|
113
|
+
it 'should not be able to find a definition that does not exist' do
|
114
|
+
subject.foo.find_definition_of(:not_exist).should be_nil
|
115
|
+
end
|
116
|
+
end
|
101
117
|
end
|
102
118
|
end
|
103
119
|
end
|
104
|
-
|
105
120
|
end
|
106
121
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: inherited-hash
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 1.0.
|
9
|
+
- 1
|
10
|
+
version: 1.0.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ryan Biesemeyer
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
18
|
+
date: 2012-01-06 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: rspec
|