representable 3.0.3 → 3.0.4

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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -1
  3. data/CHANGES.md +5 -0
  4. data/README.md +1 -1
  5. data/TODO +1 -3
  6. data/TODO-4.0.md +72 -0
  7. data/lib/representable/declarative.rb +3 -3
  8. data/lib/representable/deserializer.rb +1 -1
  9. data/lib/representable/serializer.rb +1 -1
  10. data/lib/representable/version.rb +1 -1
  11. data/lib/representable/xml.rb +6 -4
  12. data/lib/representable/xml/binding.rb +19 -12
  13. data/lib/representable/xml/namespace.rb +122 -0
  14. data/representable.gemspec +2 -2
  15. data/test/as_test.rb +2 -2
  16. data/test/binding_test.rb +7 -7
  17. data/test/cached_test.rb +13 -13
  18. data/test/class_test.rb +2 -2
  19. data/test/coercion_test.rb +1 -1
  20. data/test/config_test.rb +5 -5
  21. data/test/decorator_scope_test.rb +1 -1
  22. data/test/decorator_test.rb +8 -8
  23. data/test/default_test.rb +1 -1
  24. data/test/defaults_options_test.rb +3 -3
  25. data/test/definition_test.rb +9 -11
  26. data/test/examples/object.rb +1 -5
  27. data/test/exec_context_test.rb +2 -2
  28. data/test/features_test.rb +3 -3
  29. data/test/filter_test.rb +2 -2
  30. data/test/for_collection_test.rb +8 -8
  31. data/test/generic_test.rb +11 -11
  32. data/test/hash_bindings_test.rb +1 -1
  33. data/test/hash_test.rb +13 -13
  34. data/test/heritage_test.rb +16 -13
  35. data/test/if_test.rb +3 -3
  36. data/test/include_exclude_test.rb +2 -2
  37. data/test/inherit_test.rb +3 -3
  38. data/test/inline_test.rb +13 -13
  39. data/test/instance_test.rb +2 -2
  40. data/test/json_test.rb +4 -6
  41. data/test/lonely_test.rb +15 -15
  42. data/test/nested_test.rb +6 -6
  43. data/test/object_test.rb +4 -4
  44. data/test/parse_pipeline_test.rb +0 -2
  45. data/test/pipeline_test.rb +7 -7
  46. data/test/populator_test.rb +7 -7
  47. data/test/prepare_test.rb +2 -2
  48. data/test/represent_test.rb +10 -10
  49. data/test/representable_test.rb +7 -7
  50. data/test/schema_test.rb +3 -6
  51. data/test/skip_test.rb +6 -6
  52. data/test/test_helper.rb +16 -6
  53. data/test/wrap_test.rb +8 -8
  54. data/test/xml_namespace_test.rb +186 -0
  55. data/test/xml_test.rb +53 -34
  56. data/test/yaml_test.rb +11 -11
  57. metadata +9 -7
  58. data/lib/representable/TODO.getting_serious +0 -11
