classy_struct 0.1.0 → 0.2.0
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/README.rdoc +1 -1
- data/VERSION +1 -1
- data/lib/classy_struct.rb +26 -5
- data/spec/classy_struct_spec.rb +76 -6
- metadata +2 -2
data/README.rdoc
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/lib/classy_struct.rb
CHANGED
@@ -1,14 +1,20 @@
|
|
1
1
|
class ClassyStruct
|
2
|
-
def self.new
|
3
|
-
Class.new(ClassyStructClass)
|
2
|
+
def self.new(&block)
|
3
|
+
klass = Class.new(ClassyStructClass)
|
4
|
+
klass.method_mapper = block
|
5
|
+
klass
|
4
6
|
end
|
5
7
|
|
6
8
|
class ClassyStructClass
|
7
9
|
def initialize(hash=hil)
|
8
10
|
if hash
|
9
11
|
hash.each_pair do |k,v|
|
12
|
+
k = self.class.method_mapper.call(k.to_s) if self.class.method_mapper
|
13
|
+
|
10
14
|
if v.is_a?(Hash)
|
11
15
|
v = self.class.node_class(k).new(v)
|
16
|
+
elsif v.is_a?(Array)
|
17
|
+
v = self.class.map_array(k, v)
|
12
18
|
end
|
13
19
|
|
14
20
|
send("#{k}=", v)
|
@@ -16,9 +22,24 @@ class ClassyStruct
|
|
16
22
|
end
|
17
23
|
end
|
18
24
|
|
19
|
-
|
20
|
-
|
21
|
-
|
25
|
+
class << self
|
26
|
+
attr_accessor :method_mapper
|
27
|
+
|
28
|
+
def node_class(name)
|
29
|
+
@__node_classes ||= {}
|
30
|
+
@__node_classes[name.to_sym] ||= ClassyStruct.new(&method_mapper)
|
31
|
+
end
|
32
|
+
|
33
|
+
def map_array(key, ary)
|
34
|
+
ary.map do |e|
|
35
|
+
case e
|
36
|
+
when Hash
|
37
|
+
node_class(key).new(e)
|
38
|
+
else
|
39
|
+
e
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
22
43
|
end
|
23
44
|
|
24
45
|
def new_child(key)
|
data/spec/classy_struct_spec.rb
CHANGED
@@ -14,6 +14,23 @@ describe ClassyStruct do
|
|
14
14
|
it "returns something that inherits from ClassyStruct" do
|
15
15
|
ClassyStruct.new.ancestors.should include(ClassyStruct::ClassyStructClass)
|
16
16
|
end
|
17
|
+
|
18
|
+
it 'assigns a method mapper if a block is given' do
|
19
|
+
prok = Proc.new{'proc_out'}
|
20
|
+
|
21
|
+
ClassyStruct.new(&prok).method_mapper.should == prok
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'maintains unique method mappers per instance' do
|
25
|
+
prok1 = Proc.new{'proc_out1'}
|
26
|
+
prok2 = Proc.new{'proc_out2'}
|
27
|
+
|
28
|
+
klass1 = ClassyStruct.new(&prok1)
|
29
|
+
klass2 = ClassyStruct.new(&prok2)
|
30
|
+
|
31
|
+
klass1.method_mapper.should == prok1
|
32
|
+
klass2.method_mapper.should == prok2
|
33
|
+
end
|
17
34
|
end
|
18
35
|
|
19
36
|
describe :method_missing do
|
@@ -55,17 +72,24 @@ describe ClassyStruct do
|
|
55
72
|
end
|
56
73
|
|
57
74
|
it 'creates child nodes whose class is the same regardless of the instance' do
|
58
|
-
|
59
|
-
|
75
|
+
klass1 = @foo_struct.node_class(:bar)
|
76
|
+
klass2 = @foo_struct.node_class(:bar)
|
60
77
|
|
61
|
-
|
78
|
+
klass1.should == klass2
|
62
79
|
end
|
63
80
|
|
64
81
|
it 'creates child nodes whose class is different for different ClassyStruct instances' do
|
65
|
-
|
66
|
-
|
82
|
+
klass1 = @foo_struct.node_class(:bar)
|
83
|
+
klass2 = @bar_struct.node_class(:bar)
|
84
|
+
|
85
|
+
klass1.should_not == klass2
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'passes the method mapper to the child node class' do
|
89
|
+
prok = Proc.new{|m| m.downcase}
|
67
90
|
|
68
|
-
|
91
|
+
the_struct = ClassyStruct.new(&prok)
|
92
|
+
the_struct.node_class(:bar).method_mapper.should == prok
|
69
93
|
end
|
70
94
|
end
|
71
95
|
|
@@ -77,6 +101,23 @@ describe ClassyStruct do
|
|
77
101
|
o.baz.should == :xyzzy
|
78
102
|
end
|
79
103
|
|
104
|
+
it 'maps hash keys with the method mapper if provided' do
|
105
|
+
the_struct = ClassyStruct.new{|m| m.tr('bf', 'fb')}
|
106
|
+
|
107
|
+
o = the_struct.new(:foo => :bar, 'baz' => :xyzzy)
|
108
|
+
|
109
|
+
o.boo.should == :bar
|
110
|
+
o.faz.should == :xyzzy
|
111
|
+
end
|
112
|
+
|
113
|
+
it 'maps hash keys on nested hashes' do
|
114
|
+
the_struct = ClassyStruct.new{|m| m.tr('bf', 'fb')}
|
115
|
+
|
116
|
+
o = the_struct.new(:foo => {:bar => :xyzzy})
|
117
|
+
|
118
|
+
o.boo.far.should == :xyzzy
|
119
|
+
end
|
120
|
+
|
80
121
|
it 'initializes sub-hashes by creating new ClassyStruct child nodes' do
|
81
122
|
o = @foo_struct.new(:foo => :bar, 'baz' => {:xyzzy => 'something', 'thud' => 'splat'})
|
82
123
|
|
@@ -93,6 +134,35 @@ describe ClassyStruct do
|
|
93
134
|
o.class.should == p.class
|
94
135
|
o.baz.class.should == p.baz.class
|
95
136
|
end
|
137
|
+
|
138
|
+
it 'converts arrays' do
|
139
|
+
o = @foo_struct.new(:foo => [{:bar => :baz}, {:bar => :xyzzy}, {:bar => :thud}])
|
140
|
+
|
141
|
+
o.foo.collect{|f| f.bar}.should == [:baz, :xyzzy, :thud]
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'uses the same class for each converted hash member of arrays' do
|
145
|
+
o = @foo_struct.new(:foo => [{:bar => :baz}, {:bar => :xyzzy}, {:bar => :thud}])
|
146
|
+
|
147
|
+
o.foo[0].class.should == o.foo[1].class
|
148
|
+
o.foo[0].class.should == o.foo[2].class
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'creates new classes that do not match the object class when mapping arrays' do
|
152
|
+
o = @foo_struct.new(:foo => [{:bar => :baz}])
|
153
|
+
|
154
|
+
o.class.should_not == o.foo.first.class
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'uses the method mapper for hash members of arrays' do
|
158
|
+
mstruct = ClassyStruct.new{|k| k.downcase}
|
159
|
+
|
160
|
+
o = mstruct.new('Bar' => [{'Baz' => :xyzzy}])
|
161
|
+
|
162
|
+
o.bar.should be_an(Array)
|
163
|
+
o.bar.length.should == 1
|
164
|
+
o.bar.first.baz.should == :xyzzy
|
165
|
+
end
|
96
166
|
end
|
97
167
|
|
98
168
|
describe :new_child do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: classy_struct
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- amikula
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-11-
|
12
|
+
date: 2009-11-18 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|