representable 3.0.0 → 3.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 +5 -5
- data/.github/workflows/ci.yml +23 -0
- data/CHANGES.md +33 -0
- data/Gemfile +4 -12
- data/LICENSE +1 -1
- data/README.md +12 -13
- data/Rakefile +1 -6
- data/TODO +1 -3
- data/TODO-4.0.md +72 -0
- data/lib/representable/binding.rb +32 -12
- data/lib/representable/cached.rb +1 -1
- data/lib/representable/coercion.rb +8 -6
- data/lib/representable/config.rb +13 -3
- data/lib/representable/debug.rb +23 -15
- data/lib/representable/declarative.rb +12 -7
- data/lib/representable/decorator.rb +1 -1
- data/lib/representable/definition.rb +7 -3
- data/lib/representable/deserializer.rb +5 -4
- data/lib/representable/for_collection.rb +1 -1
- data/lib/representable/hash/allow_symbols.rb +9 -11
- data/lib/representable/hash/binding.rb +1 -0
- data/lib/representable/hash/collection.rb +4 -2
- data/lib/representable/hash.rb +9 -2
- data/lib/representable/hash_methods.rb +3 -2
- data/lib/representable/insert.rb +1 -1
- data/lib/representable/json/collection.rb +3 -0
- data/lib/representable/json.rb +8 -7
- data/lib/representable/object/binding.rb +5 -1
- data/lib/representable/object.rb +1 -1
- data/lib/representable/option.rb +19 -0
- data/lib/representable/pipeline.rb +3 -2
- data/lib/representable/pipeline_factories.rb +4 -2
- data/lib/representable/populator.rb +1 -1
- data/lib/representable/represent.rb +1 -0
- data/lib/representable/serializer.rb +3 -2
- data/lib/representable/version.rb +1 -1
- data/lib/representable/xml/binding.rb +19 -13
- data/lib/representable/xml/namespace.rb +122 -0
- data/lib/representable/xml.rb +12 -10
- data/lib/representable/yaml/binding.rb +1 -0
- data/lib/representable/yaml.rb +6 -2
- data/lib/representable.rb +19 -25
- data/representable.gemspec +8 -9
- data/test/as_test.rb +7 -7
- data/test/binding_test.rb +14 -14
- data/test/cached_test.rb +59 -49
- data/test/class_test.rb +9 -9
- data/test/coercion_test.rb +33 -22
- data/test/config/inherit_test.rb +14 -14
- data/test/config_test.rb +20 -20
- data/test/decorator_scope_test.rb +4 -4
- data/test/decorator_test.rb +33 -20
- data/test/default_test.rb +8 -8
- data/test/defaults_options_test.rb +3 -3
- data/test/definition_test.rb +38 -40
- data/test/{example.rb → examples/example.rb} +0 -1
- data/test/examples/object.rb +1 -5
- data/test/exec_context_test.rb +8 -8
- data/test/features_test.rb +6 -6
- data/test/filter_test.rb +8 -8
- data/test/for_collection_test.rb +10 -10
- data/test/generic_test.rb +13 -13
- data/test/getter_setter_test.rb +5 -5
- data/test/hash_bindings_test.rb +1 -1
- data/test/hash_test.rb +45 -23
- data/test/heritage_test.rb +16 -13
- data/test/if_test.rb +9 -9
- data/test/include_exclude_test.rb +14 -14
- data/test/inherit_test.rb +18 -18
- data/test/inline_test.rb +24 -24
- data/test/instance_test.rb +31 -31
- data/test/is_representable_test.rb +10 -10
- data/test/json_test.rb +29 -7
- data/test/lonely_test.rb +31 -31
- data/test/nested_test.rb +13 -13
- data/test/object_test.rb +9 -9
- data/test/option_test.rb +36 -0
- data/test/parse_pipeline_test.rb +3 -5
- data/test/pipeline_test.rb +50 -50
- data/test/populator_test.rb +18 -18
- data/test/prepare_test.rb +4 -4
- data/test/private_options_test.rb +2 -2
- data/test/reader_writer_test.rb +2 -2
- data/test/render_nil_test.rb +2 -2
- data/test/represent_test.rb +14 -14
- data/test/representable_test.rb +34 -36
- data/test/schema_test.rb +8 -11
- data/test/serialize_deserialize_test.rb +2 -2
- data/test/skip_test.rb +14 -14
- data/test/stringify_hash_test.rb +3 -3
- data/test/test_helper.rb +26 -14
- data/test/uncategorized_test.rb +10 -10
- data/test/user_options_test.rb +4 -4
- data/test/wrap_test.rb +19 -19
- data/test/xml_bindings_test.rb +0 -4
- data/test/xml_namespace_test.rb +186 -0
- data/test/xml_test.rb +103 -43
- data/test/yaml_test.rb +51 -26
- metadata +42 -35
- data/.travis.yml +0 -7
- data/lib/representable/TODO.getting_serious +0 -11
- data/lib/representable/autoload.rb +0 -10
- data/test/mongoid_test.rb +0 -31
data/test/test_helper.rb
CHANGED
@@ -1,16 +1,20 @@
|
|
1
|
+
require 'pry-byebug'
|
1
2
|
require 'representable'
|
2
3
|
|
3
|
-
require "json"
|
4
|
-
require "psych"
|
5
|
-
|
6
|
-
require 'representable/json'
|
7
|
-
require 'representable/xml'
|
8
|
-
require 'representable/yaml'
|
9
4
|
require 'minitest/autorun'
|
10
5
|
require 'test_xml/mini_test'
|
11
6
|
|
12
7
|
require "representable/debug"
|
8
|
+
require 'minitest/assertions'
|
13
9
|
|
10
|
+
module MiniTest::Assertions
|
11
|
+
def assert_equal_xml(text, subject)
|
12
|
+
assert_equal (text.gsub("\n", "").gsub(/(\s\s+)/, "")), subject.gsub("\n", "").gsub(/(\s\s+)/, "")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
String.infect_an_assertion :assert_equal_xml, :must_xml
|
16
|
+
|
17
|
+
# TODO: delete all that in 4.0:
|
14
18
|
class Album
|
15
19
|
attr_accessor :songs, :best_song
|
16
20
|
def initialize(songs=nil, best_song=nil)
|
@@ -45,7 +49,7 @@ module AssertJson
|
|
45
49
|
module Assertions
|
46
50
|
def assert_json(expected, actual, msg=nil)
|
47
51
|
msg = message(msg, "") { diff expected, actual }
|
48
|
-
|
52
|
+
assert_equal(expected.split("").sort, actual.split("").sort, msg)
|
49
53
|
end
|
50
54
|
end
|
51
55
|
end
|
@@ -83,7 +87,7 @@ MiniTest::Spec.class_eval do
|
|
83
87
|
end
|
84
88
|
|
85
89
|
def self.representer!(options={}, &block)
|
86
|
-
fmt = options # we need that so the 2nd call to ::let
|
90
|
+
fmt = options # we need that so the 2nd call to ::let(within a ::describe) remembers the right format.
|
87
91
|
|
88
92
|
name = options[:name] || :representer
|
89
93
|
format = options[:module] || Representable::Hash
|
@@ -101,6 +105,8 @@ MiniTest::Spec.class_eval do
|
|
101
105
|
mod
|
102
106
|
end
|
103
107
|
|
108
|
+
undef :inject_representer if method_defined? :inject_representer
|
109
|
+
|
104
110
|
def inject_representer(mod, options)
|
105
111
|
return unless options[:inject]
|
106
112
|
|
@@ -116,7 +122,7 @@ MiniTest::Spec.class_eval do
|
|
116
122
|
def representer_for(modules=[Representable::Hash], &block)
|
117
123
|
Module.new do
|
118
124
|
extend TestMethods
|
119
|
-
include
|
125
|
+
include(*modules)
|
120
126
|
module_exec(&block)
|
121
127
|
end
|
122
128
|
end
|
@@ -127,9 +133,15 @@ MiniTest::Spec.class_eval do
|
|
127
133
|
end
|
128
134
|
|
129
135
|
class BaseTest < MiniTest::Spec
|
130
|
-
let
|
131
|
-
let
|
132
|
-
let
|
133
|
-
let
|
136
|
+
let(:new_album) { OpenStruct.new.extend(representer) }
|
137
|
+
let(:album) { OpenStruct.new(:songs => ["Fuck Armageddon"]).extend(representer) }
|
138
|
+
let(:song) { OpenStruct.new(:title => "Resist Stance") }
|
139
|
+
let(:song_representer) { Module.new do include Representable::Hash; property :title end }
|
134
140
|
|
135
|
-
end
|
141
|
+
end
|
142
|
+
|
143
|
+
Band = Struct.new(:id, :name) do
|
144
|
+
def [](*attrs)
|
145
|
+
attrs.collect { |attr| send(attr) }
|
146
|
+
end
|
147
|
+
end
|
data/test/uncategorized_test.rb
CHANGED
@@ -15,12 +15,12 @@ class StopWhenIncomingObjectFragmentIsNilTest < MiniTest::Spec
|
|
15
15
|
|
16
16
|
it do
|
17
17
|
album = Album.new
|
18
|
-
representer.new(album).from_hash({"id"=>1, "songs"=>[{"title"=>"Walkie Talkie"}]}).songs.must_equal [Song.new("Walkie Talkie")]
|
18
|
+
_(representer.new(album).from_hash({"id"=>1, "songs"=>[{"title"=>"Walkie Talkie"}]}).songs).must_equal [Song.new("Walkie Talkie")]
|
19
19
|
end
|
20
20
|
|
21
21
|
it do
|
22
22
|
album = Album.new(2, ["original"])
|
23
|
-
representer.new(album).from_hash({"id"=>1, "songs"=>nil}).songs.must_equal ["original"]
|
23
|
+
_(representer.new(album).from_hash({"id"=>1, "songs"=>nil}).songs).must_equal ["original"]
|
24
24
|
end
|
25
25
|
|
26
26
|
end
|
@@ -35,13 +35,13 @@ class RenderPipelineOptionTest < MiniTest::Spec
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
it { representer.new(Album.new).to_hash(user_options: {function: NilToNA}).must_equal({"id"=>"n/a"}) }
|
39
|
-
it { representer.new(Album.new(1)).to_hash(user_options: {function: NilToNA}).must_equal({"id"=>1}) }
|
38
|
+
it { _(representer.new(Album.new).to_hash(user_options: {function: NilToNA})).must_equal({"id"=>"n/a"}) }
|
39
|
+
it { _(representer.new(Album.new(1)).to_hash(user_options: {function: NilToNA})).must_equal({"id"=>1}) }
|
40
40
|
|
41
41
|
it "is cached" do
|
42
42
|
decorator = representer.new(Album.new)
|
43
|
-
decorator.to_hash(user_options: {function: NilToNA}).must_equal({"id"=>"n/a"})
|
44
|
-
decorator.to_hash(user_options: {function: nil}).must_equal({"id"=>"n/a"}) # non-sense function is not applied.
|
43
|
+
_(decorator.to_hash(user_options: {function: NilToNA})).must_equal({"id"=>"n/a"})
|
44
|
+
_(decorator.to_hash(user_options: {function: nil})).must_equal({"id"=>"n/a"}) # non-sense function is not applied.
|
45
45
|
end
|
46
46
|
|
47
47
|
end
|
@@ -56,12 +56,12 @@ class ParsePipelineOptionTest < MiniTest::Spec
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
-
it { representer.new(Album.new).from_hash({"id"=>nil}, user_options: {function: NilToNA}).id.must_equal "n/a" }
|
60
|
-
it { representer.new(Album.new(1)).to_hash(user_options: {function: NilToNA}).must_equal({"id"=>1}) }
|
59
|
+
it { _(representer.new(Album.new).from_hash({"id"=>nil}, user_options: {function: NilToNA}).id).must_equal "n/a" }
|
60
|
+
it { _(representer.new(Album.new(1)).to_hash(user_options: {function: NilToNA})).must_equal({"id"=>1}) }
|
61
61
|
|
62
62
|
it "is cached" do
|
63
63
|
decorator = representer.new(Album.new)
|
64
|
-
decorator.from_hash({"id"=>nil}, user_options: {function: NilToNA}).id.must_equal "n/a"
|
65
|
-
decorator.from_hash({"id"=>nil}, user_options: {function: "nonsense"}).id.must_equal "n/a" # non-sense function is not applied.
|
64
|
+
_(decorator.from_hash({"id"=>nil}, user_options: {function: NilToNA}).id).must_equal "n/a"
|
65
|
+
_(decorator.from_hash({"id"=>nil}, user_options: {function: "nonsense"}).id).must_equal "n/a" # non-sense function is not applied.
|
66
66
|
end
|
67
67
|
end
|
data/test/user_options_test.rb
CHANGED
@@ -7,9 +7,9 @@ class UserOptionsTest < Minitest::Spec
|
|
7
7
|
property :title, if: ->(options) { options[:user_options][:visible] }
|
8
8
|
end
|
9
9
|
|
10
|
-
it { Song.new("Run With It").extend(representer).to_hash.must_equal({}) }
|
11
|
-
it { Song.new("Run With It").extend(representer).to_hash(user_options: {visible: true}).must_equal({"title"=>"Run With It"}) }
|
12
|
-
it { Song.new("Run With It").extend(representer).from_hash("title"=>"Business Conduct").title.must_equal "Run With It" }
|
13
|
-
it { Song.new("Run With It").extend(representer).from_hash({"title"=>"Business Conduct"}, user_options: {visible: true}).title.must_equal "Business Conduct" }
|
10
|
+
it { _(Song.new("Run With It").extend(representer).to_hash).must_equal({}) }
|
11
|
+
it { _(Song.new("Run With It").extend(representer).to_hash(user_options: {visible: true})).must_equal({"title"=>"Run With It"}) }
|
12
|
+
it { _(Song.new("Run With It").extend(representer).from_hash("title"=>"Business Conduct").title).must_equal "Run With It" }
|
13
|
+
it { _(Song.new("Run With It").extend(representer).from_hash({"title"=>"Business Conduct"}, user_options: {visible: true}).title).must_equal "Business Conduct" }
|
14
14
|
end
|
15
15
|
# Representable.deprecations=false
|
data/test/wrap_test.rb
CHANGED
@@ -8,10 +8,10 @@ class WrapTest < MiniTest::Spec
|
|
8
8
|
class SoftcoreBand < HardcoreBand
|
9
9
|
end
|
10
10
|
|
11
|
-
let
|
11
|
+
let(:band) { HardcoreBand.new }
|
12
12
|
|
13
13
|
it "returns false per default" do
|
14
|
-
|
14
|
+
assert_nil SoftcoreBand.new.send(:representation_wrap)
|
15
15
|
end
|
16
16
|
|
17
17
|
it "infers a printable class name if set to true" do
|
@@ -32,17 +32,17 @@ class WrapTest < MiniTest::Spec
|
|
32
32
|
) do |format, mod, output, input|
|
33
33
|
|
34
34
|
describe "[#{format}] dynamic wrap" do
|
35
|
-
let
|
36
|
-
let
|
35
|
+
let(:band) { representer.prepare(Struct.new(:name, :genre).new("Blink", "Pop")) }
|
36
|
+
let(:format) { format }
|
37
37
|
|
38
38
|
representer!(:module => mod) do
|
39
|
-
self.representation_wrap = lambda { |
|
39
|
+
self.representation_wrap = lambda { |number:, **| "#{name}#{number}" }
|
40
40
|
property :genre
|
41
41
|
end
|
42
42
|
|
43
43
|
it { render(band, {:number => 182}).must_equal_document(output) }
|
44
44
|
|
45
|
-
it { parse(band, input, {:number => 182}).genre.must_equal "Poppunk" } # TODO: better test. also, xml parses _any_ wrap.
|
45
|
+
it { _(parse(band, input, {:number => 182}).genre).must_equal "Poppunk" } # TODO: better test. also, xml parses _any_ wrap.
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
@@ -65,19 +65,19 @@ class HashDisableWrapTest < MiniTest::Spec
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
-
let
|
68
|
+
let(:band) { BandDecorator.prepare(Band.new("Social Distortion")) }
|
69
69
|
|
70
70
|
# direct, local api.
|
71
71
|
it do
|
72
|
-
band.to_hash.must_equal({"bands" => {"name"=>"Social Distortion"}})
|
73
|
-
band.to_hash(wrap: false).must_equal({"name"=>"Social Distortion"})
|
74
|
-
band.to_hash(wrap: :band).must_equal(:band=>{"name"=>"Social Distortion"})
|
72
|
+
_(band.to_hash).must_equal({"bands" => {"name"=>"Social Distortion"}})
|
73
|
+
_(band.to_hash(wrap: false)).must_equal({"name"=>"Social Distortion"})
|
74
|
+
_(band.to_hash(wrap: :band)).must_equal(:band=>{"name"=>"Social Distortion"})
|
75
75
|
end
|
76
76
|
|
77
77
|
it do
|
78
|
-
band.from_hash({"bands" => {"name"=>"Social Distortion"}}).name.must_equal "Social Distortion"
|
79
|
-
band.from_hash({"name"=>"Social Distortion"}, wrap: false).name.must_equal "Social Distortion"
|
80
|
-
band.from_hash({band: {"name"=>"Social Distortion"}}, wrap: :band).name.must_equal "Social Distortion"
|
78
|
+
_(band.from_hash({"bands" => {"name"=>"Social Distortion"}}).name).must_equal "Social Distortion"
|
79
|
+
_(band.from_hash({"name"=>"Social Distortion"}, wrap: false).name).must_equal "Social Distortion"
|
80
|
+
_(band.from_hash({band: {"name"=>"Social Distortion"}}, wrap: :band).name).must_equal "Social Distortion"
|
81
81
|
end
|
82
82
|
|
83
83
|
|
@@ -90,15 +90,15 @@ class HashDisableWrapTest < MiniTest::Spec
|
|
90
90
|
end
|
91
91
|
|
92
92
|
|
93
|
-
let
|
93
|
+
let(:album) { AlbumDecorator.prepare(Album.new(Band.new("Social Distortion", Label.new("Epitaph")))) }
|
94
94
|
|
95
95
|
# band has wrap turned off per property definition, however, label still has wrap.
|
96
96
|
it "renders" do
|
97
|
-
album.to_hash.must_equal({"albums" => {"band" => {"name"=>"Social Distortion", "label"=>{"important"=>{"name"=>"Epitaph"}}}}})
|
97
|
+
_(album.to_hash).must_equal({"albums" => {"band" => {"name"=>"Social Distortion", "label"=>{"important"=>{"name"=>"Epitaph"}}}}})
|
98
98
|
end
|
99
99
|
|
100
100
|
it "parses" do
|
101
|
-
album.from_hash({"albums" => {"band" => {"name"=>"Rvivr"}}}).band.name.must_equal "Rvivr"
|
101
|
+
_(album.from_hash({"albums" => {"band" => {"name"=>"Rvivr"}}}).band.name).must_equal "Rvivr"
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
@@ -120,7 +120,7 @@ class XMLDisableWrapTest < MiniTest::Spec
|
|
120
120
|
# end
|
121
121
|
end
|
122
122
|
|
123
|
-
let
|
123
|
+
let(:band) { BandDecorator.prepare(Band.new("Social Distortion")) }
|
124
124
|
|
125
125
|
it do
|
126
126
|
band.to_xml.must_equal_xml "<bands><name>Social Distortion</name></bands>"
|
@@ -137,12 +137,12 @@ class XMLDisableWrapTest < MiniTest::Spec
|
|
137
137
|
end
|
138
138
|
|
139
139
|
|
140
|
-
let
|
140
|
+
let(:album) { AlbumDecorator.prepare(Album.new(Band.new("Social Distortion", Label.new("Epitaph")))) }
|
141
141
|
|
142
142
|
# band has wrap turned of per property definition, however, label still has wrap.
|
143
143
|
it "rendersxx" do
|
144
144
|
skip
|
145
|
-
album.to_xml.must_equal({"albums" => {"band" => {"name"=>"Social Distortion", "label"=>{"important"=>{"name"=>"Epitaph"}}}}})
|
145
|
+
_(album.to_xml).must_equal({"albums" => {"band" => {"name"=>"Social Distortion", "label"=>{"important"=>{"name"=>"Epitaph"}}}}})
|
146
146
|
end
|
147
147
|
|
148
148
|
# it "parses" do
|
data/test/xml_bindings_test.rb
CHANGED
@@ -1,10 +1,6 @@
|
|
1
1
|
require 'test_helper'
|
2
|
-
require 'representable/json' # FIXME.
|
3
|
-
require 'representable/xml/collection'
|
4
2
|
require 'representable/xml/hash'
|
5
3
|
|
6
|
-
require 'representable/xml'
|
7
|
-
|
8
4
|
class XMLBindingTest < MiniTest::Spec
|
9
5
|
module SongRepresenter
|
10
6
|
include Representable::XML
|
@@ -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
|