@@ -0,0 +1,186 @@
1
+ require "test_helper"
2
+
3
+ # <lib:library
4
+ # xmlns:lib="http://eric.van-der-vlist.com/ns/library"
5
+ # xmlns:hr="http://eric.van-der-vlist.com/ns/person">
6
+ # <lib:book id="b0836217462" available="true">
7
+ # <lib:isbn>0836217462</lib:isbn>
8
+ # <lib:title xml:lang="en">Being a Dog Is a Full-Time Job</lib:title>
9
+ # <hr:author id="CMS">
10
+ # <hr:name>Charles M Schulz</hr:name>
11
+ # <hr:born>1922-11-26</hr:born>
12
+ # <hr:dead>2000-02-12</hr:dead>
13
+ # </hr:author>
14
+ # <lib:character id="PP">
15
+ # <hr:name>Peppermint Patty</hr:name>
16
+ # <hr:born>1966-08-22</hr:born>
17
+ # <lib:qualification>bold, brash and tomboyish</lib:qualification>
18
+ # </lib:character>
19
+ # <lib:character id="Snoopy">
20
+ # <hr:name>Snoopy</hr:name>
21
+ # <hr:born>1950-10-04</hr:born>
22
+ # <lib:qualification>extroverted beagle</lib:qualification>
23
+ # </lib:character>
24
+ # <lib:character id="Schroeder">
25
+ # <hr:name>Schroeder</hr:name>
26
+ # <hr:born>1951-05-30</hr:born>
27
+ # <lib:qualification>brought classical music to the Peanuts strip
28
+ # </lib:qualification>
29
+ # </lib:character>
30
+ # <lib:character id="Lucy">
31
+ # <hr:name>Lucy</hr:name>
32
+ # <hr:born>1952-03-03</hr:born>
33
+ # <lib:qualification>bossy, crabby and selfish</lib:qualification>
34
+ # </lib:character>
35
+ # </lib:book>
36
+ # </lib:library>
37
+
38
+ # Theoretically, every property (scalar) needs/should have a namespace.
39
+ # property :name, namespace: "http://eric.van-der-vlist.com/ns/person"
40
+ # # This is implicit if contained:
41
+ # class Person < Decorator
42
+ # namespace: "http://eric.van-der-vlist.com/ns/person"
43
+ # property :name #, namespace: "http://eric.van-der-vlist.com/ns/person"
44
+ # end
45
+ # class Library
46
+ # namespace "http://eric.van-der-vlist.com/ns/library"
47
+
48
+ # namespace_def lib: "http://eric.van-der-vlist.com/ns/library"
49
+ # namespace_def person: "http://eric.van-der-vlist.com/ns/person"
50
+ # # namespace_def person: Person
51
+
52
+ # property :person, decorator: Person
53
+ # end
54
+ class NamespaceXMLTest < Minitest::Spec
55
+ module Model
56
+ Library = Struct.new(:book)
57
+ Book = Struct.new(:id, :isbn)
58
+ end
59
+
60
+ let (:book) { Model::Book.new(1, 666) }
61
+
62
+ #:simple-class
63
+ class Library < Representable::Decorator
64
+ feature Representable::XML
65
+ feature Representable::XML::Namespace
66
+
67
+ namespace "http://eric.van-der-vlist.com/ns/library"
68
+
69
+ property :book do
70
+ namespace "http://eric.van-der-vlist.com/ns/library"
71
+
72
+ property :id, attribute: true
73
+ property :isbn
74
+ end
75
+ end
76
+ #:simple-class end
77
+
78
+
79
+ # default namespace for library
80
+ it "what" do
81
+ Library.new(Model::Library.new(book)).to_xml.must_xml(
82
+
83
+ #:simple-xml
84
+ %{<library xmlns="http://eric.van-der-vlist.com/ns/library">
85
+ <book id="1">
86
+ <isbn>666</isbn>
87
+ </book>
88
+ </library>}
89
+ #:simple-xml end
90
+ )
91
+ end
92
+ end
93
+
94
+ class Namespace2XMLTest < Minitest::Spec
95
+ module Model
96
+ Library = Struct.new(:book)
97
+ Book = Struct.new(:id, :isbn, :author, :character)
98
+ Character = Struct.new(:name, :born, :qualification)
99
+ end
100
+
101
+ let (:book) { Model::Book.new(1, 666, Model::Character.new("Fowler"), [Model::Character.new("Frau Java", 1991, "typed")]) }
102
+
103
+ #:map-class
104
+ class Library < Representable::Decorator
105
+ feature Representable::XML
106
+ feature Representable::XML::Namespace
107
+
108
+ namespace "http://eric.van-der-vlist.com/ns/library"
109
+ namespace_def lib: "http://eric.van-der-vlist.com/ns/library"
110
+ namespace_def hr: "http://eric.van-der-vlist.com/ns/person"
111
+
112
+ property :book, class: Model::Book do
113
+ namespace "http://eric.van-der-vlist.com/ns/library"
114
+
115
+ property :id, attribute: true
116
+ property :isbn
117
+
118
+ property :author, class: Model::Character do
119
+ namespace "http://eric.van-der-vlist.com/ns/person"
120
+
121
+ property :name
122
+ property :born
123
+ end
124
+
125
+ collection :character, class: Model::Character do
126
+ namespace "http://eric.van-der-vlist.com/ns/library"
127
+
128
+ property :qualification
129
+
130
+ property :name, namespace: "http://eric.van-der-vlist.com/ns/person"
131
+ property :born, namespace: "http://eric.van-der-vlist.com/ns/person"
132
+ end
133
+ end
134
+ end
135
+ #:map-class end
136
+
137
+ it "renders" do
138
+ Library.new(Model::Library.new(book)).to_xml.must_xml(
139
+ #:map-xml
140
+ %{<lib:library xmlns:lib=\"http://eric.van-der-vlist.com/ns/library\" xmlns:hr=\"http://eric.van-der-vlist.com/ns/person\">
141
+ <lib:book id=\"1\">
142
+ <lib:isbn>666</lib:isbn>
143
+ <hr:author>
144
+ <hr:name>Fowler</hr:name>
145
+ </hr:author>
146
+ <lib:character>
147
+ <lib:qualification>typed</lib:qualification>
148
+ <hr:name>Frau Java</hr:name>
149
+ <hr:born>1991</hr:born>
150
+ </lib:character>
151
+ </lib:book>
152
+ </lib:library>}
153
+ #:map-xml end
154
+ )
155
+ end
156
+
157
+ it "parses" do
158
+ lib = Model::Library.new
159
+ #:parse-call
160
+ Library.new(lib).from_xml(%{<lib:library
161
+ xmlns:lib="http://eric.van-der-vlist.com/ns/library"
162
+ xmlns:hr="http://eric.van-der-vlist.com/ns/person">
163
+ <lib:book id="1">
164
+ <lib:isbn>666</lib:isbn>
165
+ <hr:author>
166
+ <hr:name>Fowler</hr:name>
167
+ </hr:author>
168
+ <lib:character>
169
+ <lib:qualification>typed</lib:qualification>
170
+ <hr:name>Frau Java</hr:name>
171
+ <bogus:name>Mr. Ruby</hr:name>
172
+ <name>Dr. Elixir</hr:name>
173
+ <hr:born>1991</hr:born>
174
+ </lib:character>
175
+ </lib:book>
176
+ </lib:library>}
177
+ #:parse-call end
178
+ )
179
+
180
+ lib.book.inspect.must_equal %{#<struct Namespace2XMLTest::Model::Book id=\"1\", isbn=\"666\", author=#<struct Namespace2XMLTest::Model::Character name=\"Fowler\", born=nil, qualification=nil>, character=[#<struct Namespace2XMLTest::Model::Character name=\"Frau Java\", born=\"1991\", qualification=\"typed\">]>}
181
+
182
+ #:parse-res
183
+ lib.book.character[0].name #=> "Frau Java"
184
+ #:parse-res end
185
+ end
186
+ end
@@ -10,14 +10,14 @@ class XmlPublicMethodsTest < Minitest::Spec
10
10
  property :name
11
11
  end
12
12
 
13
- let (:data) { %{<data><id>1</id><name>Rancid</name></data>} }
13
+ let(:data) { %{<data><id>1</id><name>Rancid</name></data>} }
14
14
 
15
15
  it { BandRepresenter.new(Band.new).from_xml(data)[:id, :name].must_equal ["1", "Rancid"] }
16
16
  it { BandRepresenter.new(Band.new).parse(data)[:id, :name].must_equal ["1", "Rancid"] }
17
17
 
18
18
  #---
19
19
  # to_hash
20
- let (:band) { Band.new("1", "Rancid") }
20
+ let(:band) { Band.new("1", "Rancid") }
21
21
 
22
22
  it { BandRepresenter.new(band).to_xml.must_equal_xml data }
23
23
  it { BandRepresenter.new(band).render.must_equal_xml data }
@@ -145,14 +145,12 @@ class XmlTest < MiniTest::Spec
145
145
  module SongRepresenter
146
146
  include Representable::XML
147
147
  property :name
148
- representation_wrap = :song
149
148
  end
150
149
 
151
150
  module AlbumRepresenter
152
151
  include Representable::XML
153
152
  property :best_song, :class => Song, :extend => SongRepresenter
154
153
  collection :songs, :class => Song, :as => :song, :extend => SongRepresenter
155
- representation_wrap = :album
156
154
  end
157
155
 
158
156
 
@@ -179,11 +177,11 @@ class XmlTest < MiniTest::Spec
179
177
  [Song.new("I Hate My Brain"), mr=Song.new("Mr. Charisma")], mr)
