classy_struct 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -1,4 +1,4 @@
1
- = airystruct
1
+ = classy_struct
2
2
 
3
3
  Description goes here.
4
4
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.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
- def self.node_class(name)
20
- @__node_classes ||= {}
21
- @__node_classes[name.to_sym] ||= ClassyStruct.new
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)
@@ -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
- klazz1 = @foo_struct.node_class(:bar)
59
- klazz2 = @foo_struct.node_class(:bar)
75
+ klass1 = @foo_struct.node_class(:bar)
76
+ klass2 = @foo_struct.node_class(:bar)
60
77
 
61
- klazz1.should == klazz2
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
- klazz1 = @foo_struct.node_class(:bar)
66
- klazz2 = @bar_struct.node_class(:bar)
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
- klazz1.should_not == klazz2
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.1.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-11 00:00:00 -08:00
12
+ date: 2009-11-18 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency