aduki 0.1.3 → 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.
- checksums.yaml +4 -4
- data/lib/aduki.rb +11 -1
- data/lib/aduki/attr_finder.rb +90 -0
- data/lib/aduki/recursive_hash.rb +33 -0
- data/lib/aduki/version.rb +1 -1
- data/spec/attr_finder_spec.rb +21 -0
- data/spec/custom_builder_spec.rb +2 -2
- data/spec/finder_spec.rb +136 -0
- data/spec/initializer_spec.rb +102 -1
- data/spec/merge_attributes_spec.rb +39 -0
- data/spec/spec_helper.rb +35 -7
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b7074743cb0761525eaa92e7b9c6e3c942b2b27d
|
4
|
+
data.tar.gz: 757b6d2914b0d256e9b2404f959f85a0bd42662d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 23d19d50ef586a3dd4a2c29061a2fe8fca8837d235182a97bd9f0dedd1274019761e7b93ca14ef6d9aff0b504fcba8a49d1c6bfa17bb9eadb864b2d209df783a
|
7
|
+
data.tar.gz: 32443cdd6d8b1ef2008e1f33b4658f6097d6c17e7c2053937fb6bb47368a5fe4f518809b19913da6e266584750e4270ce47848bb34a3b4469aebdfafb8ca3a86
|
data/lib/aduki.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require "date"
|
2
2
|
require "time"
|
3
3
|
require "aduki/version"
|
4
|
+
require "aduki/recursive_hash"
|
5
|
+
require "aduki/attr_finder"
|
4
6
|
|
5
7
|
module Aduki
|
6
8
|
def self.to_aduki obj, collector={ }, key="", join=""
|
@@ -108,7 +110,7 @@ module Aduki
|
|
108
110
|
existing_value = object.send setter if object.respond_to?(setter)
|
109
111
|
if existing_value
|
110
112
|
if existing_value.is_a? Hash
|
111
|
-
|
113
|
+
value.each { |k, v| existing_value[k] = v }
|
112
114
|
else
|
113
115
|
Aduki.apply_attributes existing_value, value
|
114
116
|
end
|
@@ -169,6 +171,14 @@ module Aduki
|
|
169
171
|
def get_aduki_initializers
|
170
172
|
@@initializers[self] || []
|
171
173
|
end
|
174
|
+
|
175
|
+
def attr_finder finder, id, *args
|
176
|
+
class_eval Aduki::AttrFinder.attr_finders_text(finder, id, *args)
|
177
|
+
end
|
178
|
+
|
179
|
+
def attr_many_finder finder, id, name, options={ }
|
180
|
+
class_eval Aduki::AttrFinder.one2many_attr_finder_text(finder, id, name, options={ })
|
181
|
+
end
|
172
182
|
end
|
173
183
|
|
174
184
|
module Initializer
|
@@ -0,0 +1,90 @@
|
|
1
|
+
class Aduki::AttrFinder
|
2
|
+
if defined? ActiveSupport
|
3
|
+
def self.camelize str ; str.to_s.camelize ; end
|
4
|
+
def self.singularize str ; str.to_s.singularize ; end
|
5
|
+
def self.pluralize str ; str.to_s.pluralize ; end
|
6
|
+
else
|
7
|
+
def self.camelize str
|
8
|
+
str.split(/\//).map { |s| s.gsub(/(^|_)([a-z])/) { |m| $2.upcase } }.join("::")
|
9
|
+
end
|
10
|
+
def self.singularize str
|
11
|
+
str.to_s.gsub(/ies$/, "y").gsub(/s$/, '')
|
12
|
+
end
|
13
|
+
def self.pluralize str
|
14
|
+
str.to_s.gsub(/y$/, "ies").gsub(/([^s])$/, '\1s')
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.hashify_args a
|
19
|
+
return a.first if a.first.is_a? Hash
|
20
|
+
a.inject({ }) { |hash, arg|
|
21
|
+
if arg.is_a?(Hash)
|
22
|
+
hash.merge arg
|
23
|
+
else
|
24
|
+
hash[arg] = camelize arg.to_s
|
25
|
+
hash
|
26
|
+
end
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.attr_finders_text finder, id, *args
|
31
|
+
hashify_args(args).map { |name, klass|
|
32
|
+
attr_finder_text finder, id, name, klass
|
33
|
+
}.join("\n")
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.attr_finder_text finder, id, name, klass
|
37
|
+
id_method = "#{name}_#{id}"
|
38
|
+
<<EVAL
|
39
|
+
remove_method :#{id_method} if method_defined?(:#{id_method})
|
40
|
+
remove_method :#{id_method}= if method_defined?(:#{id_method}=)
|
41
|
+
remove_method :#{name} if method_defined?(:#{name})
|
42
|
+
remove_method :#{name}= if method_defined?(:#{name}=)
|
43
|
+
|
44
|
+
attr_reader :#{id_method}
|
45
|
+
|
46
|
+
def #{id_method}= x
|
47
|
+
@#{id_method}= x
|
48
|
+
@#{name} = nil
|
49
|
+
end
|
50
|
+
|
51
|
+
def #{name}
|
52
|
+
@#{name} ||= #{klass}.#{finder}(@#{id_method}) unless @#{id_method}.nil? || @#{id_method} == ''
|
53
|
+
end
|
54
|
+
|
55
|
+
def #{name}= x
|
56
|
+
@#{name} = x
|
57
|
+
@#{id_method} = x ? x.#{id} : nil
|
58
|
+
end
|
59
|
+
EVAL
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.one2many_attr_finder_text finder, id, name, options={ }
|
63
|
+
singular = singularize name.to_s
|
64
|
+
klass = options[:class_name] || camelize(singular)
|
65
|
+
id_method = "#{singular}_#{pluralize id}"
|
66
|
+
<<EVAL
|
67
|
+
remove_method :#{id_method} if method_defined?(:#{id_method})
|
68
|
+
remove_method :#{id_method}= if method_defined?(:#{id_method}=)
|
69
|
+
remove_method :#{name} if method_defined?(:#{name})
|
70
|
+
remove_method :#{name}= if method_defined?(:#{name}=)
|
71
|
+
|
72
|
+
attr_reader :#{id_method}
|
73
|
+
|
74
|
+
def #{id_method}= x
|
75
|
+
@#{id_method} = x
|
76
|
+
@#{name} = nil
|
77
|
+
end
|
78
|
+
|
79
|
+
def #{name}
|
80
|
+
@#{name} ||= #{klass}.#{finder} @#{id_method} unless @#{id_method}.nil?
|
81
|
+
end
|
82
|
+
|
83
|
+
def #{name}= x
|
84
|
+
@#{id_method} = x ? x.map(&:#{id}) : nil
|
85
|
+
@#{name} = x
|
86
|
+
end
|
87
|
+
EVAL
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'aduki'
|
2
|
+
|
3
|
+
class Aduki::RecursiveHash < Hash
|
4
|
+
def []= key, value
|
5
|
+
return super(key, value) unless key.is_a? String
|
6
|
+
|
7
|
+
k0, k1 = key.split(/\./, 2)
|
8
|
+
|
9
|
+
if k0.match(/\[\d+\]$/)
|
10
|
+
getter = k0.gsub(/\[\d+\]$/, '')
|
11
|
+
index = k0.gsub(/.*\[(\d+)\]$/, '\1').to_i
|
12
|
+
subarray = self[getter] || []
|
13
|
+
if k1
|
14
|
+
subarray[index] ||= Aduki::RecursiveHash.new
|
15
|
+
subarray[index][k1] = value
|
16
|
+
else
|
17
|
+
subarray[index] = value
|
18
|
+
end
|
19
|
+
super getter, subarray
|
20
|
+
else
|
21
|
+
return super(key, value) if k1.nil?
|
22
|
+
existing = self[k0]
|
23
|
+
subhash = (existing.is_a? Hash) ? existing : Aduki::RecursiveHash.new
|
24
|
+
subhash[k1] = value
|
25
|
+
super k0, subhash
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def copy other
|
30
|
+
other.each { |k, v| self[k]= v }
|
31
|
+
self
|
32
|
+
end
|
33
|
+
end
|
data/lib/aduki/version.rb
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
require "aduki"
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
describe Aduki::AttrFinder do
|
5
|
+
it "should assign a value using attr_finder" do
|
6
|
+
props = {
|
7
|
+
"name" => "Eamonn de Valera",
|
8
|
+
"city_name" => "dublin",
|
9
|
+
"gift_names[0]" => "dinner",
|
10
|
+
"gift_names[1]" => "whiskey",
|
11
|
+
"gift_names[2]" => "cigars",
|
12
|
+
}
|
13
|
+
|
14
|
+
politician = Politician.new props
|
15
|
+
|
16
|
+
expect(politician.name).to eq "Eamonn de Valera"
|
17
|
+
expect(politician.city).to eq City::CITIES["dublin"]
|
18
|
+
expect(politician.city.name).to eq "dublin"
|
19
|
+
expect(politician.gifts).to eq [Gift.lookup("dinner"), Gift.lookup("whiskey"), Gift.lookup("cigars")]
|
20
|
+
end
|
21
|
+
end
|
data/spec/custom_builder_spec.rb
CHANGED
@@ -12,7 +12,7 @@ describe Aduki::Initializer do
|
|
12
12
|
contraption = MachineBuilder.new props
|
13
13
|
|
14
14
|
expect(contraption.name).to eq "Anna Livia"
|
15
|
-
expect(contraption.city).to eq CITIES["dublin"]
|
16
|
-
expect(contraption.city.name).to eq "
|
15
|
+
expect(contraption.city).to eq City::CITIES["dublin"]
|
16
|
+
expect(contraption.city.name).to eq "dublin"
|
17
17
|
end
|
18
18
|
end
|
data/spec/finder_spec.rb
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
require "aduki"
|
2
|
+
require "aduki/attr_finder"
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
describe Aduki::AttrFinder do
|
6
|
+
it "generates code for a single attribute" do
|
7
|
+
txt = Aduki::AttrFinder.attr_finder_text :find, :id, "widget_holder", "WidgetHolder"
|
8
|
+
expected = <<EXPECTED
|
9
|
+
remove_method :widget_holder_id if method_defined?(:widget_holder_id)
|
10
|
+
remove_method :widget_holder_id= if method_defined?(:widget_holder_id=)
|
11
|
+
remove_method :widget_holder if method_defined?(:widget_holder)
|
12
|
+
remove_method :widget_holder= if method_defined?(:widget_holder=)
|
13
|
+
|
14
|
+
attr_reader :widget_holder_id
|
15
|
+
|
16
|
+
def widget_holder_id= x
|
17
|
+
@widget_holder_id= x
|
18
|
+
@widget_holder = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def widget_holder
|
22
|
+
@widget_holder ||= WidgetHolder.find(@widget_holder_id) unless @widget_holder_id.nil? || @widget_holder_id == ''
|
23
|
+
end
|
24
|
+
|
25
|
+
def widget_holder= x
|
26
|
+
@widget_holder = x
|
27
|
+
@widget_holder_id = x ? x.id : nil
|
28
|
+
end
|
29
|
+
EXPECTED
|
30
|
+
|
31
|
+
expect(txt).to eq expected
|
32
|
+
end
|
33
|
+
|
34
|
+
it "generates code for multiple attributes" do
|
35
|
+
txt = Aduki::AttrFinder.attr_finders_text :open, :time, :happy_hour, widget: "WidgetHolder::Base"
|
36
|
+
expected = <<EXPECTED
|
37
|
+
remove_method :happy_hour_time if method_defined?(:happy_hour_time)
|
38
|
+
remove_method :happy_hour_time= if method_defined?(:happy_hour_time=)
|
39
|
+
remove_method :happy_hour if method_defined?(:happy_hour)
|
40
|
+
remove_method :happy_hour= if method_defined?(:happy_hour=)
|
41
|
+
|
42
|
+
attr_reader :happy_hour_time
|
43
|
+
|
44
|
+
def happy_hour_time= x
|
45
|
+
@happy_hour_time= x
|
46
|
+
@happy_hour = nil
|
47
|
+
end
|
48
|
+
|
49
|
+
def happy_hour
|
50
|
+
@happy_hour ||= HappyHour.open(@happy_hour_time) unless @happy_hour_time.nil? || @happy_hour_time == ''
|
51
|
+
end
|
52
|
+
|
53
|
+
def happy_hour= x
|
54
|
+
@happy_hour = x
|
55
|
+
@happy_hour_time = x ? x.time : nil
|
56
|
+
end
|
57
|
+
|
58
|
+
remove_method :widget_time if method_defined?(:widget_time)
|
59
|
+
remove_method :widget_time= if method_defined?(:widget_time=)
|
60
|
+
remove_method :widget if method_defined?(:widget)
|
61
|
+
remove_method :widget= if method_defined?(:widget=)
|
62
|
+
|
63
|
+
attr_reader :widget_time
|
64
|
+
|
65
|
+
def widget_time= x
|
66
|
+
@widget_time= x
|
67
|
+
@widget = nil
|
68
|
+
end
|
69
|
+
|
70
|
+
def widget
|
71
|
+
@widget ||= WidgetHolder::Base.open(@widget_time) unless @widget_time.nil? || @widget_time == ''
|
72
|
+
end
|
73
|
+
|
74
|
+
def widget= x
|
75
|
+
@widget = x
|
76
|
+
@widget_time = x ? x.time : nil
|
77
|
+
end
|
78
|
+
EXPECTED
|
79
|
+
|
80
|
+
expect(txt).to eq expected
|
81
|
+
end
|
82
|
+
|
83
|
+
it "generates a one-to-many finder" do
|
84
|
+
txt = Aduki::AttrFinder.one2many_attr_finder_text :purchase, :price, :birthday_gifts
|
85
|
+
expected = <<EXPECTED
|
86
|
+
remove_method :birthday_gift_prices if method_defined?(:birthday_gift_prices)
|
87
|
+
remove_method :birthday_gift_prices= if method_defined?(:birthday_gift_prices=)
|
88
|
+
remove_method :birthday_gifts if method_defined?(:birthday_gifts)
|
89
|
+
remove_method :birthday_gifts= if method_defined?(:birthday_gifts=)
|
90
|
+
|
91
|
+
attr_reader :birthday_gift_prices
|
92
|
+
|
93
|
+
def birthday_gift_prices= x
|
94
|
+
@birthday_gift_prices = x
|
95
|
+
@birthday_gifts = nil
|
96
|
+
end
|
97
|
+
|
98
|
+
def birthday_gifts
|
99
|
+
@birthday_gifts ||= BirthdayGift.purchase @birthday_gift_prices unless @birthday_gift_prices.nil?
|
100
|
+
end
|
101
|
+
|
102
|
+
def birthday_gifts= x
|
103
|
+
@birthday_gift_prices = x ? x.map(&:price) : nil
|
104
|
+
@birthday_gifts = x
|
105
|
+
end
|
106
|
+
EXPECTED
|
107
|
+
expect(txt).to eq expected
|
108
|
+
end
|
109
|
+
|
110
|
+
it "generates a one-to-many finder with alternative class name" do
|
111
|
+
txt = Aduki::AttrFinder.one2many_attr_finder_text :purchase, :price, :birthday_gifts, class_name: "ToyShop"
|
112
|
+
expected = <<EXPECTED
|
113
|
+
remove_method :birthday_gift_prices if method_defined?(:birthday_gift_prices)
|
114
|
+
remove_method :birthday_gift_prices= if method_defined?(:birthday_gift_prices=)
|
115
|
+
remove_method :birthday_gifts if method_defined?(:birthday_gifts)
|
116
|
+
remove_method :birthday_gifts= if method_defined?(:birthday_gifts=)
|
117
|
+
|
118
|
+
attr_reader :birthday_gift_prices
|
119
|
+
|
120
|
+
def birthday_gift_prices= x
|
121
|
+
@birthday_gift_prices = x
|
122
|
+
@birthday_gifts = nil
|
123
|
+
end
|
124
|
+
|
125
|
+
def birthday_gifts
|
126
|
+
@birthday_gifts ||= ToyShop.purchase @birthday_gift_prices unless @birthday_gift_prices.nil?
|
127
|
+
end
|
128
|
+
|
129
|
+
def birthday_gifts= x
|
130
|
+
@birthday_gift_prices = x ? x.map(&:price) : nil
|
131
|
+
@birthday_gifts = x
|
132
|
+
end
|
133
|
+
EXPECTED
|
134
|
+
expect(txt).to eq expected
|
135
|
+
end
|
136
|
+
end
|
data/spec/initializer_spec.rb
CHANGED
@@ -252,7 +252,7 @@ describe Aduki::Initializer do
|
|
252
252
|
expect(model.gadget.speaker.threads).to eq [ 12.4, 8.16, 21.42 ]
|
253
253
|
end
|
254
254
|
|
255
|
-
it "should handle pre-initialized hashes
|
255
|
+
it "should handle pre-initialized hashes" do
|
256
256
|
props = {
|
257
257
|
"name" => "Brackish Water",
|
258
258
|
"gadget.name" => "The Loud Gadget",
|
@@ -265,4 +265,105 @@ describe Aduki::Initializer do
|
|
265
265
|
|
266
266
|
expect(model.gadget.variables).to eq({ "x"=> "29", "y" => "12.4", "z" => "8.16"})
|
267
267
|
end
|
268
|
+
|
269
|
+
it "should handle pre-initialized hashes with more complex subkeys" do
|
270
|
+
props = {
|
271
|
+
"name" => "Brackish Water",
|
272
|
+
"gadget.name" => "The Loud Gadget",
|
273
|
+
"gadget.variables.x[4]" => "24",
|
274
|
+
"gadget.variables.x[7]" => "27",
|
275
|
+
"gadget.variables.x[3].length" => "3",
|
276
|
+
"gadget.variables.x[3].width" => "13",
|
277
|
+
"gadget.variables.x[3].depth[0]" => "23",
|
278
|
+
"gadget.variables.x[3].depth[1].high" => "23+10",
|
279
|
+
"gadget.variables.x[3].depth[1].low" => "23-10",
|
280
|
+
"gadget.variables.x[3].depth[2]" => "33",
|
281
|
+
"gadget.variables.y.fortune" => "flavours",
|
282
|
+
"gadget.variables.y.help" => "F1",
|
283
|
+
"gadget.variables.y.pandora" => "boxy",
|
284
|
+
"gadget.variables.z" => "8.16",
|
285
|
+
}
|
286
|
+
|
287
|
+
model = Model.new props
|
288
|
+
|
289
|
+
expected = {
|
290
|
+
"x"=> [
|
291
|
+
nil,
|
292
|
+
nil,
|
293
|
+
nil,
|
294
|
+
{
|
295
|
+
"length" => "3",
|
296
|
+
"width" => "13",
|
297
|
+
"depth" => [
|
298
|
+
"23",
|
299
|
+
{ "high" => "23+10", "low" => "23-10"},
|
300
|
+
"33"
|
301
|
+
],
|
302
|
+
},
|
303
|
+
"24",
|
304
|
+
nil,
|
305
|
+
nil,
|
306
|
+
"27"
|
307
|
+
],
|
308
|
+
"y" => {
|
309
|
+
"fortune" => "flavours",
|
310
|
+
"help" => "F1",
|
311
|
+
"pandora" => "boxy"},
|
312
|
+
"z" => "8.16"
|
313
|
+
}
|
314
|
+
expect(model.gadget.variables).to eq expected
|
315
|
+
end
|
316
|
+
|
317
|
+
it "creates a new hash by recursively splitting string keys on separator-character" do
|
318
|
+
props = {
|
319
|
+
"name" => "Brackish Water",
|
320
|
+
"gadget.name" => "The Loud Gadget",
|
321
|
+
"gadget.variables.x[4]" => "24",
|
322
|
+
"gadget.variables.x[7]" => "27",
|
323
|
+
"gadget.variables.x[3].length" => "3",
|
324
|
+
"gadget.variables.x[3].width" => "13",
|
325
|
+
"gadget.variables.x[3].depth[0]" => "23",
|
326
|
+
"gadget.variables.x[3].depth[1].high" => "23+10",
|
327
|
+
"gadget.variables.x[3].depth[1].low" => "23-10",
|
328
|
+
"gadget.variables.x[3].depth[2]" => "33",
|
329
|
+
"gadget.variables.y.fortune" => "flavours",
|
330
|
+
"gadget.variables.y.help" => "F1",
|
331
|
+
"gadget.variables.y.pandora" => "boxy",
|
332
|
+
"gadget.variables.z" => "8.16",
|
333
|
+
}
|
334
|
+
|
335
|
+
hash = Aduki::RecursiveHash.new.copy props
|
336
|
+
expected = {
|
337
|
+
"name" => "Brackish Water",
|
338
|
+
"gadget" => {
|
339
|
+
"name" => "The Loud Gadget",
|
340
|
+
"variables" => {
|
341
|
+
"x"=> [
|
342
|
+
nil,
|
343
|
+
nil,
|
344
|
+
nil,
|
345
|
+
{
|
346
|
+
"length" => "3",
|
347
|
+
"width" => "13",
|
348
|
+
"depth" => [
|
349
|
+
"23",
|
350
|
+
{ "high" => "23+10", "low" => "23-10"},
|
351
|
+
"33"
|
352
|
+
],
|
353
|
+
},
|
354
|
+
"24",
|
355
|
+
nil,
|
356
|
+
nil,
|
357
|
+
"27"
|
358
|
+
],
|
359
|
+
"y" => {
|
360
|
+
"fortune" => "flavours",
|
361
|
+
"help" => "F1",
|
362
|
+
"pandora" => "boxy"},
|
363
|
+
"z" => "8.16"
|
364
|
+
}
|
365
|
+
}
|
366
|
+
}
|
367
|
+
expect(hash).to eq expected
|
368
|
+
end
|
268
369
|
end
|
@@ -83,4 +83,43 @@ describe Aduki::Initializer do
|
|
83
83
|
expect(model.gadget.speaker.ohms). to eq "29"
|
84
84
|
expect(model.gadget.speaker.diameter).to eq "large"
|
85
85
|
end
|
86
|
+
|
87
|
+
|
88
|
+
it "merges a hash attribute" do
|
89
|
+
props = {
|
90
|
+
"name" => "Brackish Water",
|
91
|
+
"gadget.name" => "The Loud Gadget",
|
92
|
+
"gadget.variables.x" => "29",
|
93
|
+
"gadget.variables.y" => "12.4",
|
94
|
+
"gadget.variables.z" => "8.16",
|
95
|
+
}
|
96
|
+
|
97
|
+
model = Model.new props
|
98
|
+
|
99
|
+
more_props = {
|
100
|
+
"gadget.variables.x.left" => "strong",
|
101
|
+
"gadget.variables.x.right" => "central",
|
102
|
+
"gadget.variables.y.left" => "weak",
|
103
|
+
"gadget.variables.y.right" => "mirror",
|
104
|
+
"gadget.variables.other" => "central",
|
105
|
+
}
|
106
|
+
|
107
|
+
Aduki.apply_attributes model, more_props
|
108
|
+
|
109
|
+
expected = {
|
110
|
+
"x"=> {
|
111
|
+
"left" => "strong",
|
112
|
+
"right" => "central",
|
113
|
+
},
|
114
|
+
"y" => {
|
115
|
+
"left" => "weak",
|
116
|
+
"right" => "mirror",
|
117
|
+
},
|
118
|
+
"z" => "8.16",
|
119
|
+
"other" => "central"
|
120
|
+
}
|
121
|
+
|
122
|
+
expect(model.gadget.variables).to eq expected
|
123
|
+
end
|
124
|
+
|
86
125
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -6,18 +6,46 @@ RSpec.configure do |config|
|
|
6
6
|
end
|
7
7
|
|
8
8
|
|
9
|
-
CITIES = { }
|
10
|
-
|
11
9
|
class City < Struct.new(:name)
|
10
|
+
CITIES = { }
|
12
11
|
def self.aduki_find value
|
13
12
|
CITIES[value]
|
14
13
|
end
|
14
|
+
|
15
|
+
def register
|
16
|
+
CITIES[name] = self
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
City.new("paris" ).register
|
21
|
+
City.new("madrid" ).register
|
22
|
+
City.new("stockholm").register
|
23
|
+
City.new("dublin" ).register
|
24
|
+
|
25
|
+
class Gift
|
26
|
+
GIFTS = { }
|
27
|
+
include Aduki::Initializer
|
28
|
+
attr_accessor :name, :price
|
29
|
+
def self.lookup name
|
30
|
+
name.is_a?(String) ? GIFTS[name] : name.map { |n| GIFTS[n] }
|
31
|
+
end
|
32
|
+
def register
|
33
|
+
GIFTS[name] = self
|
34
|
+
end
|
15
35
|
end
|
16
36
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
37
|
+
Gift.new(name: "dinner" , price: :cheap ).register
|
38
|
+
Gift.new(name: "massage" , price: :cheap ).register
|
39
|
+
Gift.new(name: "med_cruise", price: :expensive).register
|
40
|
+
Gift.new(name: "whiskey" , price: :medium ).register
|
41
|
+
Gift.new(name: "cigars" , price: :medium ).register
|
42
|
+
|
43
|
+
class Politician
|
44
|
+
include Aduki::Initializer
|
45
|
+
attr_accessor :name
|
46
|
+
attr_finder :aduki_find, :name, :city
|
47
|
+
attr_many_finder :lookup, :name, :gifts
|
48
|
+
end
|
21
49
|
|
22
50
|
class Contraption
|
23
51
|
include Aduki::Initializer
|
@@ -52,7 +80,7 @@ class Gadget
|
|
52
80
|
attr_accessor :name, :price, :supplier, :variables
|
53
81
|
attr_writer :wattage
|
54
82
|
aduki_initialize :speaker, Speaker
|
55
|
-
aduki_initialize :variables,
|
83
|
+
aduki_initialize :variables, Aduki::RecursiveHash, nil
|
56
84
|
|
57
85
|
def watts
|
58
86
|
@wattage
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aduki
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Conan Dalton
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-04-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -53,9 +53,13 @@ files:
|
|
53
53
|
- Rakefile
|
54
54
|
- aduki.gemspec
|
55
55
|
- lib/aduki.rb
|
56
|
+
- lib/aduki/attr_finder.rb
|
57
|
+
- lib/aduki/recursive_hash.rb
|
56
58
|
- lib/aduki/version.rb
|
57
59
|
- spec/array_attribute_spec.rb
|
60
|
+
- spec/attr_finder_spec.rb
|
58
61
|
- spec/custom_builder_spec.rb
|
62
|
+
- spec/finder_spec.rb
|
59
63
|
- spec/initializer_spec.rb
|
60
64
|
- spec/merge_attributes_spec.rb
|
61
65
|
- spec/model.rb
|
@@ -90,7 +94,9 @@ specification_version: 4
|
|
90
94
|
summary: set object attributes recursively from an attributes hash
|
91
95
|
test_files:
|
92
96
|
- spec/array_attribute_spec.rb
|
97
|
+
- spec/attr_finder_spec.rb
|
93
98
|
- spec/custom_builder_spec.rb
|
99
|
+
- spec/finder_spec.rb
|
94
100
|
- spec/initializer_spec.rb
|
95
101
|
- spec/merge_attributes_spec.rb
|
96
102
|
- spec/model.rb
|