180
178
  @album.extend(AlbumRepresenter)
181
179
 
182
- assert_xml_equal "<album>
180
+ @album.to_xml.must_equal_xml "<album>
183
181
  <song><name>Mr. Charisma</name></song>
184
182
  <song><name>I Hate My Brain</name></song>
185
183
  <song><name>Mr. Charisma</name></song>
186
- </album>", @album.to_xml
184
+ </album>"
187
185
  end
188
186
 
189
187
  it "extends contained models when deserializing" do
@@ -316,32 +314,54 @@ class TypedPropertyTest < MiniTest::Spec
316
314
  end
317
315
  end
318
316
 
317
+ # TODO: add parsing tests.
318
+ class XMLPropertyTest < Minitest::Spec
319
+ Band = Struct.new(:name, :genre)
320
+ Manager = Struct.new(:managed)
319
321
 
320
- class CollectionTest < MiniTest::Spec
321
- class Band
322
+ #---
323
+ #- :as with scalar
324
+ class BandRepresenter < Representable::Decorator
322
325
  include Representable::XML
323
- property :name
324
- attr_accessor :name
326
+ property :name, as: :theyCallUs
327
+ property :genre, attribute: true
328
+ end
325
329
 
326
- def initialize(name=nil)
327
- name and self.name = name
328
- end
330
+ it { BandRepresenter.new(Band.new("Mute")).to_xml.must_equal_xml %{<band><theyCallUs>Mute</theyCallUs></band>} }
331
+
332
+ class ManagerRepresenter < Representable::Decorator
333
+ include Representable::XML
334
+ property :managed, as: :band, decorator: BandRepresenter
329
335
  end
