aduki 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|