representable 2.4.1 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +7 -12
- data/CHANGES.md +6 -27
- data/README.md +28 -1326
- data/lib/representable.rb +4 -14
- data/lib/representable/binding.rb +3 -7
- data/lib/representable/definition.rb +1 -2
- data/lib/representable/populator.rb +35 -0
- data/lib/representable/version.rb +1 -1
- data/test/definition_test.rb +0 -7
- data/test/exec_context_test.rb +2 -2
- data/test/instance_test.rb +0 -19
- data/test/realistic_benchmark.rb +0 -13
- data/test/representable_test.rb +0 -16
- data/test/skip_test.rb +1 -1
- data/test/test_helper.rb +0 -2
- metadata +3 -65
- data/lib/representable/deprecations.rb +0 -127
- data/lib/representable/parse_strategies.rb +0 -93
- data/test-with-deprecations/as_test.rb +0 -65
- data/test-with-deprecations/benchmarking.rb +0 -83
- data/test-with-deprecations/binding_test.rb +0 -46
- data/test-with-deprecations/blaaaaaaaa_test.rb +0 -69
- data/test-with-deprecations/cached_test.rb +0 -147
- data/test-with-deprecations/class_test.rb +0 -119
- data/test-with-deprecations/coercion_test.rb +0 -52
- data/test-with-deprecations/config/inherit_test.rb +0 -135
- data/test-with-deprecations/config_test.rb +0 -122
- data/test-with-deprecations/decorator_scope_test.rb +0 -28
- data/test-with-deprecations/decorator_test.rb +0 -96
- data/test-with-deprecations/default_test.rb +0 -34
- data/test-with-deprecations/defaults_options_test.rb +0 -93
- data/test-with-deprecations/definition_test.rb +0 -264
- data/test-with-deprecations/example.rb +0 -310
- data/test-with-deprecations/examples/object.rb +0 -31
- data/test-with-deprecations/exec_context_test.rb +0 -93
- data/test-with-deprecations/features_test.rb +0 -70
- data/test-with-deprecations/filter_test.rb +0 -57
- data/test-with-deprecations/for_collection_test.rb +0 -74
- data/test-with-deprecations/generic_test.rb +0 -116
- data/test-with-deprecations/getter_setter_test.rb +0 -21
- data/test-with-deprecations/hash_bindings_test.rb +0 -87
- data/test-with-deprecations/hash_test.rb +0 -160
- data/test-with-deprecations/heritage_test.rb +0 -62
- data/test-with-deprecations/if_test.rb +0 -79
- data/test-with-deprecations/include_exclude_test.rb +0 -88
- data/test-with-deprecations/inherit_test.rb +0 -159
- data/test-with-deprecations/inline_test.rb +0 -272
- data/test-with-deprecations/instance_test.rb +0 -266
- data/test-with-deprecations/is_representable_test.rb +0 -77
- data/test-with-deprecations/json_test.rb +0 -355
- data/test-with-deprecations/lonely_test.rb +0 -239
- data/test-with-deprecations/mongoid_test.rb +0 -31
- data/test-with-deprecations/nested_test.rb +0 -115
- data/test-with-deprecations/object_test.rb +0 -60
- data/test-with-deprecations/parse_pipeline_test.rb +0 -64
- data/test-with-deprecations/parse_strategy_test.rb +0 -279
- data/test-with-deprecations/pass_options_test.rb +0 -27
- data/test-with-deprecations/pipeline_test.rb +0 -277
- data/test-with-deprecations/populator_test.rb +0 -105
- data/test-with-deprecations/prepare_test.rb +0 -67
- data/test-with-deprecations/private_options_test.rb +0 -18
- data/test-with-deprecations/reader_writer_test.rb +0 -19
- data/test-with-deprecations/realistic_benchmark.rb +0 -115
- data/test-with-deprecations/render_nil_test.rb +0 -21
- data/test-with-deprecations/represent_test.rb +0 -88
- data/test-with-deprecations/representable_test.rb +0 -511
- data/test-with-deprecations/schema_test.rb +0 -148
- data/test-with-deprecations/serialize_deserialize_test.rb +0 -33
- data/test-with-deprecations/skip_test.rb +0 -81
- data/test-with-deprecations/stringify_hash_test.rb +0 -41
- data/test-with-deprecations/test_helper.rb +0 -135
- data/test-with-deprecations/test_helper_test.rb +0 -25
- data/test-with-deprecations/uncategorized_test.rb +0 -67
- data/test-with-deprecations/user_options_test.rb +0 -15
- data/test-with-deprecations/wrap_test.rb +0 -152
- data/test-with-deprecations/xml_bindings_test.rb +0 -62
- data/test-with-deprecations/xml_test.rb +0 -503
- data/test-with-deprecations/yaml_test.rb +0 -162
- data/test/parse_strategy_test.rb +0 -279
@@ -1,67 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class StopWhenIncomingObjectFragmentIsNilTest < MiniTest::Spec
|
4
|
-
Album = Struct.new(:id, :songs)
|
5
|
-
Song = Struct.new(:title)
|
6
|
-
|
7
|
-
representer!(decorator: true) do
|
8
|
-
property :id
|
9
|
-
collection :songs, class: Song, parse_pipeline: ->(input, options) { # TODO: test if :doc is set for parsing. test if options are ok and contain :user_options!
|
10
|
-
Representable::Pipeline[*parse_functions.insert(3, Representable::StopOnNil)]
|
11
|
-
} do
|
12
|
-
property :title
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
it do
|
17
|
-
album = Album.new
|
18
|
-
representer.new(album).from_hash({"id"=>1, "songs"=>[{"title"=>"Walkie Talkie"}]}).songs.must_equal [Song.new("Walkie Talkie")]
|
19
|
-
end
|
20
|
-
|
21
|
-
it do
|
22
|
-
album = Album.new(2, ["original"])
|
23
|
-
representer.new(album).from_hash({"id"=>1, "songs"=>nil}).songs.must_equal ["original"]
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
class RenderPipelineOptionTest < MiniTest::Spec
|
29
|
-
Album = Struct.new(:id, :songs)
|
30
|
-
NilToNA = ->(input, options) { input.nil? ? "n/a" : input }
|
31
|
-
|
32
|
-
representer!(decorator: true) do
|
33
|
-
property :id, render_pipeline: ->(input, options) do
|
34
|
-
Representable::Pipeline[*render_functions.insert(2, options[:options][:user_options][:function])]
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
it { representer.new(Album.new).to_hash(function: NilToNA).must_equal({"id"=>"n/a"}) }
|
39
|
-
it { representer.new(Album.new(1)).to_hash(function: NilToNA).must_equal({"id"=>1}) }
|
40
|
-
|
41
|
-
it "is cached" do
|
42
|
-
decorator = representer.new(Album.new)
|
43
|
-
decorator.to_hash(function: NilToNA).must_equal({"id"=>"n/a"})
|
44
|
-
decorator.to_hash(function: nil).must_equal({"id"=>"n/a"}) # non-sense function is not applied.
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|
48
|
-
|
49
|
-
class ParsePipelineOptionTest < MiniTest::Spec
|
50
|
-
Album = Struct.new(:id, :songs)
|
51
|
-
NilToNA = ->(input, options) { input.nil? ? "n/a" : input }
|
52
|
-
|
53
|
-
representer!(decorator: true) do
|
54
|
-
property :id, parse_pipeline: ->(input, options) do
|
55
|
-
Representable::Pipeline[*parse_functions.insert(3, options[:options][:user_options][:function])].extend(Representable::Pipeline::Debug)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
it { representer.new(Album.new).from_hash({"id"=>nil}, function: NilToNA).id.must_equal "n/a" }
|
60
|
-
it { representer.new(Album.new(1)).to_hash(function: NilToNA).must_equal({"id"=>1}) }
|
61
|
-
|
62
|
-
it "is cached" do
|
63
|
-
decorator = representer.new(Album.new)
|
64
|
-
decorator.from_hash({"id"=>nil}, function: NilToNA).id.must_equal "n/a"
|
65
|
-
decorator.from_hash({"id"=>nil}, function: "nonsense").id.must_equal "n/a" # non-sense function is not applied.
|
66
|
-
end
|
67
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class UserOptionsTest < Minitest::Spec
|
4
|
-
Song = Struct.new(:title)
|
5
|
-
|
6
|
-
representer! do
|
7
|
-
property :title, if: ->(options) { options[:visible] }
|
8
|
-
end
|
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(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"}, visible: true).title.must_equal "Business Conduct" }
|
14
|
-
end
|
15
|
-
# Representable.deprecations=false
|
@@ -1,152 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
|
3
|
-
class WrapTest < MiniTest::Spec
|
4
|
-
class HardcoreBand
|
5
|
-
include Representable::Hash
|
6
|
-
end
|
7
|
-
|
8
|
-
class SoftcoreBand < HardcoreBand
|
9
|
-
end
|
10
|
-
|
11
|
-
let (:band) { HardcoreBand.new }
|
12
|
-
|
13
|
-
it "returns false per default" do
|
14
|
-
assert_equal nil, SoftcoreBand.new.send(:representation_wrap)
|
15
|
-
end
|
16
|
-
|
17
|
-
it "infers a printable class name if set to true" do
|
18
|
-
HardcoreBand.representation_wrap = true
|
19
|
-
assert_equal "hardcore_band", band.send(:representation_wrap)
|
20
|
-
end
|
21
|
-
|
22
|
-
it "can be set explicitely" do
|
23
|
-
HardcoreBand.representation_wrap = "breach"
|
24
|
-
assert_equal "breach", band.send(:representation_wrap)
|
25
|
-
end
|
26
|
-
|
27
|
-
for_formats(
|
28
|
-
:hash => [Representable::Hash, {"Blink182"=>{"genre"=>"Pop"}}, {"Blink182"=>{"genre"=>"Poppunk"}}],
|
29
|
-
:json => [Representable::JSON, "{\"Blink182\":{\"genre\":\"Pop\"}}", "{\"Blink182\":{\"genre\":\"Poppunk\"}}"],
|
30
|
-
:xml => [Representable::XML, "<Blink182><genre>Pop</genre></Blink182>", "<Blink182><genre>Poppunk</genre></Blink182>"],
|
31
|
-
# :yaml => [Representable::YAML, "---\nBlink182:\n"], # TODO: fix YAML.
|
32
|
-
) do |format, mod, output, input|
|
33
|
-
|
34
|
-
describe "[#{format}] dynamic wrap" do
|
35
|
-
let (:band) { representer.prepare(Struct.new(:name, :genre).new("Blink", "Pop")) }
|
36
|
-
let (:format) { format }
|
37
|
-
|
38
|
-
representer!(:module => mod) do
|
39
|
-
self.representation_wrap = lambda { |args| "#{name}#{args[:number]}" }
|
40
|
-
property :genre
|
41
|
-
end
|
42
|
-
|
43
|
-
it { render(band, {:number => 182}).must_equal_document(output) }
|
44
|
-
|
45
|
-
it { parse(band, input, {:number => 182}).genre.must_equal "Poppunk" } # TODO: better test. also, xml parses _any_ wrap.
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
|
51
|
-
class HashDisableWrapTest < MiniTest::Spec
|
52
|
-
Band = Struct.new(:name, :label)
|
53
|
-
Album = Struct.new(:band)
|
54
|
-
Label = Struct.new(:name)
|
55
|
-
|
56
|
-
class BandDecorator < Representable::Decorator
|
57
|
-
include Representable::Hash
|
58
|
-
|
59
|
-
self.representation_wrap = :bands
|
60
|
-
property :name
|
61
|
-
|
62
|
-
property :label do # this should have a wrap!
|
63
|
-
self.representation_wrap = :important
|
64
|
-
property :name
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
let (:band) { BandDecorator.prepare(Band.new("Social Distortion")) }
|
69
|
-
|
70
|
-
# direct, local api.
|
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"})
|
75
|
-
end
|
76
|
-
|
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"
|
81
|
-
end
|
82
|
-
|
83
|
-
|
84
|
-
class AlbumDecorator < Representable::Decorator
|
85
|
-
include Representable::Hash
|
86
|
-
|
87
|
-
self.representation_wrap = :albums
|
88
|
-
|
89
|
-
property :band, decorator: BandDecorator, wrap: false, class: Band
|
90
|
-
end
|
91
|
-
|
92
|
-
|
93
|
-
let (:album) { AlbumDecorator.prepare(Album.new(Band.new("Social Distortion", Label.new("Epitaph")))) }
|
94
|
-
|
95
|
-
# band has wrap turned off per property definition, however, label still has wrap.
|
96
|
-
it "renders" do
|
97
|
-
album.to_hash.must_equal({"albums" => {"band" => {"name"=>"Social Distortion", "label"=>{"important"=>{"name"=>"Epitaph"}}}}})
|
98
|
-
end
|
99
|
-
|
100
|
-
it "parses" do
|
101
|
-
album.from_hash({"albums" => {"band" => {"name"=>"Rvivr"}}}).band.name.must_equal "Rvivr"
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
|
106
|
-
class XMLDisableWrapTest < MiniTest::Spec
|
107
|
-
Band = Struct.new(:name, :label)
|
108
|
-
Album = Struct.new(:band)
|
109
|
-
Label = Struct.new(:name)
|
110
|
-
|
111
|
-
class BandDecorator < Representable::Decorator
|
112
|
-
include Representable::XML
|
113
|
-
|
114
|
-
self.representation_wrap = :bands # when nested, it uses this.
|
115
|
-
property :name
|
116
|
-
|
117
|
-
# property :label do # this should have a wrap!
|
118
|
-
# self.representation_wrap = :important
|
119
|
-
# property :name
|
120
|
-
# end
|
121
|
-
end
|
122
|
-
|
123
|
-
let (:band) { BandDecorator.prepare(Band.new("Social Distortion")) }
|
124
|
-
|
125
|
-
it do
|
126
|
-
band.to_xml.must_equal_xml "<bands><name>Social Distortion</name></bands>"
|
127
|
-
band.to_xml(wrap: "combo").must_equal_xml "<combo><name>Social Distortion</name></combo>"
|
128
|
-
end
|
129
|
-
|
130
|
-
|
131
|
-
class AlbumDecorator < Representable::Decorator
|
132
|
-
include Representable::XML
|
133
|
-
|
134
|
-
self.representation_wrap = :albums
|
135
|
-
|
136
|
-
property :band, decorator: BandDecorator, wrap: "po", class: Band
|
137
|
-
end
|
138
|
-
|
139
|
-
|
140
|
-
let (:album) { AlbumDecorator.prepare(Album.new(Band.new("Social Distortion", Label.new("Epitaph")))) }
|
141
|
-
|
142
|
-
# band has wrap turned of per property definition, however, label still has wrap.
|
143
|
-
it "rendersxx" do
|
144
|
-
skip
|
145
|
-
album.to_xml.must_equal({"albums" => {"band" => {"name"=>"Social Distortion", "label"=>{"important"=>{"name"=>"Epitaph"}}}}})
|
146
|
-
end
|
147
|
-
|
148
|
-
# it "parses" do
|
149
|
-
# album.from_hash({"albums" => {"band" => {"name"=>"Rvivr"}}}).band.name.must_equal "Rvivr"
|
150
|
-
# end
|
151
|
-
end
|
152
|
-
|
@@ -1,62 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
require 'representable/json' # FIXME.
|
3
|
-
require 'representable/xml/collection'
|
4
|
-
require 'representable/xml/hash'
|
5
|
-
|
6
|
-
require 'representable/xml'
|
7
|
-
|
8
|
-
class XMLBindingTest < MiniTest::Spec
|
9
|
-
module SongRepresenter
|
10
|
-
include Representable::XML
|
11
|
-
property :name
|
12
|
-
self.representation_wrap = :song
|
13
|
-
end
|
14
|
-
|
15
|
-
class SongWithRepresenter < ::Song
|
16
|
-
include Representable
|
17
|
-
include SongRepresenter
|
18
|
-
self.representation_wrap = :song
|
19
|
-
end
|
20
|
-
|
21
|
-
before do
|
22
|
-
@doc = Nokogiri::XML::Document.new
|
23
|
-
@song = SongWithRepresenter.new("Thinning the Herd")
|
24
|
-
end
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
describe "AttributeBinding" do
|
30
|
-
describe "with plain text items" do
|
31
|
-
before do
|
32
|
-
@property = Representable::XML::Binding::Attribute.new(Representable::Definition.new(:name, :attribute => true))
|
33
|
-
end
|
34
|
-
|
35
|
-
it "extracts with #read" do
|
36
|
-
assert_equal "The Gargoyle", @property.read(Nokogiri::XML("<song name=\"The Gargoyle\" />").root, "name")
|
37
|
-
end
|
38
|
-
|
39
|
-
it "inserts with #write" do
|
40
|
-
parent = Nokogiri::XML::Node.new("song", @doc)
|
41
|
-
@property.write(parent, "The Gargoyle", "name")
|
42
|
-
assert_xml_equal("<song name=\"The Gargoyle\" />", parent.to_s)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
describe "ContentBinding" do
|
48
|
-
before do
|
49
|
-
@property = Representable::XML::Binding::Content.new(Representable::Definition.new(:name, :content => true))
|
50
|
-
end
|
51
|
-
|
52
|
-
it "extracts with #read" do
|
53
|
-
assert_equal "The Gargoyle", @property.read(Nokogiri::XML("<song>The Gargoyle</song>").root, "song")
|
54
|
-
end
|
55
|
-
|
56
|
-
it "inserts with #write" do
|
57
|
-
parent = Nokogiri::XML::Node.new("song", @doc)
|
58
|
-
@property.write(parent, "The Gargoyle", "song")
|
59
|
-
assert_xml_equal("<song>The Gargoyle</song>", parent.to_s)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
@@ -1,503 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
require 'representable/xml'
|
3
|
-
|
4
|
-
class Band
|
5
|
-
include Representable::XML
|
6
|
-
property :name
|
7
|
-
attr_accessor :name
|
8
|
-
|
9
|
-
def initialize(name=nil)
|
10
|
-
name and self.name = name
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
class Album
|
15
|
-
attr_accessor :songs
|
16
|
-
end
|
17
|
-
|
18
|
-
|
19
|
-
class XmlTest < MiniTest::Spec
|
20
|
-
XML = Representable::XML
|
21
|
-
Def = Representable::Definition
|
22
|
-
|
23
|
-
describe "Xml module" do
|
24
|
-
before do
|
25
|
-
@Band = Class.new do
|
26
|
-
include Representable::XML
|
27
|
-
self.representation_wrap = :band
|
28
|
-
property :name
|
29
|
-
property :label
|
30
|
-
attr_accessor :name, :label
|
31
|
-
end
|
32
|
-
|
33
|
-
@band = @Band.new
|
34
|
-
end
|
35
|
-
|
36
|
-
|
37
|
-
describe "#from_xml" do
|
38
|
-
before do
|
39
|
-
@band = @Band.new
|
40
|
-
@xml = %{<band><name>Nofx</name><label>NOFX</label></band>}
|
41
|
-
end
|
42
|
-
|
43
|
-
it "parses XML and assigns properties" do
|
44
|
-
@band.from_xml(@xml)
|
45
|
-
assert_equal ["Nofx", "NOFX"], [@band.name, @band.label]
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
describe "#from_xml with remove_namespaces! and xmlns present" do
|
50
|
-
before do
|
51
|
-
@Band.remove_namespaces!
|
52
|
-
@band = @Band.new
|
53
|
-
@xml = %{<band xmlns="exists"><name>Nofx</name><label>NOFX</label></band>}
|
54
|
-
end
|
55
|
-
|
56
|
-
it "parses with xmlns present" do
|
57
|
-
@band.from_xml(@xml)
|
58
|
-
assert_equal ["Nofx", "NOFX"], [@band.name, @band.label]
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
describe "#from_node" do
|
63
|
-
before do
|
64
|
-
@band = @Band.new
|
65
|
-
@xml = Nokogiri::XML(%{<band><name>Nofx</name><label>NOFX</label></band>}).root
|
66
|
-
end
|
67
|
-
|
68
|
-
it "receives Nokogiri node and assigns properties" do
|
69
|
-
@band.from_node(@xml)
|
70
|
-
assert_equal ["Nofx", "NOFX"], [@band.name, @band.label]
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
|
75
|
-
describe "#to_xml" do
|
76
|
-
it "delegates to #to_node and returns string" do
|
77
|
-
assert_xml_equal "<band><name>Rise Against</name></band>", Band.new("Rise Against").to_xml
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
|
82
|
-
describe "#to_node" do
|
83
|
-
it "returns Nokogiri node" do
|
84
|
-
node = Band.new("Rise Against").to_node
|
85
|
-
assert_kind_of Nokogiri::XML::Element, node
|
86
|
-
end
|
87
|
-
|
88
|
-
it "wraps with infered class name per default" do
|
89
|
-
node = Band.new("Rise Against").to_node
|
90
|
-
assert_xml_equal "<band><name>Rise Against</name></band>", node.to_s
|
91
|
-
end
|
92
|
-
|
93
|
-
it "respects #representation_wrap=" do
|
94
|
-
klass = Class.new(Band) do
|
95
|
-
include Representable
|
96
|
-
property :name
|
97
|
-
end
|
98
|
-
|
99
|
-
klass.representation_wrap = :group
|
100
|
-
assert_xml_equal "<group><name>Rise Against</name></group>", klass.new("Rise Against").to_node.to_s
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
|
105
|
-
describe "XML::Binding#build_for" do
|
106
|
-
it "returns AttributeBinding" do
|
107
|
-
assert_kind_of XML::Binding::Attribute, XML::Binding.build_for(Def.new(:band, :as => "band", :attribute => true))
|
108
|
-
end
|
109
|
-
|
110
|
-
it "returns Binding" do
|
111
|
-
assert_kind_of XML::Binding, XML::Binding.build_for(Def.new(:band, :class => Hash))
|
112
|
-
assert_kind_of XML::Binding, XML::Binding.build_for(Def.new(:band, :as => :content))
|
113
|
-
end
|
114
|
-
|
115
|
-
it "returns CollectionBinding" do
|
116
|
-
assert_kind_of XML::Binding::Collection, XML::Binding.build_for(Def.new(:band, :collection => :true))
|
117
|
-
end
|
118
|
-
|
119
|
-
it "returns HashBinding" do
|
120
|
-
assert_kind_of XML::Binding::Hash, XML::Binding.build_for(Def.new(:band, :hash => :true))
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
|
125
|
-
describe "DCI" do
|
126
|
-
module SongRepresenter
|
127
|
-
include Representable::XML
|
128
|
-
property :name
|
129
|
-
representation_wrap = :song
|
130
|
-
end
|
131
|
-
|
132
|
-
module AlbumRepresenter
|
133
|
-
include Representable::XML
|
134
|
-
property :best_song, :class => Song, :extend => SongRepresenter
|
135
|
-
collection :songs, :class => Song, :as => :song, :extend => SongRepresenter
|
136
|
-
representation_wrap = :album
|
137
|
-
end
|
138
|
-
|
139
|
-
|
140
|
-
it "allows adding the representer by using #extend" do
|
141
|
-
module BandRepresenter
|
142
|
-
include Representable::XML
|
143
|
-
property :name
|
144
|
-
end
|
145
|
-
|
146
|
-
civ = Object.new
|
147
|
-
civ.instance_eval do
|
148
|
-
def name; "CIV"; end
|
149
|
-
def name=(v)
|
150
|
-
@name = v
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
civ.extend(BandRepresenter)
|
155
|
-
assert_xml_equal "<object><name>CIV</name></object>", civ.to_xml
|
156
|
-
end
|
157
|
-
|
158
|
-
it "extends contained models when serializing" do
|
159
|
-
@album = Album.new([Song.new("I Hate My Brain"), mr=Song.new("Mr. Charisma")], mr)
|
160
|
-
@album.extend(AlbumRepresenter)
|
161
|
-
|
162
|
-
assert_xml_equal "<album>
|
163
|
-
<song><name>Mr. Charisma</name></song>
|
164
|
-
<song><name>I Hate My Brain</name></song>
|
165
|
-
<song><name>Mr. Charisma</name></song>
|
166
|
-
</album>", @album.to_xml
|
167
|
-
end
|
168
|
-
|
169
|
-
it "extends contained models when deserializing" do
|
170
|
-
@album = Album.new
|
171
|
-
@album.extend(AlbumRepresenter)
|
172
|
-
|
173
|
-
@album.from_xml("<album><best_song><name>Mr. Charisma</name></best_song><song><name>I Hate My Brain</name></song><song><name>Mr. Charisma</name></song></album>")
|
174
|
-
assert_equal "Mr. Charisma", @album.best_song.name
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
|
181
|
-
class AttributesTest < MiniTest::Spec
|
182
|
-
describe ":as => rel, :attribute => true" do
|
183
|
-
class Link
|
184
|
-
include Representable::XML
|
185
|
-
property :href, :as => "href", :attribute => true
|
186
|
-
property :title, :as => "title", :attribute => true
|
187
|
-
attr_accessor :href, :title
|
188
|
-
end
|
189
|
-
|
190
|
-
it "#from_xml creates correct accessors" do
|
191
|
-
link = Link.new.from_xml(%{
|
192
|
-
<a href="http://apotomo.de" title="Home, sweet home" />
|
193
|
-
})
|
194
|
-
assert_equal "http://apotomo.de", link.href
|
195
|
-
assert_equal "Home, sweet home", link.title
|
196
|
-
end
|
197
|
-
|
198
|
-
it "#to_xml serializes correctly" do
|
199
|
-
link = Link.new
|
200
|
-
link.href = "http://apotomo.de/"
|
201
|
-
|
202
|
-
assert_xml_equal %{<link href="http://apotomo.de/">}, link.to_xml
|
203
|
-
end
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
|
-
|
208
|
-
class CDataBand
|
209
|
-
class CData < Representable::XML::Binding
|
210
|
-
def serialize_node(parent, value)
|
211
|
-
parent << Nokogiri::XML::CDATA.new(parent, represented.name)
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
include Representable::XML
|
216
|
-
property :name, :binding => lambda { |*args| CData.new(*args) }#getter: lambda { |opt| Nokogiri::XML::CDATA.new(opt[:doc], name) }
|
217
|
-
attr_accessor :name
|
218
|
-
|
219
|
-
def initialize(name=nil)
|
220
|
-
name and self.name = name
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
class TypedPropertyTest < MiniTest::Spec
|
225
|
-
module AlbumRepresenter
|
226
|
-
include Representable::XML
|
227
|
-
property :band, :class => Band
|
228
|
-
end
|
229
|
-
|
230
|
-
class Album
|
231
|
-
attr_accessor :band
|
232
|
-
def initialize(band=nil)
|
233
|
-
@band = band
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
# TODO:property :group, :class => Band
|
238
|
-
# :class
|
239
|
-
# where to mixin DCI?
|
240
|
-
describe ":class => Item" do
|
241
|
-
it "#from_xml creates one Item instance" do
|
242
|
-
album = Album.new.extend(AlbumRepresenter).from_xml(%{
|
243
|
-
<album>
|
244
|
-
<band><name>Bad Religion</name></band>
|
245
|
-
</album>
|
246
|
-
})
|
247
|
-
assert_equal "Bad Religion", album.band.name
|
248
|
-
end
|
249
|
-
|
250
|
-
describe "#to_xml" do
|
251
|
-
it "doesn't escape xml from Band#to_xml" do
|
252
|
-
band = Band.new("Bad Religion")
|
253
|
-
album = Album.new(band).extend(AlbumRepresenter)
|
254
|
-
|
255
|
-
assert_xml_equal %{<album>
|
256
|
-
<band>
|
257
|
-
<name>Bad Religion</name>
|
258
|
-
</band>
|
259
|
-
</album>}, album.to_xml
|
260
|
-
end
|
261
|
-
|
262
|
-
it "doesn't escape and wrap string from Band#to_node" do
|
263
|
-
band = Band.new("Bad Religion")
|
264
|
-
band.instance_eval do
|
265
|
-
def to_node(*)
|
266
|
-
"<band>Baaaad Religion</band>"
|
267
|
-
end
|
268
|
-
end
|
269
|
-
|
270
|
-
assert_xml_equal %{<album><band>Baaaad Religion</band></album>}, Album.new(band).extend(AlbumRepresenter).to_xml
|
271
|
-
end
|
272
|
-
end
|
273
|
-
|
274
|
-
describe "#to_xml with CDATA" do
|
275
|
-
it "wraps Band name in CDATA#to_xml" do
|
276
|
-
band = CDataBand.new("Bad Religion")
|
277
|
-
album = Album.new(band).extend(AlbumRepresenter)
|
278
|
-
|
279
|
-
assert_xml_equal %{<album>
|
280
|
-
<c_data_band>
|
281
|
-
<name><![CDATA[Bad Religion]]></name>
|
282
|
-
</c_data_band>
|
283
|
-
</album>}, album.to_xml
|
284
|
-
end
|
285
|
-
end
|
286
|
-
end
|
287
|
-
end
|
288
|
-
|
289
|
-
|
290
|
-
class CollectionTest < MiniTest::Spec
|
291
|
-
describe ":class => Band, :as => :band, :collection => true" do
|
292
|
-
class Compilation
|
293
|
-
include Representable::XML
|
294
|
-
collection :bands, :class => Band, :as => :band
|
295
|
-
attr_accessor :bands
|
296
|
-
end
|
297
|
-
|
298
|
-
describe "#from_xml" do
|
299
|
-
it "pushes collection items to array" do
|
300
|
-
cd = Compilation.new.from_xml(%{
|
301
|
-
<compilation>
|
302
|
-
<band><name>Diesel Boy</name></band>
|
303
|
-
<band><name>Cobra Skulls</name></band>
|
304
|
-
</compilation>
|
305
|
-
})
|
306
|
-
assert_equal ["Cobra Skulls", "Diesel Boy"], cd.bands.map(&:name).sort
|
307
|
-
end
|
308
|
-
end
|
309
|
-
|
310
|
-
it "responds to #to_xml" do
|
311
|
-
cd = Compilation.new
|
312
|
-
cd.bands = [Band.new("Diesel Boy"), Band.new("Bad Religion")]
|
313
|
-
|
314
|
-
assert_xml_equal %{<compilation>
|
315
|
-
<band><name>Diesel Boy</name></band>
|
316
|
-
<band><name>Bad Religion</name></band>
|
317
|
-
</compilation>}, cd.to_xml
|
318
|
-
end
|
319
|
-
end
|
320
|
-
|
321
|
-
|
322
|
-
describe ":as" do
|
323
|
-
let(:xml_doc) {
|
324
|
-
Module.new do
|
325
|
-
include Representable::XML
|
326
|
-
collection :songs, :as => :song
|
327
|
-
end }
|
328
|
-
|
329
|
-
it "collects untyped items" do
|
330
|
-
album = Album.new.extend(xml_doc).from_xml(%{
|
331
|
-
<album>
|
332
|
-
<song>Two Kevins</song>
|
333
|
-
<song>Wright and Rong</song>
|
334
|
-
<song>Laundry Basket</song>
|
335
|
-
</album>
|
336
|
-
})
|
337
|
-
assert_equal ["Laundry Basket", "Two Kevins", "Wright and Rong"].sort, album.songs.sort
|
338
|
-
end
|
339
|
-
end
|
340
|
-
|
341
|
-
|
342
|
-
describe ":wrap" do
|
343
|
-
let (:album) { Album.new.extend(xml_doc) }
|
344
|
-
let (:xml_doc) {
|
345
|
-
Module.new do
|
346
|
-
include Representable::XML
|
347
|
-
collection :songs, :as => :song, :wrap => :songs
|
348
|
-
end }
|
349
|
-
|
350
|
-
describe "#from_xml" do
|
351
|
-
it "finds items in wrapped collection" do
|
352
|
-
album.from_xml(%{
|
353
|
-
<album>
|
354
|
-
<songs>
|
355
|
-
<song>Two Kevins</song>
|
356
|
-
<song>Wright and Rong</song>
|
357
|
-
<song>Laundry Basket</song>
|
358
|
-
</songs>
|
359
|
-
</album>
|
360
|
-
})
|
361
|
-
assert_equal ["Laundry Basket", "Two Kevins", "Wright and Rong"].sort, album.songs.sort
|
362
|
-
end
|
363
|
-
end
|
364
|
-
|
365
|
-
describe "#to_xml" do
|
366
|
-
it "wraps items" do
|
367
|
-
album.songs = ["Laundry Basket", "Two Kevins", "Wright and Rong"]
|
368
|
-
assert_xml_equal %{
|
369
|
-
<album>
|
370
|
-
<songs>
|
371
|
-
<song>Laundry Basket</song>
|
372
|
-
<song>Two Kevins</song>
|
373
|
-
<song>Wright and Rong</song>
|
374
|
-
</songs>
|
375
|
-
</album>
|
376
|
-
}, album.to_xml
|
377
|
-
end
|
378
|
-
end
|
379
|
-
end
|
380
|
-
|
381
|
-
require 'representable/xml/hash'
|
382
|
-
class LonelyRepresenterTest < MiniTest::Spec
|
383
|
-
# TODO: where is the XML::Hash test?
|
384
|
-
module SongRepresenter
|
385
|
-
include Representable::XML
|
386
|
-
property :name
|
387
|
-
self.representation_wrap = :song
|
388
|
-
end
|
389
|
-
|
390
|
-
let (:decorator) { rpr = representer; Class.new(Representable::Decorator) { include Representable::XML; include rpr } }
|
391
|
-
|
392
|
-
describe "XML::Collection" do
|
393
|
-
describe "with contained objects" do
|
394
|
-
representer!(:module => Representable::XML::Collection) do
|
395
|
-
items :class => Song, :extend => SongRepresenter
|
396
|
-
self.representation_wrap= :songs
|
397
|
-
end
|
398
|
-
|
399
|
-
let (:songs) { [Song.new("Days Go By"), Song.new("Can't Take Them All")] }
|
400
|
-
let (:xml_doc) { "<songs><song><name>Days Go By</name></song><song><name>Can't Take Them All</name></song></songs>" }
|
401
|
-
|
402
|
-
it "renders array" do
|
403
|
-
songs.extend(representer).to_xml.must_equal_xml xml_doc
|
404
|
-
end
|
405
|
-
|
406
|
-
it "renders array with decorator" do
|
407
|
-
decorator.new(songs).to_xml.must_equal_xml xml_doc
|
408
|
-
end
|
409
|
-
|
410
|
-
it "parses array" do
|
411
|
-
[].extend(representer).from_xml(xml_doc).must_equal songs
|
412
|
-
end
|
413
|
-
|
414
|
-
it "parses array with decorator" do
|
415
|
-
decorator.new([]).from_xml(xml_doc).must_equal songs
|
416
|
-
end
|
417
|
-
end
|
418
|
-
end
|
419
|
-
|
420
|
-
describe "XML::AttributeHash" do # TODO: move to HashTest.
|
421
|
-
representer!(:module => Representable::XML::AttributeHash) do
|
422
|
-
self.representation_wrap= :songs
|
423
|
-
end
|
424
|
-
|
425
|
-
let (:songs) { {"one" => "Graveyards", "two" => "Can't Take Them All"} }
|
426
|
-
let (:xml_doc) { "<favs one=\"Graveyards\" two=\"Can't Take Them All\" />" }
|
427
|
-
|
428
|
-
describe "#to_xml" do
|
429
|
-
it "renders hash" do
|
430
|
-
songs.extend(representer).to_xml.must_equal_xml xml_doc
|
431
|
-
end
|
432
|
-
|
433
|
-
it "respects :exclude" do
|
434
|
-
assert_xml_equal "<favs two=\"Can't Take Them All\" />", songs.extend(representer).to_xml(:exclude => [:one])
|
435
|
-
end
|
436
|
-
|
437
|
-
it "respects :include" do
|
438
|
-
assert_xml_equal "<favs two=\"Can't Take Them All\" />", songs.extend(representer).to_xml(:include => [:two])
|
439
|
-
end
|
440
|
-
|
441
|
-
it "renders hash with decorator" do
|
442
|
-
decorator.new(songs).to_xml.must_equal_xml xml_doc
|
443
|
-
end
|
444
|
-
end
|
445
|
-
|
446
|
-
describe "#from_json" do
|
447
|
-
it "returns hash" do
|
448
|
-
{}.extend(representer).from_xml(xml_doc).must_equal songs
|
449
|
-
end
|
450
|
-
|
451
|
-
it "respects :exclude" do
|
452
|
-
assert_equal({"two" => "Can't Take Them All"}, {}.extend(representer).from_xml(xml_doc, :exclude => [:one]))
|
453
|
-
end
|
454
|
-
|
455
|
-
it "respects :include" do
|
456
|
-
assert_equal({"one" => "Graveyards"}, {}.extend(representer).from_xml(xml_doc, :include => [:one]))
|
457
|
-
end
|
458
|
-
|
459
|
-
it "parses hash with decorator" do
|
460
|
-
decorator.new({}).from_xml(xml_doc).must_equal songs
|
461
|
-
end
|
462
|
-
end
|
463
|
-
end
|
464
|
-
end
|
465
|
-
end
|
466
|
-
|
467
|
-
class XmlHashTest < MiniTest::Spec
|
468
|
-
# scalar, no object
|
469
|
-
describe "plain text" do
|
470
|
-
representer!(module: Representable::XML) do
|
471
|
-
hash :songs
|
472
|
-
end
|
473
|
-
|
474
|
-
let (:doc) { "<open_struct><first>The Gargoyle</first><second>Bronx</second></open_struct>" }
|
475
|
-
|
476
|
-
# to_xml
|
477
|
-
it { OpenStruct.new(songs: {"first" => "The Gargoyle", "second" => "Bronx"}).extend(representer).to_xml.must_equal_xml(doc) }
|
478
|
-
# FIXME: this NEVER worked!
|
479
|
-
# it { OpenStruct.new.extend(representer).from_xml(doc).songs.must_equal({"first" => "The Gargoyle", "second" => "Bronx"}) }
|
480
|
-
end
|
481
|
-
|
482
|
-
describe "with objects" do
|
483
|
-
representer!(module: Representable::XML) do
|
484
|
-
hash :songs, class: OpenStruct do
|
485
|
-
property :title
|
486
|
-
end
|
487
|
-
end
|
488
|
-
|
489
|
-
let (:doc) { "<open_struct>
|
490
|
-
<open_struct>
|
491
|
-
<title>The Gargoyle</title>
|
492
|
-
</open_struct>
|
493
|
-
<open_struct>
|
494
|
-
<title>Bronx</title>
|
495
|
-
</open_struct>
|
496
|
-
</open_struct>" }
|
497
|
-
|
498
|
-
# to_xml
|
499
|
-
it { OpenStruct.new(songs: {"first" => OpenStruct.new(title: "The Gargoyle"), "second" => OpenStruct.new(title: "Bronx")}).extend(representer).to_xml.must_equal_xml(doc) }
|
500
|
-
# FIXME: this NEVER worked!
|
501
|
-
# it { OpenStruct.new.extend(representer).from_xml(doc).songs.must_equal({"first" => "The Gargoyle", "second" => "Bronx"}) }
|
502
|
-
end
|
503
|
-
end
|