330
336
 
337
+ #- :as with nested property
338
+ it { ManagerRepresenter.new(Manager.new(Band.new("Mute", "Punkrock"))).to_xml.must_equal_xml %{<manager><band genre="Punkrock"><theyCallUs>Mute</theyCallUs></band></manager>} }
339
+ end
340
+
341
+
342
+ class XMLCollectionTest < MiniTest::Spec
343
+ Band = Struct.new(:name)
344
+ Compilation = Struct.new(:bands)
345
+
346
+ class BandRepresenter < Representable::Decorator
347
+ include Representable::XML
348
+ property :name
349
+ end
331
350
 
351
+ #---
352
+ #- :as, :decorator, :class
332
353
  describe ":class => Band, :as => :band, :collection => true" do
333
- class Compilation
354
+ class CompilationRepresenter < Representable::Decorator
334
355
  include Representable::XML
335
- collection :bands, :class => Band, :as => :band
336
- attr_accessor :bands
356
+ collection :bands, class: Band, as: :group, decorator: BandRepresenter
337
357
  end
338
358
 
339
359
  describe "#from_xml" do
340
360
  it "pushes collection items to array" do
341
- cd = Compilation.new.from_xml(%{
361
+ cd = CompilationRepresenter.new(Compilation.new).from_xml(%{
342
362
  <compilation>
343
- <band><name>Diesel Boy</name></band>
344
- <band><name>Cobra Skulls</name></band>
363
+ <group><name>Diesel Boy</name></group>
364
+ <group><name>Cobra Skulls</name></group>
345
365
  </compilation>
346
366
  })
347
367
  assert_equal ["Cobra Skulls", "Diesel Boy"], cd.bands.map(&:name).sort
@@ -349,13 +369,12 @@ class CollectionTest < MiniTest::Spec
349
369
  end
350
370
 
351
371
  it "responds to #to_xml" do
352
- cd = Compilation.new
353
- cd.bands = [Band.new("Diesel Boy"), Band.new("Bad Religion")]
372
+ cd = Compilation.new([Band.new("Diesel Boy"), Band.new("Bad Religion")])
354
373
 
355
- assert_xml_equal %{<compilation>
356
- <band><name>Diesel Boy</name></band>
357
- <band><name>Bad Religion</name></band>
358
- </compilation>}, cd.to_xml
374
+ CompilationRepresenter.new(cd).to_xml.must_equal_xml %{<compilation>
375
+ <group><name>Diesel Boy</name></group>
376
+ <group><name>Bad Religion</name></group>
377
+ </compilation>}
359
378
  end
360
379
  end
361
380
 
@@ -381,8 +400,8 @@ class CollectionTest < MiniTest::Spec
381
400
 
382
401
 
383
402
  describe ":wrap" do
384
- let (:album) { Album.new.extend(xml_doc) }
385
- let (:xml_doc) {
403
+ let(:album) { Album.new.extend(xml_doc) }
404
+ let(:xml_doc) {
386
405
  Module.new do
387
406
  include Representable::XML
388
407
  collection :songs, :as => :song, :wrap => :songs
@@ -428,7 +447,7 @@ class CollectionTest < MiniTest::Spec
428
447
  self.representation_wrap = :song
429
448
  end
430
449
 
431
- let (:decorator) { rpr = representer; Class.new(Representable::Decorator) { include Representable::XML; include rpr } }
450
+ let(:decorator) { rpr = representer; Class.new(Representable::Decorator) { include Representable::XML; include rpr } }
432
451
 
433
452
  describe "XML::Collection" do
434
453
  describe "with contained objects" do
@@ -437,8 +456,8 @@ class CollectionTest < MiniTest::Spec
437
456
  self.representation_wrap= :songs
438
457
  end
439
458
 
440
- let (:songs) { [Song.new("Days Go By"), Song.new("Can't Take Them All")] }
441
- let (:xml_doc) { "<songs><song><name>Days Go By</name></song><song><name>Can't Take Them All</name></song></songs>" }
459
+ let(:songs) { [Song.new("Days Go By"), Song.new("Can't Take Them All")] }
460
+ let(:xml_doc) { "<songs><song><name>Days Go By</name></song><song><name>Can't Take Them All</name></song></songs>" }
442
461
 
443
462
  it "renders array" do
444
463
  songs.extend(representer).to_xml.must_equal_xml xml_doc
@@ -463,8 +482,8 @@ class CollectionTest < MiniTest::Spec
463
482
  self.representation_wrap= :songs
464
483
  end
465
484
 
466
- let (:songs) { {"one" => "Graveyards", "two" => "Can't Take Them All"} }
467
- let (:xml_doc) { "<favs one=\"Graveyards\" two=\"Can't Take Them All\" />" }
485
+ let(:songs) { {"one" => "Graveyards", "two" => "Can't Take Them All"} }
486
+ let(:xml_doc) { "<favs one=\"Graveyards\" two=\"Can't Take Them All\" />" }
468
487
 
469
488
  describe "#to_xml" do
470
489
  it "renders hash" do
@@ -512,7 +531,7 @@ class XmlHashTest < MiniTest::Spec
512
531
  hash :songs
513
532
  end
514
533
 
515
- let (:doc) { "<open_struct><first>The Gargoyle</first><second>Bronx</second></open_struct>" }
534
+ let(:doc) { "<open_struct><first>The Gargoyle</first><second>Bronx</second></open_struct>" }
516
535
 
517
536
  # to_xml
518
537
  it { OpenStruct.new(songs: {"first" => "The Gargoyle", "second" => "Bronx"}).extend(representer).to_xml.must_equal_xml(doc) }
@@ -527,7 +546,7 @@ class XmlHashTest < MiniTest::Spec
527
546
  end
528
547
  end
529
548
 
530
- let (:doc) { "<open_struct>
549
+ let(:doc) { "<open_struct>
531
550
  <open_struct>
532
551
  <title>The Gargoyle</title>
533
552
  </open_struct>
@@ -9,7 +9,7 @@ class YamlPublicMethodsTest < Minitest::Spec
9
9
  property :name
10
10
  end
11
11
 
12
- let (:data) { %{---
12
+ let(:data) { %{---
13
13
  id: 1
14
14
  name: Rancid
15
15
  } }
@@ -19,7 +19,7 @@ name: Rancid
19
19
 
20
20
  #---
21
21
  # to_yaml
22
- let (:band) { Band.new("1", "Rancid") }
22
+ let(:band) { Band.new("1", "Rancid") }
23
23
 
24
24
  it { BandRepresenter.new(band).to_yaml.must_equal data }
25
25
  it { BandRepresenter.new(band).render.must_equal data }
@@ -29,7 +29,7 @@ class YamlTest < MiniTest::Spec
29
29
  def self.yaml_representer(&block)
30
30
  Module.new do
31
31
  include Representable::YAML
32
- instance_exec &block
32
+ instance_exec(&block)
33
33
  end
34
34
  end
35
35
 
@@ -39,9 +39,9 @@ class YamlTest < MiniTest::Spec
39
39
 
40
40
 
41
41
  describe "property" do
42
- let (:yaml) { yaml_representer do property :best_song end }
42
+ let(:yaml) { yaml_representer do property :best_song end }
43
43
 
44
- let (:album) { Album.new.tap do |album|
44
+ let(:album) { Album.new.tap do |album|
45
45
  album.best_song = "Liar"
46
46
  end }
47
47
 
@@ -75,12 +75,12 @@ best_song: This Song Is Recycled
75
75
 
76
76
  describe "with :class and :extend" do
77
77
  yaml_song = yaml_representer do property :name end
78
- let (:yaml_album) { Module.new do
78
+ let(:yaml_album) { Module.new do
79
79
  include Representable::YAML
80
80
  property :best_song, :extend => yaml_song, :class => Song
81
81
  end }
82
82
 
83
- let (:album) { Album.new.tap do |album|
83
+ let(:album) { Album.new.tap do |album|
84
84
  album.best_song = Song.new("Liar")
85
85
  end }
86
86
 
@@ -107,9 +107,9 @@ best_song:
107
107
 
108
108
 
109
109
  describe "collection" do
110
- let (:yaml) { yaml_representer do collection :songs end }
110
+ let(:yaml) { yaml_representer do collection :songs end }
111
111
 
112
- let (:album) { Album.new.tap do |album|
112
+ let(:album) { Album.new.tap do |album|
113
113
  album.songs = ["Jackhammer", "Terrible Man"]
114
114
  end }
115
115
 
@@ -149,7 +149,7 @@ songs: [Off Key Melody, Sinking]").must_equal Album.new(["Off Key Melody", "Sink
149
149
 
150
150
 
151
151
  describe "with :class and :extend" do
152
- let (:yaml_album) { Module.new do
152
+ let(:yaml_album) { Module.new do
153
153
  include Representable::YAML
154
154
  collection :songs, :class => Song do
155
155
  property :name
@@ -157,7 +157,7 @@ songs: [Off Key Melody, Sinking]").must_equal Album.new(["Off Key Melody", "Sink
157
157
  end
158
158
  end }
159
159
 
160
- let (:album) { Album.new([Song.new("Liar", 1), Song.new("What I Know", 2)]) }
160
+ let(:album) { Album.new([Song.new("Liar", 1), Song.new("What I Know", 2)]) }
161
161
 
162
162
 
163
163
  describe "#to_yaml" do