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.
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