representable 1.5.3 → 1.6.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 +7 -0
- data/{CHANGES.textile → CHANGES.md} +17 -0
- data/Gemfile +1 -1
- data/README.md +24 -3
- data/TODO +11 -3
- data/lib/representable.rb +37 -117
- data/lib/representable/coercion.rb +29 -4
- data/lib/representable/config.rb +52 -0
- data/lib/representable/decorator.rb +8 -7
- data/lib/representable/decorator/coercion.rb +2 -57
- data/lib/representable/definition.rb +1 -0
- data/lib/representable/feature/readable_writeable.rb +1 -1
- data/lib/representable/hash.rb +5 -0
- data/lib/representable/hash/collection.rb +38 -0
- data/lib/representable/hash_methods.rb +2 -2
- data/lib/representable/json.rb +5 -0
- data/lib/representable/json/collection.rb +3 -28
- data/lib/representable/mapper.rb +78 -0
- data/lib/representable/version.rb +1 -1
- data/lib/representable/xml.rb +15 -10
- data/lib/representable/xml/collection.rb +7 -25
- data/lib/representable/yaml.rb +16 -11
- data/test/coercion_test.rb +95 -66
- data/test/decorator_test.rb +10 -0
- data/test/inheritance_test.rb +21 -0
- data/test/json_test.rb +7 -7
- data/test/representable_test.rb +146 -26
- data/test/test_helper.rb +1 -0
- data/test/yaml_test.rb +1 -2
- metadata +26 -44
data/test/coercion_test.rb
CHANGED
@@ -3,82 +3,111 @@ require 'representable/coercion'
|
|
3
3
|
require 'representable/decorator/coercion'
|
4
4
|
|
5
5
|
class VirtusCoercionTest < MiniTest::Spec
|
6
|
-
class Song # note that we
|
7
|
-
attr_accessor :title
|
6
|
+
class Song # note that we have to define accessors for the properties here.
|
7
|
+
attr_accessor :title, :composed_at, :track
|
8
8
|
end
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
# it "coerces when rendering" do
|
29
|
-
# song = Song.new
|
30
|
-
# song.title = "Scarified"
|
31
|
-
# song.to_json.must_equal ''
|
32
|
-
# end
|
10
|
+
let (:date) { DateTime.parse("Fri, 18 Nov 1983 00:00:00 +0000") }
|
11
|
+
|
12
|
+
describe "on object level" do
|
13
|
+
module SongRepresenter
|
14
|
+
include Representable::JSON
|
15
|
+
include Representable::Coercion
|
16
|
+
property :composed_at, :type => DateTime
|
17
|
+
property :track, :type => Integer
|
18
|
+
property :title # no coercion.
|
19
|
+
end
|
20
|
+
|
21
|
+
it "coerces properties in #from_json" do
|
22
|
+
song = Song.new.extend(SongRepresenter).from_json('{"composed_at":"November 18th, 1983","track":"18","title":"Scarified"}')
|
23
|
+
song.composed_at.must_equal date
|
24
|
+
song.track.must_equal 18
|
25
|
+
song.title.must_equal "Scarified"
|
33
26
|
end
|
34
27
|
|
28
|
+
it "coerces when rendering" do
|
29
|
+
song = Song.new.extend(SongRepresenter)
|
30
|
+
song.title = "Scarified"
|
31
|
+
song.composed_at = "Fri, 18 Nov 1983"
|
35
32
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
33
|
+
song.to_hash.must_equal({"title" => "Scarified", "composed_at" => date})
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "on class level" do
|
38
|
+
class ImmigrantSong
|
39
|
+
include Representable::JSON
|
40
|
+
include Representable::Coercion
|
40
41
|
|
41
|
-
|
42
|
-
|
43
|
-
end
|
42
|
+
property :composed_at, :type => DateTime, :default => "May 12th, 2012"
|
43
|
+
property :track, :type => Integer
|
44
44
|
|
45
|
-
|
46
|
-
|
47
|
-
assert_equal DateTime.parse("Fri, 18 Nov 1983 00:00:00 +0000"), song.composed_at
|
48
|
-
assert_equal 18, song.track
|
49
|
-
end
|
45
|
+
attr_accessor :composed_at, :track
|
46
|
+
end
|
50
47
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
end
|
48
|
+
it "coerces into the provided type" do
|
49
|
+
song = ImmigrantSong.new.from_json("{\"composed_at\":\"November 18th, 1983\",\"track\":\"18\"}")
|
50
|
+
song.composed_at.must_equal date
|
51
|
+
song.track.must_equal 18
|
56
52
|
end
|
57
53
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
include Representable::Decorator::Coercion
|
62
|
-
|
63
|
-
property :composed_at, :type => DateTime
|
64
|
-
property :title
|
65
|
-
end
|
66
|
-
|
67
|
-
it "coerces when parsing" do
|
68
|
-
song = SongRepresentation.new(OpenStruct.new).from_json("{\"composed_at\":\"November 18th, 1983\", \"title\": \"Scarified\"}")
|
69
|
-
song.must_be_kind_of OpenStruct
|
70
|
-
song.composed_at.must_equal DateTime.parse("Fri, 18 Nov 1983")
|
71
|
-
song.title.must_equal "Scarified"
|
72
|
-
end
|
73
|
-
|
74
|
-
it "coerces when rendering" do
|
75
|
-
SongRepresentation.new(
|
76
|
-
OpenStruct.new(
|
77
|
-
:composed_at => "November 18th, 1983",
|
78
|
-
:title => "Scarified"
|
79
|
-
)
|
80
|
-
).to_hash.must_equal({"composed_at"=>DateTime.parse("Fri, 18 Nov 1983"), "title"=>"Scarified"})
|
81
|
-
end
|
54
|
+
it "respects the :default options" do
|
55
|
+
song = ImmigrantSong.new.from_json("{}")
|
56
|
+
song.composed_at.must_equal DateTime.parse("Mon, 12 May 2012 00:00:00 +0000")
|
82
57
|
end
|
83
58
|
end
|
59
|
+
|
60
|
+
describe "on decorator" do
|
61
|
+
class SongRepresentation < Representable::Decorator
|
62
|
+
include Representable::JSON
|
63
|
+
include Representable::Coercion
|
64
|
+
|
65
|
+
property :composed_at, :type => DateTime
|
66
|
+
property :title
|
67
|
+
end
|
68
|
+
|
69
|
+
it "coerces when parsing" do
|
70
|
+
song = SongRepresentation.new(OpenStruct.new).from_json("{\"composed_at\":\"November 18th, 1983\", \"title\": \"Scarified\"}")
|
71
|
+
song.must_be_kind_of OpenStruct
|
72
|
+
song.composed_at.must_equal date
|
73
|
+
song.title.must_equal "Scarified"
|
74
|
+
end
|
75
|
+
|
76
|
+
it "coerses with inherited decorator" do
|
77
|
+
song = Class.new(SongRepresentation).new(OpenStruct.new).from_json("{\"composed_at\":\"November 18th, 1983\", \"title\": \"Scarified\"}")
|
78
|
+
song.composed_at.must_equal date
|
79
|
+
end
|
80
|
+
|
81
|
+
it "coerces when rendering" do
|
82
|
+
SongRepresentation.new(
|
83
|
+
OpenStruct.new(
|
84
|
+
:composed_at => "November 18th, 1983",
|
85
|
+
:title => "Scarified"
|
86
|
+
)
|
87
|
+
).to_hash.must_equal({"composed_at"=>date, "title"=>"Scarified"})
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# DISCUSS: do we actually wanna have accessors in a decorator/module? i guess the better idea is to let coercion happen through from_/to_,
|
92
|
+
# only, to make it as simple as possible.
|
93
|
+
# describe "without serialization/deserialization" do
|
94
|
+
# let (:coercer_class) do
|
95
|
+
# class SongCoercer < Representable::Decorator
|
96
|
+
# include Representable::Decorator::Coercion
|
97
|
+
|
98
|
+
# property :composed_at, :type => DateTime
|
99
|
+
# property :title
|
100
|
+
|
101
|
+
# self
|
102
|
+
# end
|
103
|
+
# end
|
104
|
+
|
105
|
+
# it "coerces when setting" do
|
106
|
+
# coercer = coercer_class.new(song = OpenStruct.new)
|
107
|
+
# coercer.composed_at = "November 18th, 1983"
|
108
|
+
# #coercer.title = "Scarified"
|
109
|
+
|
110
|
+
# song.composed_at.must_equal date
|
111
|
+
# end
|
112
|
+
# end
|
84
113
|
end
|
data/test/decorator_test.rb
CHANGED
@@ -17,6 +17,16 @@ class DecoratorTest < MiniTest::Spec
|
|
17
17
|
let (:album) { Album.new([song]) }
|
18
18
|
let (:decorator) { AlbumRepresentation.new(album) }
|
19
19
|
|
20
|
+
describe "inheritance" do
|
21
|
+
let (:inherited_decorator) do
|
22
|
+
Class.new(AlbumRepresentation) do
|
23
|
+
property :best_song
|
24
|
+
end.new(Album.new([song], "Stand Up"))
|
25
|
+
end
|
26
|
+
|
27
|
+
it { inherited_decorator.to_hash.must_equal({"songs"=>[{"name"=>"Mama, I'm Coming Home"}], "best_song"=>"Stand Up"}) }
|
28
|
+
end
|
29
|
+
|
20
30
|
it "renders" do
|
21
31
|
decorator.to_hash.must_equal({"songs"=>[{"name"=>"Mama, I'm Coming Home"}]})
|
22
32
|
album.wont_respond_to :to_hash
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class InheritanceTest < MiniTest::Spec
|
4
|
+
let (:decorator) do
|
5
|
+
Class.new(Representable::Decorator) do
|
6
|
+
property :title
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
# Decorator.new.representable_attrs != Decorator.representable_attrs
|
11
|
+
it "doesn't clone for instantiated decorator" do
|
12
|
+
instance = decorator.new(Object.new)
|
13
|
+
instance.send(:representable_attrs).first.options[:instance] = true
|
14
|
+
|
15
|
+
# we didn't clone and thereby change the original config:
|
16
|
+
instance.send(:representable_attrs).to_s.must_equal decorator.representable_attrs.to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
# TODO: ? (performance?)
|
20
|
+
# more tests on cloning
|
21
|
+
end
|
data/test/json_test.rb
CHANGED
@@ -144,13 +144,13 @@ module JsonTest
|
|
144
144
|
end
|
145
145
|
end
|
146
146
|
|
147
|
-
describe "#representable_bindings_for" do
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
end
|
147
|
+
# describe "#representable_bindings_for" do
|
148
|
+
# it "returns bindings for each property" do
|
149
|
+
# bins = @band.send(:representable_bindings_for, Representable::JSON::PropertyBinding, {})
|
150
|
+
# assert_equal 2, bins.size
|
151
|
+
# assert_equal "name", bins.first.name
|
152
|
+
# end
|
153
|
+
# end
|
154
154
|
end
|
155
155
|
|
156
156
|
|
data/test/representable_test.rb
CHANGED
@@ -2,7 +2,7 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class RepresentableTest < MiniTest::Spec
|
4
4
|
class Band
|
5
|
-
include Representable
|
5
|
+
include Representable::Hash
|
6
6
|
property :name
|
7
7
|
attr_accessor :name
|
8
8
|
end
|
@@ -92,7 +92,6 @@ class RepresentableTest < MiniTest::Spec
|
|
92
92
|
|
93
93
|
assert parent.representable_attrs.first != child.representable_attrs.first, "definitions shouldn't be identical"
|
94
94
|
end
|
95
|
-
|
96
95
|
end
|
97
96
|
end
|
98
97
|
|
@@ -172,6 +171,12 @@ class RepresentableTest < MiniTest::Spec
|
|
172
171
|
assert_equal "friends", band.representable_attrs.last.from
|
173
172
|
end
|
174
173
|
end
|
174
|
+
|
175
|
+
representer! {}
|
176
|
+
|
177
|
+
it "returns the Definition instance" do
|
178
|
+
representer.property(:name).must_be_kind_of Representable::Definition
|
179
|
+
end
|
175
180
|
end
|
176
181
|
|
177
182
|
describe "#collection" do
|
@@ -242,36 +247,36 @@ class RepresentableTest < MiniTest::Spec
|
|
242
247
|
end
|
243
248
|
|
244
249
|
it "copies values from document to object" do
|
245
|
-
@band.
|
250
|
+
@band.from_hash({"name"=>"No One's Choice", "groupies"=>2})
|
246
251
|
assert_equal "No One's Choice", @band.name
|
247
252
|
assert_equal 2, @band.groupies
|
248
253
|
end
|
249
254
|
|
250
255
|
it "accepts :exclude option" do
|
251
|
-
@band.
|
256
|
+
@band.from_hash({"name"=>"No One's Choice", "groupies"=>2}, {:exclude => [:groupies]})
|
252
257
|
assert_equal "No One's Choice", @band.name
|
253
258
|
assert_equal nil, @band.groupies
|
254
259
|
end
|
255
260
|
|
256
261
|
it "accepts :include option" do
|
257
|
-
@band.
|
262
|
+
@band.from_hash({"name"=>"No One's Choice", "groupies"=>2}, :include => [:groupies])
|
258
263
|
assert_equal 2, @band.groupies
|
259
264
|
assert_equal nil, @band.name
|
260
265
|
end
|
261
266
|
|
262
267
|
it "ignores non-writeable properties" do
|
263
268
|
@band = Class.new(Band) { property :name; collection :founders, :writeable => false; attr_accessor :founders }.new
|
264
|
-
@band.
|
269
|
+
@band.from_hash("name" => "Iron Maiden", "groupies" => 2, "founders" => ["Steve Harris"])
|
265
270
|
assert_equal "Iron Maiden", @band.name
|
266
271
|
assert_equal nil, @band.founders
|
267
272
|
end
|
268
273
|
|
269
274
|
it "always returns the represented" do
|
270
|
-
assert_equal @band, @band.
|
275
|
+
assert_equal @band, @band.from_hash({"name"=>"Nofx"})
|
271
276
|
end
|
272
277
|
|
273
278
|
it "includes false attributes" do
|
274
|
-
@band.
|
279
|
+
@band.from_hash({"groupies"=>false})
|
275
280
|
assert_equal false, @band.groupies
|
276
281
|
end
|
277
282
|
|
@@ -279,14 +284,15 @@ class RepresentableTest < MiniTest::Spec
|
|
279
284
|
@band.instance_eval do
|
280
285
|
def name=(*); raise "I should never be called!"; end
|
281
286
|
end
|
282
|
-
@band.
|
287
|
+
@band.from_hash({})
|
283
288
|
end
|
284
289
|
|
290
|
+
# FIXME: do we need this test with XML _and_ JSON?
|
285
291
|
it "ignores (no-default) properties not present in the incoming document" do
|
286
|
-
{ Representable::
|
287
|
-
Representable::XML => [xml(%{<band/>})
|
292
|
+
{ Representable::Hash => [:from_hash, {}],
|
293
|
+
Representable::XML => [:from_xml, xml(%{<band/>}).to_s]
|
288
294
|
}.each do |format, config|
|
289
|
-
nested_repr = Module.new do # this module is never applied.
|
295
|
+
nested_repr = Module.new do # this module is never applied. # FIXME: can we make that a simpler test?
|
290
296
|
include format
|
291
297
|
property :created_at
|
292
298
|
end
|
@@ -297,7 +303,7 @@ class RepresentableTest < MiniTest::Spec
|
|
297
303
|
end
|
298
304
|
|
299
305
|
@band = Band.new.extend(repr)
|
300
|
-
@band.
|
306
|
+
@band.send(config.first, config.last)
|
301
307
|
assert_equal nil, @band.name, "Failed in #{format}"
|
302
308
|
end
|
303
309
|
end
|
@@ -348,16 +354,16 @@ class RepresentableTest < MiniTest::Spec
|
|
348
354
|
end
|
349
355
|
|
350
356
|
it "compiles document from properties in object" do
|
351
|
-
assert_equal({"name"=>"No One's Choice", "groupies"=>2}, @band.
|
357
|
+
assert_equal({"name"=>"No One's Choice", "groupies"=>2}, @band.to_hash)
|
352
358
|
end
|
353
359
|
|
354
360
|
it "accepts :exclude option" do
|
355
|
-
hash = @band.
|
361
|
+
hash = @band.to_hash({:exclude => [:groupies]})
|
356
362
|
assert_equal({"name"=>"No One's Choice"}, hash)
|
357
363
|
end
|
358
364
|
|
359
365
|
it "accepts :include option" do
|
360
|
-
hash = @band.
|
366
|
+
hash = @band.to_hash({:include => [:groupies]})
|
361
367
|
assert_equal({"groupies"=>2}, hash)
|
362
368
|
end
|
363
369
|
|
@@ -366,18 +372,18 @@ class RepresentableTest < MiniTest::Spec
|
|
366
372
|
@band.name = "Iron Maiden"
|
367
373
|
@band.founder_ids = [1,2,3]
|
368
374
|
|
369
|
-
hash = @band.
|
375
|
+
hash = @band.to_hash
|
370
376
|
assert_equal({"name" => "Iron Maiden"}, hash)
|
371
377
|
end
|
372
378
|
|
373
379
|
it "does not write nil attributes" do
|
374
380
|
@band.groupies = nil
|
375
|
-
assert_equal({"name"=>"No One's Choice"}, @band.
|
381
|
+
assert_equal({"name"=>"No One's Choice"}, @band.to_hash)
|
376
382
|
end
|
377
383
|
|
378
384
|
it "writes false attributes" do
|
379
385
|
@band.groupies = false
|
380
|
-
assert_equal({"name"=>"No One's Choice","groupies"=>false}, @band.
|
386
|
+
assert_equal({"name"=>"No One's Choice","groupies"=>false}, @band.to_hash)
|
381
387
|
end
|
382
388
|
|
383
389
|
describe "when :render_nil is true" do
|
@@ -390,7 +396,7 @@ class RepresentableTest < MiniTest::Spec
|
|
390
396
|
|
391
397
|
@band.extend(mod) # FIXME: use clean object.
|
392
398
|
@band.groupies = nil
|
393
|
-
hash = @band.
|
399
|
+
hash = @band.to_hash
|
394
400
|
assert_equal({"name"=>"No One's Choice", "groupies" => nil}, hash)
|
395
401
|
end
|
396
402
|
|
@@ -403,7 +409,7 @@ class RepresentableTest < MiniTest::Spec
|
|
403
409
|
|
404
410
|
@band.extend(mod) # FIXME: use clean object.
|
405
411
|
@band.groupies = nil
|
406
|
-
hash = @band.
|
412
|
+
hash = @band.to_hash
|
407
413
|
assert_equal({"name"=>"No One's Choice", "groupies" => nil}, hash)
|
408
414
|
end
|
409
415
|
end
|
@@ -422,6 +428,63 @@ class RepresentableTest < MiniTest::Spec
|
|
422
428
|
end
|
423
429
|
end
|
424
430
|
|
431
|
+
describe "inline representers" do
|
432
|
+
let (:song) { Song.new("Alive") }
|
433
|
+
let (:request) { representer.prepare(OpenStruct.new(:song => song)) }
|
434
|
+
|
435
|
+
{
|
436
|
+
:hash => [Representable::Hash, {"song"=>{"name"=>"Alive"}}, {"song"=>{"name"=>"You've Taken Everything"}}],
|
437
|
+
:json => [Representable::JSON, "{\"song\":{\"name\":\"Alive\"}}", "{\"song\":{\"name\":\"You've Taken Everything\"}}"],
|
438
|
+
:xml => [Representable::XML, "<open_struct>\n <song>\n <name>Alive</name>\n </song>\n</open_struct>", "<open_struct><song><name>You've Taken Everything</name></song>/open_struct>"],
|
439
|
+
:yaml => [Representable::YAML, "---\nsong:\n name: Alive\n", "---\nsong:\n name: You've Taken Everything\n"],
|
440
|
+
}.each do |format, cfg|
|
441
|
+
mod, output, input = cfg
|
442
|
+
|
443
|
+
describe "[#{format}] with :class" do
|
444
|
+
representer!(mod) do
|
445
|
+
property :song, :class => Song do
|
446
|
+
property :name
|
447
|
+
end
|
448
|
+
end
|
449
|
+
|
450
|
+
it { request.send("to_#{format}").must_equal output }
|
451
|
+
it { request.send("from_#{format}", input).song.name.must_equal "You've Taken Everything"}
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
describe "without :class" do
|
456
|
+
representer! do
|
457
|
+
property :song do
|
458
|
+
property :name
|
459
|
+
end
|
460
|
+
end
|
461
|
+
|
462
|
+
it { request.to_hash.must_equal({"song"=>{"name"=>"Alive"}}) }
|
463
|
+
end
|
464
|
+
|
465
|
+
describe "decorator" do
|
466
|
+
let (:representer) do
|
467
|
+
Class.new(Representable::Decorator) do
|
468
|
+
include Representable::Hash
|
469
|
+
|
470
|
+
property :song, :class => Song do
|
471
|
+
property :name
|
472
|
+
end
|
473
|
+
|
474
|
+
self
|
475
|
+
end
|
476
|
+
end
|
477
|
+
|
478
|
+
it { request.to_hash.must_equal({"song"=>{"name"=>"Alive"}}) }
|
479
|
+
it { request.from_hash({"song"=>{"name"=>"You've Taken Everything"}}).song.name.must_equal "You've Taken Everything"}
|
480
|
+
|
481
|
+
it "uses an inline decorator" do
|
482
|
+
request.to_hash
|
483
|
+
song.wont_be_kind_of Representable
|
484
|
+
end
|
485
|
+
end
|
486
|
+
end
|
487
|
+
|
425
488
|
describe ":if" do
|
426
489
|
before do
|
427
490
|
@pop = Class.new(PopBand) { attr_accessor :fame }
|
@@ -430,21 +493,21 @@ class RepresentableTest < MiniTest::Spec
|
|
430
493
|
it "respects property when condition true" do
|
431
494
|
@pop.class_eval { property :fame, :if => lambda { true } }
|
432
495
|
band = @pop.new
|
433
|
-
band.
|
496
|
+
band.from_hash({"fame"=>"oh yes"})
|
434
497
|
assert_equal "oh yes", band.fame
|
435
498
|
end
|
436
499
|
|
437
500
|
it "ignores property when condition false" do
|
438
501
|
@pop.class_eval { property :fame, :if => lambda { false } }
|
439
502
|
band = @pop.new
|
440
|
-
band.
|
503
|
+
band.from_hash({"fame"=>"oh yes"})
|
441
504
|
assert_equal nil, band.fame
|
442
505
|
end
|
443
506
|
|
444
507
|
it "ignores property when :exclude'ed even when condition is true" do
|
445
508
|
@pop.class_eval { property :fame, :if => lambda { true } }
|
446
509
|
band = @pop.new
|
447
|
-
band.
|
510
|
+
band.from_hash({"fame"=>"oh yes"}, {:exclude => [:fame]})
|
448
511
|
assert_equal nil, band.fame
|
449
512
|
end
|
450
513
|
|
@@ -452,7 +515,7 @@ class RepresentableTest < MiniTest::Spec
|
|
452
515
|
@pop.class_eval { property :fame, :if => lambda { groupies } }
|
453
516
|
band = @pop.new
|
454
517
|
band.groupies = true
|
455
|
-
band.
|
518
|
+
band.from_hash({"fame"=>"oh yes"})
|
456
519
|
assert_equal "oh yes", band.fame
|
457
520
|
end
|
458
521
|
|
@@ -793,11 +856,68 @@ class RepresentableTest < MiniTest::Spec
|
|
793
856
|
end
|
794
857
|
end
|
795
858
|
|
796
|
-
describe "clone" do
|
859
|
+
describe "#clone" do
|
797
860
|
it "clones all definitions" do
|
798
861
|
subject << Object.new
|
799
862
|
assert subject.first != subject.clone.first
|
800
863
|
end
|
801
864
|
end
|
865
|
+
|
866
|
+
describe "Config inheritance" do
|
867
|
+
# TODO: this section will soon be moved to uber.
|
868
|
+
describe "inheritance when including" do
|
869
|
+
# TODO: test all the below issues AND if cloning works.
|
870
|
+
module TestMethods
|
871
|
+
def representer_for(modules=[Representable], &block)
|
872
|
+
Module.new do
|
873
|
+
extend TestMethods
|
874
|
+
include *modules
|
875
|
+
module_exec(&block)
|
876
|
+
end
|
877
|
+
end
|
878
|
+
end
|
879
|
+
include TestMethods
|
880
|
+
|
881
|
+
it "inherits to uninitialized child" do
|
882
|
+
representer_for do # child
|
883
|
+
include(representer_for do # parent
|
884
|
+
representable_attrs.inheritable_array(:links) << "bar"
|
885
|
+
end)
|
886
|
+
end.representable_attrs.inheritable_array(:links).must_equal(["bar"])
|
887
|
+
end
|
888
|
+
|
889
|
+
it "works with uninitialized parent" do
|
890
|
+
representer_for do # child
|
891
|
+
representable_attrs.inheritable_array(:links) << "bar"
|
892
|
+
|
893
|
+
include(representer_for do # parent
|
894
|
+
end)
|
895
|
+
end.representable_attrs.inheritable_array(:links).must_equal(["bar"])
|
896
|
+
end
|
897
|
+
|
898
|
+
it "inherits when both are initialized" do
|
899
|
+
representer_for do # child
|
900
|
+
representable_attrs.inheritable_array(:links) << "bar"
|
901
|
+
|
902
|
+
include(representer_for do # parent
|
903
|
+
representable_attrs.inheritable_array(:links) << "stadium"
|
904
|
+
end)
|
905
|
+
end.representable_attrs.inheritable_array(:links).must_equal(["bar", "stadium"])
|
906
|
+
end
|
907
|
+
|
908
|
+
it "clones parent inheritables" do # FIXME: actually we don't clone here!
|
909
|
+
representer_for do # child
|
910
|
+
representable_attrs.inheritable_array(:links) << "bar"
|
911
|
+
|
912
|
+
include(parent = representer_for do # parent
|
913
|
+
representable_attrs.inheritable_array(:links) << "stadium"
|
914
|
+
end)
|
915
|
+
|
916
|
+
parent.representable_attrs.inheritable_array(:links) << "park" # modify parent array.
|
917
|
+
|
918
|
+
end.representable_attrs.inheritable_array(:links).must_equal(["bar", "stadium"])
|
919
|
+
end
|
920
|
+
end
|
921
|
+
end
|
802
922
|
end
|
803
923
|
end
|