representable 2.4.1 → 3.0.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 +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
|