representable 2.4.0.rc3 → 2.4.0.rc4
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/CHANGES.md +7 -2
- data/Rakefile +6 -0
- data/lib/representable.rb +21 -17
- data/lib/representable/binding.rb +3 -2
- data/lib/representable/definition.rb +1 -1
- data/lib/representable/deprecations.rb +31 -5
- data/lib/representable/deserializer.rb +24 -34
- data/lib/representable/hash/collection.rb +9 -2
- data/lib/representable/hash_methods.rb +2 -2
- data/lib/representable/parse_strategies.rb +6 -7
- data/lib/representable/pipeline.rb +12 -1
- data/lib/representable/pipeline_factories.rb +9 -2
- data/lib/representable/serializer.rb +3 -3
- data/lib/representable/version.rb +1 -1
- data/test-with-deprecations/as_test.rb +65 -0
- data/test-with-deprecations/benchmarking.rb +83 -0
- data/test-with-deprecations/binding_test.rb +46 -0
- data/test-with-deprecations/blaaaaaaaa_test.rb +69 -0
- data/test-with-deprecations/cached_test.rb +147 -0
- data/test-with-deprecations/class_test.rb +119 -0
- data/test-with-deprecations/coercion_test.rb +52 -0
- data/test-with-deprecations/config/inherit_test.rb +135 -0
- data/test-with-deprecations/config_test.rb +122 -0
- data/test-with-deprecations/decorator_scope_test.rb +28 -0
- data/test-with-deprecations/decorator_test.rb +96 -0
- data/test-with-deprecations/default_test.rb +34 -0
- data/test-with-deprecations/defaults_options_test.rb +93 -0
- data/test-with-deprecations/definition_test.rb +264 -0
- data/test-with-deprecations/example.rb +310 -0
- data/test-with-deprecations/examples/object.rb +31 -0
- data/test-with-deprecations/exec_context_test.rb +93 -0
- data/test-with-deprecations/features_test.rb +70 -0
- data/test-with-deprecations/filter_test.rb +57 -0
- data/test-with-deprecations/for_collection_test.rb +74 -0
- data/test-with-deprecations/generic_test.rb +116 -0
- data/test-with-deprecations/getter_setter_test.rb +21 -0
- data/test-with-deprecations/hash_bindings_test.rb +87 -0
- data/test-with-deprecations/hash_test.rb +160 -0
- data/test-with-deprecations/heritage_test.rb +62 -0
- data/test-with-deprecations/if_test.rb +79 -0
- data/test-with-deprecations/include_exclude_test.rb +88 -0
- data/test-with-deprecations/inherit_test.rb +159 -0
- data/test-with-deprecations/inline_test.rb +272 -0
- data/test-with-deprecations/instance_test.rb +266 -0
- data/test-with-deprecations/is_representable_test.rb +77 -0
- data/test-with-deprecations/json_test.rb +355 -0
- data/test-with-deprecations/lonely_test.rb +239 -0
- data/test-with-deprecations/mongoid_test.rb +31 -0
- data/test-with-deprecations/nested_test.rb +115 -0
- data/test-with-deprecations/object_test.rb +60 -0
- data/{test/---deserialize-pipeline_test.rb → test-with-deprecations/parse_pipeline_test.rb} +29 -2
- data/test-with-deprecations/parse_strategy_test.rb +279 -0
- data/{test → test-with-deprecations}/pass_options_test.rb +0 -0
- data/test-with-deprecations/pipeline_test.rb +277 -0
- data/test-with-deprecations/populator_test.rb +105 -0
- data/test-with-deprecations/prepare_test.rb +67 -0
- data/test-with-deprecations/private_options_test.rb +18 -0
- data/test-with-deprecations/reader_writer_test.rb +19 -0
- data/test-with-deprecations/realistic_benchmark.rb +115 -0
- data/test-with-deprecations/render_nil_test.rb +21 -0
- data/test-with-deprecations/represent_test.rb +88 -0
- data/test-with-deprecations/representable_test.rb +511 -0
- data/test-with-deprecations/schema_test.rb +148 -0
- data/test-with-deprecations/serialize_deserialize_test.rb +33 -0
- data/test-with-deprecations/skip_test.rb +81 -0
- data/test-with-deprecations/stringify_hash_test.rb +41 -0
- data/test-with-deprecations/test_helper.rb +135 -0
- data/test-with-deprecations/test_helper_test.rb +25 -0
- data/test-with-deprecations/uncategorized_test.rb +67 -0
- data/test-with-deprecations/user_options_test.rb +15 -0
- data/test-with-deprecations/wrap_test.rb +152 -0
- data/test-with-deprecations/xml_bindings_test.rb +62 -0
- data/test-with-deprecations/xml_test.rb +503 -0
- data/test-with-deprecations/yaml_test.rb +162 -0
- data/test/as_test.rb +3 -3
- data/test/cached_test.rb +2 -2
- data/test/class_test.rb +5 -5
- data/test/exec_context_test.rb +2 -2
- data/test/filter_test.rb +1 -1
- data/test/getter_setter_test.rb +4 -4
- data/test/if_test.rb +2 -2
- data/test/include_exclude_test.rb +88 -0
- data/test/instance_test.rb +15 -15
- data/test/lonely_test.rb +18 -2
- data/test/object_test.rb +4 -4
- data/test/parse_pipeline_test.rb +64 -0
- data/test/parse_strategy_test.rb +3 -3
- data/test/pipeline_test.rb +8 -12
- data/test/prepare_test.rb +2 -3
- data/test/reader_writer_test.rb +3 -3
- data/test/representable_test.rb +12 -48
- data/test/serialize_deserialize_test.rb +9 -9
- data/test/skip_test.rb +11 -11
- data/test/test_helper.rb +2 -0
- data/test/uncategorized_test.rb +10 -10
- data/test/user_options_test.rb +15 -0
- data/test/wrap_test.rb +1 -1
- metadata +65 -4
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class GetterSetterTest < BaseTest
|
4
|
+
representer! do
|
5
|
+
property :name, # key under :name.
|
6
|
+
:getter => lambda { |args| "#{args[:welcome]} #{song_name}" },
|
7
|
+
:setter => lambda { |val, args| self.song_name = "#{args[:welcome]} #{val}" }
|
8
|
+
end
|
9
|
+
|
10
|
+
subject { Struct.new(:song_name).new("Mony Mony").extend(representer) }
|
11
|
+
|
12
|
+
it "uses :getter when rendering" do
|
13
|
+
subject.instance_eval { def name; raise; end }
|
14
|
+
subject.to_hash(:welcome => "Hi").must_equal({"name" => "Hi Mony Mony"})
|
15
|
+
end
|
16
|
+
|
17
|
+
it "uses :setter when parsing" do
|
18
|
+
subject.instance_eval { def name=(*); raise; end; self }
|
19
|
+
subject.from_hash({"name" => "Eyes Without A Face"}, :welcome => "Hello").song_name.must_equal "Hello Eyes Without A Face"
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class HashBindingTest < MiniTest::Spec
|
4
|
+
module SongRepresenter
|
5
|
+
include Representable::JSON
|
6
|
+
property :name
|
7
|
+
end
|
8
|
+
|
9
|
+
class SongWithRepresenter < ::Song
|
10
|
+
include Representable
|
11
|
+
include SongRepresenter
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
describe "PropertyBinding" do
|
16
|
+
describe "#read" do
|
17
|
+
before do
|
18
|
+
@property = Representable::Hash::Binding.new(Representable::Definition.new(:song))
|
19
|
+
end
|
20
|
+
|
21
|
+
it "returns fragment if present" do
|
22
|
+
assert_equal "Stick The Flag Up Your Goddamn Ass, You Sonofabitch", @property.read({"song" => "Stick The Flag Up Your Goddamn Ass, You Sonofabitch"}, "song")
|
23
|
+
assert_equal "", @property.read({"song" => ""}, "song")
|
24
|
+
assert_equal nil, @property.read({"song" => nil}, "song")
|
25
|
+
end
|
26
|
+
|
27
|
+
it "returns FRAGMENT_NOT_FOUND if not in document" do
|
28
|
+
assert_equal Representable::Binding::FragmentNotFound, @property.read({}, "song")
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
describe "CollectionBinding" do
|
36
|
+
describe "with plain text items" do
|
37
|
+
before do
|
38
|
+
@property = Representable::Hash::Binding::Collection.new(Representable::Definition.new(:songs, :collection => true))
|
39
|
+
end
|
40
|
+
|
41
|
+
it "extracts with #read" do
|
42
|
+
assert_equal ["The Gargoyle", "Bronx"], @property.read({"songs" => ["The Gargoyle", "Bronx"]}, "songs")
|
43
|
+
end
|
44
|
+
|
45
|
+
it "inserts with #write" do
|
46
|
+
doc = {}
|
47
|
+
assert_equal(["The Gargoyle", "Bronx"], @property.write(doc, ["The Gargoyle", "Bronx"], "songs"))
|
48
|
+
assert_equal({"songs"=>["The Gargoyle", "Bronx"]}, doc)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
describe "HashBinding" do
|
57
|
+
describe "with plain text items" do
|
58
|
+
before do
|
59
|
+
@property = Representable::Hash::Binding.new(Representable::Definition.new(:songs, :hash => true))
|
60
|
+
end
|
61
|
+
|
62
|
+
it "extracts with #read" do
|
63
|
+
assert_equal({"first" => "The Gargoyle", "second" => "Bronx"} , @property.read({"songs" => {"first" => "The Gargoyle", "second" => "Bronx"}}, "songs"))
|
64
|
+
end
|
65
|
+
|
66
|
+
it "inserts with #write" do
|
67
|
+
doc = {}
|
68
|
+
assert_equal({"first" => "The Gargoyle", "second" => "Bronx"}, @property.write(doc, {"first" => "The Gargoyle", "second" => "Bronx"}, "songs"))
|
69
|
+
assert_equal({"songs"=>{"first" => "The Gargoyle", "second" => "Bronx"}}, doc)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "with objects" do
|
74
|
+
before do
|
75
|
+
@property = Representable::Hash::Binding.new(Representable::Definition.new(:songs, :hash => true, :class => Song, :extend => SongRepresenter))
|
76
|
+
end
|
77
|
+
|
78
|
+
it "doesn't change the represented hash in #write" do
|
79
|
+
song = Song.new("Better Than That")
|
80
|
+
hash = {"first" => song}
|
81
|
+
@property.write({}, hash, "song")
|
82
|
+
assert_equal({"first" => song}, hash)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class HashWithScalarPropertyTest < MiniTest::Spec
|
4
|
+
Album = Struct.new(:title)
|
5
|
+
|
6
|
+
representer! do
|
7
|
+
property :title
|
8
|
+
end
|
9
|
+
|
10
|
+
let (:album) { Album.new("Liar") }
|
11
|
+
|
12
|
+
describe "#to_hash" do
|
13
|
+
it "renders plain property" do
|
14
|
+
album.extend(representer).to_hash.must_equal("title" => "Liar")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
describe "#from_hash" do
|
20
|
+
it "parses plain property" do
|
21
|
+
album.extend(representer).from_hash("title" => "This Song Is Recycled").title.must_equal "This Song Is Recycled"
|
22
|
+
end
|
23
|
+
|
24
|
+
# Fixes issue #115
|
25
|
+
it "allows nil value in the incoming document and corresponding nil value for the represented" do
|
26
|
+
album = Album.new
|
27
|
+
album.title.must_equal nil
|
28
|
+
album.extend(representer).from_hash("title" => nil)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
class HashWithTypedPropertyTest < MiniTest::Spec
|
35
|
+
Album = Struct.new(:best_song)
|
36
|
+
|
37
|
+
representer! do
|
38
|
+
property :best_song, :class => Song do
|
39
|
+
property :name
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
let (:album) { Album.new(Song.new("Liar")) }
|
44
|
+
|
45
|
+
describe "#to_hash" do
|
46
|
+
it "renders embedded typed property" do
|
47
|
+
album.extend(representer).to_hash.must_equal("best_song" => {"name" => "Liar"})
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "#from_hash" do
|
52
|
+
it "parses embedded typed property" do
|
53
|
+
album.extend(representer).from_hash("best_song" => {"name" => "Go With Me"})
|
54
|
+
album.best_song.name.must_equal "Go With Me"
|
55
|
+
end
|
56
|
+
|
57
|
+
# nested nil removes nested object.
|
58
|
+
it do
|
59
|
+
album = Album.new(Song.new("Pre-medicated Murder"))
|
60
|
+
album.extend(representer).from_hash("best_song" => nil)
|
61
|
+
album.best_song.must_equal nil
|
62
|
+
end
|
63
|
+
|
64
|
+
# nested blank hash creates blank object when not populated.
|
65
|
+
it do
|
66
|
+
album = Album.new#(Song.new("Pre-medicated Murder"))
|
67
|
+
album.extend(representer).from_hash("best_song" => {})
|
68
|
+
album.best_song.name.must_equal nil
|
69
|
+
end
|
70
|
+
|
71
|
+
# Fixes issue #115
|
72
|
+
it "allows nil value in the incoming document and corresponding nil value for the represented" do
|
73
|
+
album = Album.new
|
74
|
+
album.extend(representer).from_hash("best_song" => nil)
|
75
|
+
album.best_song.must_equal nil
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# TODO: move to AsTest.
|
81
|
+
class HashWithTypedPropertyAndAs < MiniTest::Spec
|
82
|
+
representer! do
|
83
|
+
property :song, :class => Song, :as => :hit do
|
84
|
+
property :name
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
let (:album) { OpenStruct.new(:song => Song.new("Liar")).extend(representer) }
|
89
|
+
|
90
|
+
it { album.to_hash.must_equal("hit" => {"name" => "Liar"}) }
|
91
|
+
it { album.from_hash("hit" => {"name" => "Go With Me"}).must_equal OpenStruct.new(:song => Song.new("Go With Me")) }
|
92
|
+
end
|
93
|
+
# # describe "FIXME COMBINE WITH ABOVE with :extend and :as" do
|
94
|
+
# # hash_song = Module.new do
|
95
|
+
# # include Representable::XML
|
96
|
+
# # self.representation_wrap = :song
|
97
|
+
# # property :name
|
98
|
+
# # end
|
99
|
+
|
100
|
+
# # let (:hash_album) { Module.new do
|
101
|
+
# # include Representable::XML
|
102
|
+
# # self.representation_wrap = :album
|
103
|
+
# # property :song, :extend => hash_song, :class => Song, :as => :hit
|
104
|
+
# # end }
|
105
|
+
|
106
|
+
# # let (:album) { OpenStruct.new(:song => Song.new("Liar")).extend(hash_album) }
|
107
|
+
|
108
|
+
# # it { album.to_xml.must_equal_xml("<album><hit><name>Liar</name></hit></album>") }
|
109
|
+
# # #it { album.from_hash("hit" => {"name" => "Go With Me"}).must_equal OpenStruct.new(:song => Song.new("Go With Me")) }
|
110
|
+
# # end
|
111
|
+
# end
|
112
|
+
|
113
|
+
|
114
|
+
|
115
|
+
class HashWithTypedCollectionTest < MiniTest::Spec
|
116
|
+
Album = Struct.new(:songs)
|
117
|
+
|
118
|
+
representer! do
|
119
|
+
collection :songs, class: Song do
|
120
|
+
property :name
|
121
|
+
property :track
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
let (:album) { Album.new([Song.new("Liar", 1), Song.new("What I Know", 2)]) }
|
126
|
+
|
127
|
+
describe "#to_hash" do
|
128
|
+
it "renders collection of typed property" do
|
129
|
+
album.extend(representer).to_hash.must_equal("songs" => [{"name" => "Liar", "track" => 1}, {"name" => "What I Know", "track" => 2}])
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe "#from_hash" do
|
134
|
+
it "parses collection of typed property" do
|
135
|
+
album.extend(representer).from_hash("songs" => [{"name" => "One Shot Deal", "track" => 4},
|
136
|
+
{"name" => "Three Way Dance", "track" => 5}]).must_equal Album.new([Song.new("One Shot Deal", 4), Song.new("Three Way Dance", 5)])
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
class HashWithScalarCollectionTest < MiniTest::Spec
|
142
|
+
Album = Struct.new(:songs)
|
143
|
+
representer! { collection :songs }
|
144
|
+
|
145
|
+
let (:album) { Album.new(["Jackhammer", "Terrible Man"]) }
|
146
|
+
|
147
|
+
|
148
|
+
describe "#to_hash" do
|
149
|
+
it "renders a block style list per default" do
|
150
|
+
album.extend(representer).to_hash.must_equal("songs" => ["Jackhammer", "Terrible Man"])
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
describe "#from_hash" do
|
156
|
+
it "parses a block style list" do
|
157
|
+
album.extend(representer).from_hash("songs" => ["Off Key Melody", "Sinking"]).must_equal Album.new(["Off Key Melody", "Sinking"])
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class HeritageTest < Minitest::Spec
|
4
|
+
module Hello
|
5
|
+
def hello
|
6
|
+
puts "Hello!"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
module Ciao
|
10
|
+
def ciao
|
11
|
+
puts "Ciao!"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
class A < Representable::Decorator
|
17
|
+
include Representable::Hash
|
18
|
+
|
19
|
+
feature Hello
|
20
|
+
|
21
|
+
property :id do
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class B < A
|
26
|
+
feature Ciao # does NOT extend id, of course.
|
27
|
+
|
28
|
+
property :id, inherit: true do
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class C < A
|
34
|
+
property :id do end # overwrite old :id.
|
35
|
+
end
|
36
|
+
|
37
|
+
it do
|
38
|
+
# puts A.heritage.inspect
|
39
|
+
# puts B.heritage.inspect
|
40
|
+
|
41
|
+
puts B.representable_attrs.get(:id)[:extend].(nil).new(nil).hello
|
42
|
+
puts B.representable_attrs.get(:id)[:extend].(nil).new(nil).ciao
|
43
|
+
|
44
|
+
# feature Hello must be "inherited" from A and included in new C properties, too.
|
45
|
+
puts C.representable_attrs.get(:id)[:extend].(nil).new(nil).hello
|
46
|
+
end
|
47
|
+
|
48
|
+
module M
|
49
|
+
include Representable
|
50
|
+
feature Hello
|
51
|
+
end
|
52
|
+
|
53
|
+
module N
|
54
|
+
include Representable
|
55
|
+
include M
|
56
|
+
feature Ciao
|
57
|
+
end
|
58
|
+
|
59
|
+
it do
|
60
|
+
Object.new.extend(N).hello
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class IfTest < MiniTest::Spec
|
4
|
+
let (:band_class) { Class.new do
|
5
|
+
include Representable::Hash
|
6
|
+
attr_accessor :fame
|
7
|
+
self
|
8
|
+
end }
|
9
|
+
|
10
|
+
it "respects property when condition true" do
|
11
|
+
band_class.class_eval { property :fame, :if => lambda { |*| true } }
|
12
|
+
band = band_class.new
|
13
|
+
band.from_hash({"fame"=>"oh yes"})
|
14
|
+
assert_equal "oh yes", band.fame
|
15
|
+
end
|
16
|
+
|
17
|
+
it "ignores property when condition false" do
|
18
|
+
band_class.class_eval { property :fame, :if => lambda { |*| false } }
|
19
|
+
band = band_class.new
|
20
|
+
band.from_hash({"fame"=>"oh yes"})
|
21
|
+
assert_equal nil, band.fame
|
22
|
+
end
|
23
|
+
|
24
|
+
it "ignores property when :exclude'ed even when condition is true" do
|
25
|
+
band_class.class_eval { property :fame, :if => lambda { |*| true } }
|
26
|
+
band = band_class.new
|
27
|
+
band.from_hash({"fame"=>"oh yes"}, {:exclude => [:fame]})
|
28
|
+
assert_equal nil, band.fame
|
29
|
+
end
|
30
|
+
|
31
|
+
it "executes block in instance context" do
|
32
|
+
band_class.class_eval { property :fame, :if => lambda { |*| groupies }; attr_accessor :groupies }
|
33
|
+
band = band_class.new
|
34
|
+
band.groupies = true
|
35
|
+
band.from_hash({"fame"=>"oh yes"})
|
36
|
+
assert_equal "oh yes", band.fame
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "executing :if lambda in represented instance context" do
|
40
|
+
representer! do
|
41
|
+
property :label, :if => lambda { |*| signed_contract }
|
42
|
+
end
|
43
|
+
|
44
|
+
subject { OpenStruct.new(:signed_contract => false, :label => "Fat") }
|
45
|
+
|
46
|
+
it "skips when false" do
|
47
|
+
subject.extend(representer).to_hash.must_equal({})
|
48
|
+
end
|
49
|
+
|
50
|
+
it "represents when true" do
|
51
|
+
subject.signed_contract= true
|
52
|
+
subject.extend(representer).to_hash.must_equal({"label"=>"Fat"})
|
53
|
+
end
|
54
|
+
|
55
|
+
it "works with decorator" do
|
56
|
+
rpr = representer
|
57
|
+
Class.new(Representable::Decorator) do
|
58
|
+
include Representable::Hash
|
59
|
+
include rpr
|
60
|
+
end.new(subject).to_hash.must_equal({})
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
describe "propagating user options to the block" do
|
66
|
+
representer! do
|
67
|
+
property :name, :if => lambda { |opts| opts[:include_name] }
|
68
|
+
end
|
69
|
+
subject { OpenStruct.new(:name => "Outbound").extend(representer) }
|
70
|
+
|
71
|
+
it "works without specifying options" do
|
72
|
+
subject.to_hash.must_equal({})
|
73
|
+
end
|
74
|
+
|
75
|
+
it "passes user options to block" do
|
76
|
+
subject.to_hash(:include_name => true).must_equal({"name" => "Outbound"})
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class IncludeExcludeTest < Minitest::Spec
|
4
|
+
Song = Struct.new(:title, :artist, :id)
|
5
|
+
Artist = Struct.new(:name, :id, :songs)
|
6
|
+
|
7
|
+
representer!(decorator: true) do
|
8
|
+
property :title
|
9
|
+
property :artist, class: Artist do
|
10
|
+
property :name
|
11
|
+
property :id
|
12
|
+
|
13
|
+
collection :songs, class: Song do
|
14
|
+
property :title
|
15
|
+
property :id
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
let (:song) { Song.new("Listless", Artist.new("7yearsbadluck", 1 )) }
|
21
|
+
let (:decorator) { representer.new(song) }
|
22
|
+
|
23
|
+
describe "#from_hash" do
|
24
|
+
it "accepts :exclude option" do
|
25
|
+
decorator.from_hash({"title"=>"Don't Smile In Trouble", "artist"=>{"id"=>2}}, exclude: [:title])
|
26
|
+
|
27
|
+
song.title.must_equal "Listless"
|
28
|
+
song.artist.must_equal Artist.new(nil, 2)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "accepts :include option" do
|
32
|
+
decorator.from_hash({"title"=>"Don't Smile In Trouble", "artist"=>{"id"=>2}}, include: [:title])
|
33
|
+
|
34
|
+
song.title.must_equal "Don't Smile In Trouble"
|
35
|
+
song.artist.must_equal Artist.new("7yearsbadluck", 1)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "accepts nested :exclude/:include option" do
|
39
|
+
decorator.from_hash({"title"=>"Don't Smile In Trouble", "artist"=>{"name"=>"Foo", "id"=>2, "songs"=>[{"id"=>1, "title"=>"Listless"}]}},
|
40
|
+
exclude: [:title],
|
41
|
+
artist: {
|
42
|
+
exclude: [:id],
|
43
|
+
songs: { include: [:title] }
|
44
|
+
}
|
45
|
+
)
|
46
|
+
|
47
|
+
song.title.must_equal "Listless"
|
48
|
+
song.artist.must_equal Artist.new("Foo", nil, [Song.new("Listless", nil, nil)])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#to_hash" do
|
53
|
+
it "accepts :exclude option" do
|
54
|
+
decorator.to_hash(exclude: [:title]).must_equal({"artist"=>{"name"=>"7yearsbadluck", "id"=>1}})
|
55
|
+
end
|
56
|
+
|
57
|
+
it "accepts :include option" do
|
58
|
+
decorator.to_hash(include: [:title]).must_equal({"title"=>"Listless"})
|
59
|
+
end
|
60
|
+
|
61
|
+
it "accepts nested :exclude/:include option" do
|
62
|
+
decorator = representer.new(Song.new("Listless", Artist.new("7yearsbadluck", 1, [Song.new("C.O.A.B.I.E.T.L.")])))
|
63
|
+
|
64
|
+
decorator.to_hash(
|
65
|
+
exclude: [:title],
|
66
|
+
artist: {
|
67
|
+
exclude: [:id],
|
68
|
+
songs: { include: [:title] }
|
69
|
+
}
|
70
|
+
).must_equal({"artist"=>{"name"=>"7yearsbadluck", "songs"=>[{"title"=>"C.O.A.B.I.E.T.L."}]}})
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it "xdoes not propagate private options to nested objects" do
|
75
|
+
Cover = Struct.new(:title, :original)
|
76
|
+
|
77
|
+
cover_rpr = Module.new do
|
78
|
+
include Representable::Hash
|
79
|
+
property :title
|
80
|
+
property :original, extend: self
|
81
|
+
end
|
82
|
+
|
83
|
+
# FIXME: we should test all representable-options (:include, :exclude, ?)
|
84
|
+
|
85
|
+
Cover.new("Roxanne", Cover.new("Roxanne (Don't Put On The Red Light)")).extend(cover_rpr).
|
86
|
+
to_hash(:include => [:original]).must_equal({"original"=>{"title"=>"Roxanne (Don't Put On The Red Light)"}})
|
87
|
+
end
|
88
|
+
end
|