representable 2.4.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +7 -12
  3. data/CHANGES.md +6 -27
  4. data/README.md +28 -1326
  5. data/lib/representable.rb +4 -14
  6. data/lib/representable/binding.rb +3 -7
  7. data/lib/representable/definition.rb +1 -2
  8. data/lib/representable/populator.rb +35 -0
  9. data/lib/representable/version.rb +1 -1
  10. data/test/definition_test.rb +0 -7
  11. data/test/exec_context_test.rb +2 -2
  12. data/test/instance_test.rb +0 -19
  13. data/test/realistic_benchmark.rb +0 -13
  14. data/test/representable_test.rb +0 -16
  15. data/test/skip_test.rb +1 -1
  16. data/test/test_helper.rb +0 -2
  17. metadata +3 -65
  18. data/lib/representable/deprecations.rb +0 -127
  19. data/lib/representable/parse_strategies.rb +0 -93
  20. data/test-with-deprecations/as_test.rb +0 -65
  21. data/test-with-deprecations/benchmarking.rb +0 -83
  22. data/test-with-deprecations/binding_test.rb +0 -46
  23. data/test-with-deprecations/blaaaaaaaa_test.rb +0 -69
  24. data/test-with-deprecations/cached_test.rb +0 -147
  25. data/test-with-deprecations/class_test.rb +0 -119
  26. data/test-with-deprecations/coercion_test.rb +0 -52
  27. data/test-with-deprecations/config/inherit_test.rb +0 -135
  28. data/test-with-deprecations/config_test.rb +0 -122
  29. data/test-with-deprecations/decorator_scope_test.rb +0 -28
  30. data/test-with-deprecations/decorator_test.rb +0 -96
  31. data/test-with-deprecations/default_test.rb +0 -34
  32. data/test-with-deprecations/defaults_options_test.rb +0 -93
  33. data/test-with-deprecations/definition_test.rb +0 -264
  34. data/test-with-deprecations/example.rb +0 -310
  35. data/test-with-deprecations/examples/object.rb +0 -31
  36. data/test-with-deprecations/exec_context_test.rb +0 -93
  37. data/test-with-deprecations/features_test.rb +0 -70
  38. data/test-with-deprecations/filter_test.rb +0 -57
  39. data/test-with-deprecations/for_collection_test.rb +0 -74
  40. data/test-with-deprecations/generic_test.rb +0 -116
  41. data/test-with-deprecations/getter_setter_test.rb +0 -21
  42. data/test-with-deprecations/hash_bindings_test.rb +0 -87
  43. data/test-with-deprecations/hash_test.rb +0 -160
  44. data/test-with-deprecations/heritage_test.rb +0 -62
  45. data/test-with-deprecations/if_test.rb +0 -79
  46. data/test-with-deprecations/include_exclude_test.rb +0 -88
  47. data/test-with-deprecations/inherit_test.rb +0 -159
  48. data/test-with-deprecations/inline_test.rb +0 -272
  49. data/test-with-deprecations/instance_test.rb +0 -266
  50. data/test-with-deprecations/is_representable_test.rb +0 -77
  51. data/test-with-deprecations/json_test.rb +0 -355
  52. data/test-with-deprecations/lonely_test.rb +0 -239
  53. data/test-with-deprecations/mongoid_test.rb +0 -31
  54. data/test-with-deprecations/nested_test.rb +0 -115
  55. data/test-with-deprecations/object_test.rb +0 -60
  56. data/test-with-deprecations/parse_pipeline_test.rb +0 -64
  57. data/test-with-deprecations/parse_strategy_test.rb +0 -279
  58. data/test-with-deprecations/pass_options_test.rb +0 -27
  59. data/test-with-deprecations/pipeline_test.rb +0 -277
  60. data/test-with-deprecations/populator_test.rb +0 -105
  61. data/test-with-deprecations/prepare_test.rb +0 -67
  62. data/test-with-deprecations/private_options_test.rb +0 -18
  63. data/test-with-deprecations/reader_writer_test.rb +0 -19
  64. data/test-with-deprecations/realistic_benchmark.rb +0 -115
  65. data/test-with-deprecations/render_nil_test.rb +0 -21
  66. data/test-with-deprecations/represent_test.rb +0 -88
  67. data/test-with-deprecations/representable_test.rb +0 -511
  68. data/test-with-deprecations/schema_test.rb +0 -148
  69. data/test-with-deprecations/serialize_deserialize_test.rb +0 -33
  70. data/test-with-deprecations/skip_test.rb +0 -81
  71. data/test-with-deprecations/stringify_hash_test.rb +0 -41
  72. data/test-with-deprecations/test_helper.rb +0 -135
  73. data/test-with-deprecations/test_helper_test.rb +0 -25
  74. data/test-with-deprecations/uncategorized_test.rb +0 -67
  75. data/test-with-deprecations/user_options_test.rb +0 -15
  76. data/test-with-deprecations/wrap_test.rb +0 -152
  77. data/test-with-deprecations/xml_bindings_test.rb +0 -62
  78. data/test-with-deprecations/xml_test.rb +0 -503
  79. data/test-with-deprecations/yaml_test.rb +0 -162
  80. 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