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 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