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,62 +0,0 @@
|
|
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
|
@@ -1,79 +0,0 @@
|
|
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
|
@@ -1,88 +0,0 @@
|
|
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
|
@@ -1,159 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
class InheritTest < MiniTest::Spec
|
4
|
-
module SongRepresenter # it's important to have a global module so we can test if stuff gets overridden in the original module.
|
5
|
-
include Representable::Hash
|
6
|
-
property :name, :as => :title do
|
7
|
-
property :string, :as => :str
|
8
|
-
end
|
9
|
-
|
10
|
-
property :track, :as => :no
|
11
|
-
end
|
12
|
-
|
13
|
-
let (:song) { Song.new(Struct.new(:string).new("Roxanne"), 1) }
|
14
|
-
|
15
|
-
describe ":inherit plain property" do
|
16
|
-
representer! do
|
17
|
-
include SongRepresenter
|
18
|
-
|
19
|
-
property :track, :inherit => true, :getter => lambda { |*| "n/a" }
|
20
|
-
end
|
21
|
-
|
22
|
-
it { SongRepresenter.prepare(song).to_hash.must_equal({"title"=>{"str"=>"Roxanne"}, "no"=>1}) }
|
23
|
-
it { representer.prepare(song).to_hash.must_equal({"title"=>{"str"=>"Roxanne"}, "no"=>"n/a"}) } # as: inherited.
|
24
|
-
end
|
25
|
-
|
26
|
-
describe ":inherit with empty inline representer" do
|
27
|
-
representer! do
|
28
|
-
include SongRepresenter
|
29
|
-
|
30
|
-
property :name, :inherit => true do # inherit as: title
|
31
|
-
# that doesn't make sense.
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
it { SongRepresenter.prepare(Song.new(Struct.new(:string).new("Believe It"), 1)).to_hash.must_equal({"title"=>{"str"=>"Believe It"}, "no"=>1}) }
|
36
|
-
# the block doesn't override the inline representer.
|
37
|
-
it { representer.prepare( Song.new(Struct.new(:string).new("Believe It"), 1)).to_hash.must_equal({"title"=>{"str"=>"Believe It"}, "no"=>1}) }
|
38
|
-
end
|
39
|
-
|
40
|
-
describe ":inherit with overriding inline representer" do
|
41
|
-
representer! do
|
42
|
-
include SongRepresenter
|
43
|
-
|
44
|
-
puts "passing block"
|
45
|
-
property :name, :inherit => true do # inherit as: title
|
46
|
-
property :string, :as => :s
|
47
|
-
property :length
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
it { representer.prepare( Song.new(Struct.new(:string, :length).new("Believe It", 10), 1)).to_hash.must_equal({"title"=>{"s"=>"Believe It","length"=>10}, "no"=>1}) }
|
52
|
-
end
|
53
|
-
|
54
|
-
describe ":inherit with empty inline and options" do
|
55
|
-
representer! do
|
56
|
-
include SongRepresenter
|
57
|
-
|
58
|
-
property :name, inherit: true, as: :name do # inherit module, only.
|
59
|
-
# that doesn't make sense. but it should simply inherit the old nested properties.
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
it { SongRepresenter.prepare(Song.new(Struct.new(:string).new("Believe It"), 1)).to_hash.must_equal({"title"=>{"str"=>"Believe It"}, "no"=>1}) }
|
64
|
-
it { representer.prepare( Song.new(Struct.new(:string).new("Believe It"), 1)).to_hash.must_equal({"name"=>{"str"=>"Believe It"}, "no"=>1}) }
|
65
|
-
end
|
66
|
-
|
67
|
-
describe ":inherit with inline without block but options" do
|
68
|
-
representer! do
|
69
|
-
include SongRepresenter
|
70
|
-
|
71
|
-
property :name, :inherit => true, :as => :name # FIXME: add :getter or something else dynamic since this is double-wrapped.
|
72
|
-
end
|
73
|
-
|
74
|
-
it { SongRepresenter.prepare(Song.new(Struct.new(:string).new("Believe It"), 1)).to_hash.must_equal({"title"=>{"str"=>"Believe It"}, "no"=>1}) }
|
75
|
-
it { representer.prepare( Song.new(Struct.new(:string).new("Believe It"), 1)).to_hash.must_equal({"name"=>{"str"=>"Believe It"}, "no"=>1}) }
|
76
|
-
end
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
# no :inherit
|
81
|
-
describe "overwriting without :inherit" do
|
82
|
-
representer! do
|
83
|
-
include SongRepresenter
|
84
|
-
|
85
|
-
property :track, :representable => true
|
86
|
-
end
|
87
|
-
|
88
|
-
it "replaces inherited property" do
|
89
|
-
representer.representable_attrs.size.must_equal 2
|
90
|
-
|
91
|
-
definition = representer.representable_attrs.get(:track) # TODO: find a better way to assert Definition identity.
|
92
|
-
# definition.keys.size.must_equal 2
|
93
|
-
definition[:representable]. must_equal true
|
94
|
-
definition.name.must_equal "track" # was "no".
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
|
99
|
-
# decorator
|
100
|
-
describe ":inherit with decorator" do
|
101
|
-
representer!(:decorator => true) do
|
102
|
-
property :hit do
|
103
|
-
property :title, exec_context: :decorator
|
104
|
-
|
105
|
-
def title
|
106
|
-
"Cheap Transistor Radio"
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
let (:inheriting) {
|
112
|
-
class InheritingDecorator < representer
|
113
|
-
include Representable::Debug
|
114
|
-
property :hit, :inherit => true do
|
115
|
-
include Representable::Debug
|
116
|
-
property :length
|
117
|
-
end
|
118
|
-
self
|
119
|
-
end
|
120
|
-
}
|
121
|
-
|
122
|
-
it { representer.new(OpenStruct.new(hit: OpenStruct.new(title: "I WILL BE OVERRIDDEN", :length => "2:59"))).to_hash.must_equal(
|
123
|
-
{"hit"=>{"title"=>"Cheap Transistor Radio"}}) }
|
124
|
-
|
125
|
-
# inheriting decorator inherits inline representer class (InlineRepresenter#title).
|
126
|
-
# inheriting decorator adds :length.
|
127
|
-
it { inheriting.new(OpenStruct.new(:hit => OpenStruct.new(:title => "Hole In Your Soul", :length => "2:59"))).to_hash.must_equal(
|
128
|
-
{"hit"=>{"title"=>"Cheap Transistor Radio", "length"=>"2:59"}}) }
|
129
|
-
end
|
130
|
-
|
131
|
-
|
132
|
-
# :inherit when property doesn't exist, yet.
|
133
|
-
describe ":inherit without inheritable property" do
|
134
|
-
representer! do
|
135
|
-
property :name, :inherit => true
|
136
|
-
end
|
137
|
-
|
138
|
-
it { representer.prepare(Song.new("The Beginning")).to_hash.must_equal({"name"=>"The Beginning"})}
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
|
143
|
-
# class InheritancingTest < MiniTest::Spec
|
144
|
-
# class SongDecorator < Representable::Decorator
|
145
|
-
# include Representable::Hash
|
146
|
-
# property :album do
|
147
|
-
# # does have Hash.
|
148
|
-
# property :title
|
149
|
-
# end
|
150
|
-
# end
|
151
|
-
|
152
|
-
# class JsonSongDecorator < SongDecorator
|
153
|
-
# include Representable::XML
|
154
|
-
# end
|
155
|
-
|
156
|
-
# it do
|
157
|
-
# puts JsonSongDecorator.new(OpenStruct.new(:album => OpenStruct.new(:title => "Erotic Cakes", :tracks => nil))).to_xml
|
158
|
-
# end
|
159
|
-
# end
|
@@ -1,272 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
class InlineTest < MiniTest::Spec
|
4
|
-
let (:song) { Song.new("Alive") }
|
5
|
-
let (:request) { representer.prepare(OpenStruct.new(:song => song)) }
|
6
|
-
|
7
|
-
{
|
8
|
-
:hash => [Representable::Hash, {"song"=>{"name"=>"Alive"}}, {"song"=>{"name"=>"You've Taken Everything"}}],
|
9
|
-
:json => [Representable::JSON, "{\"song\":{\"name\":\"Alive\"}}", "{\"song\":{\"name\":\"You've Taken Everything\"}}"],
|
10
|
-
:xml => [Representable::XML, "<open_struct>\n <song>\n <name>Alive</name>\n </song>\n</open_struct>", "<open_struct><song><name>You've Taken Everything</name></song>/open_struct>"],
|
11
|
-
:yaml => [Representable::YAML, "---\nsong:\n name: Alive\n", "---\nsong:\n name: You've Taken Everything\n"],
|
12
|
-
}.each do |format, cfg|
|
13
|
-
mod, output, input = cfg
|
14
|
-
|
15
|
-
describe "[#{format}] with :class" do
|
16
|
-
representer!(:module => mod) do
|
17
|
-
property :song, :class => Song do
|
18
|
-
property :name
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
let (:format) { format }
|
23
|
-
|
24
|
-
it { render(request).must_equal_document output }
|
25
|
-
it { parse(request, input).song.name.must_equal "You've Taken Everything"}
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
{
|
30
|
-
:hash => [Representable::Hash, {"songs"=>[{"name"=>"Alive"}]}, {"songs"=>[{"name"=>"You've Taken Everything"}]}],
|
31
|
-
:json => [Representable::JSON, "{\"songs\":[{\"name\":\"Alive\"}]}", "{\"songs\":[{\"name\":\"You've Taken Everything\"}]}"],
|
32
|
-
:xml => [Representable::XML, "<open_struct>\n <song>\n <name>Alive</name>\n </song>\n</open_struct>", "<open_struct><song><name>You've Taken Everything</name></song></open_struct>", { :as => :song }],
|
33
|
-
:yaml => [Representable::YAML, "---\nsongs:\n- name: Alive\n", "---\nsongs:\n- name: You've Taken Everything\n"],
|
34
|
-
}.each do |format, cfg|
|
35
|
-
mod, output, input, collection_options = cfg
|
36
|
-
collection_options ||= {}
|
37
|
-
|
38
|
-
describe "[#{format}] collection with :class" do
|
39
|
-
let (:request) { representer.prepare(OpenStruct.new(:songs => [song])) }
|
40
|
-
|
41
|
-
representer!(:module => mod) do
|
42
|
-
collection :songs, collection_options.merge(:class => Song) do
|
43
|
-
property :name
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
let (:format) { format } # FIXME: why do we have to define this?
|
48
|
-
|
49
|
-
it { render(request).must_equal_document output }
|
50
|
-
it { parse(request, input).songs.first.name.must_equal "You've Taken Everything"}
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
describe "without :class" do
|
55
|
-
representer! do
|
56
|
-
property :song do
|
57
|
-
property :name
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
it { request.to_hash.must_equal({"song"=>{"name"=>"Alive"}}) }
|
62
|
-
end
|
63
|
-
|
64
|
-
|
65
|
-
for_formats(
|
66
|
-
:hash => [Representable::Hash, {}],
|
67
|
-
# :xml => [Representable::XML, "<open_struct>\n <song>\n <name>Alive</name>\n </song>\n</open_struct>", "<open_struct><song><name>You've Taken Everything</name></song>/open_struct>"],
|
68
|
-
# :yaml => [Representable::YAML, "---\nsong:\n name: Alive\n", "---\nsong:\n name: You've Taken Everything\n"],
|
69
|
-
) do |format, mod, input|
|
70
|
-
|
71
|
-
describe "parsing [#{format}] where nested property missing" do
|
72
|
-
representer!(:module => mod) do
|
73
|
-
property :song do
|
74
|
-
property :name
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
it "doesn't change represented object" do
|
79
|
-
request.send("from_#{format}", input).song.must_equal song
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
|
85
|
-
describe "inheriting from outer representer" do
|
86
|
-
let (:request) { Struct.new(:song, :requester).new(song, "Josephine") }
|
87
|
-
|
88
|
-
[false, true].each do |is_decorator| # test for module and decorator.
|
89
|
-
representer!(:decorator => is_decorator) do
|
90
|
-
property :requester
|
91
|
-
|
92
|
-
property :song, :class => Song do
|
93
|
-
property :name
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
let (:decorator) { representer.prepare(request) }
|
98
|
-
|
99
|
-
it { decorator.to_hash.must_equal({"requester"=>"Josephine", "song"=>{"name"=>"Alive"}}) }
|
100
|
-
it { decorator.from_hash({"song"=>{"name"=>"You've Taken Everything"}}).song.name.must_equal "You've Taken Everything"}
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
describe "object pollution" do
|
105
|
-
representer!(:decorator => true) do
|
106
|
-
property :song do
|
107
|
-
property :name
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
it "uses an inline decorator and doesn't alter represented" do
|
112
|
-
representer.prepare(Struct.new(:song).new(song)).to_hash
|
113
|
-
song.wont_be_kind_of Representable
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
# TODO: should be in extend:/decorator: test.
|
118
|
-
# FIXME: this tests :getter{represented}+:extend - represented gets extended twice and the inline decorator overrides original config.
|
119
|
-
# for_formats(
|
120
|
-
# :hash => [Representable::Hash, {"album" => {"artist" => {"label"=>"Epitaph"}}}],
|
121
|
-
# # :xml => [Representable::XML, "<open_struct></open_struct>"],
|
122
|
-
# #:yaml => [Representable::YAML, "---\nlabel:\n label: Epitaph\n owner: Brett Gurewitz\n"]
|
123
|
-
# ) do |format, mod, output, input|
|
124
|
-
|
125
|
-
# module ArtistRepresenter
|
126
|
-
# include Representable::JSON
|
127
|
-
# property :label
|
128
|
-
# end
|
129
|
-
|
130
|
-
# describe ":getter with inline representer" do
|
131
|
-
# let (:format) { format }
|
132
|
-
|
133
|
-
# representer!(:module => mod) do
|
134
|
-
# self.representation_wrap = :album
|
135
|
-
|
136
|
-
# property :artist, :getter => lambda { |args| represented }, :extend => ArtistRepresenter
|
137
|
-
# end
|
138
|
-
|
139
|
-
# let (:album) { OpenStruct.new(:label => "Epitaph").extend(representer) }
|
140
|
-
|
141
|
-
# it "renders nested Album-properties in separate section" do
|
142
|
-
# render(album).must_equal_document output
|
143
|
-
# end
|
144
|
-
# end
|
145
|
-
# end
|
146
|
-
|
147
|
-
|
148
|
-
for_formats({
|
149
|
-
:hash => [Representable::Hash, {"album" => {"artist" => {"label"=>"Epitaph"}}}],
|
150
|
-
# :xml => [Representable::XML, "<open_struct></open_struct>"],
|
151
|
-
#:yaml => [Representable::YAML, "---\nlabel:\n label: Epitaph\n owner: Brett Gurewitz\n"]
|
152
|
-
}) do |format, mod, output, input|
|
153
|
-
|
154
|
-
class ArtistDecorator < Representable::Decorator
|
155
|
-
include Representable::JSON
|
156
|
-
property :label
|
157
|
-
end
|
158
|
-
|
159
|
-
describe ":getter with :decorator" do
|
160
|
-
let (:format) { format }
|
161
|
-
|
162
|
-
representer!(:module => mod) do
|
163
|
-
self.representation_wrap = "album"
|
164
|
-
|
165
|
-
property :artist, :getter => lambda { |args| represented }, :decorator => ArtistDecorator
|
166
|
-
end
|
167
|
-
|
168
|
-
let (:album) { OpenStruct.new(:label => "Epitaph").extend(representer) }
|
169
|
-
|
170
|
-
it "renders nested Album-properties in separate section" do
|
171
|
-
render(album).must_equal_document output
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
|
177
|
-
# test helper methods within inline representer
|
178
|
-
for_formats({
|
179
|
-
:hash => [Representable::Hash, {"song"=>{"name"=>"ALIVE"}}],
|
180
|
-
:xml => [Representable::XML, "<request>\n <song>\n <name>ALIVE</name>\n </song>\n</request>"],
|
181
|
-
:yaml => [Representable::YAML, "---\nsong:\n name: ALIVE\n"],
|
182
|
-
}) do |format, mod, output|
|
183
|
-
|
184
|
-
describe "helper method within inline representer [#{format}]" do
|
185
|
-
let (:format) { format }
|
186
|
-
|
187
|
-
representer!(:module => mod, :decorator => true) do
|
188
|
-
self.representation_wrap = :request if format == :xml
|
189
|
-
|
190
|
-
property :requester
|
191
|
-
property :song do
|
192
|
-
property :name, :exec_context => :decorator
|
193
|
-
|
194
|
-
define_method :name do
|
195
|
-
represented.name.upcase
|
196
|
-
end
|
197
|
-
|
198
|
-
self.representation_wrap = :song if format == :xml
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
let (:request) { representer.prepare(OpenStruct.new(:song => Song.new("Alive"))) }
|
203
|
-
|
204
|
-
it do
|
205
|
-
render(request).must_equal_document output
|
206
|
-
end
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
|
211
|
-
describe "include module in inline representers" do
|
212
|
-
representer! do
|
213
|
-
extension = Module.new do
|
214
|
-
include Representable::Hash
|
215
|
-
property :title
|
216
|
-
end
|
217
|
-
|
218
|
-
property :song do
|
219
|
-
include extension
|
220
|
-
property :artist
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
it do OpenStruct.new(:song => OpenStruct.new(:title => "The Fever And The Sound", :artist => "Strung Out")).extend(representer).
|
225
|
-
to_hash.
|
226
|
-
must_equal({"song"=>{"artist"=>"Strung Out", "title"=>"The Fever And The Sound"}})
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
|
231
|
-
# define method in inline representer
|
232
|
-
describe "define method in inline representer" do
|
233
|
-
Mod = Module.new do
|
234
|
-
include Representable::Hash
|
235
|
-
|
236
|
-
def song
|
237
|
-
"Object.new"
|
238
|
-
end
|
239
|
-
|
240
|
-
property :song do
|
241
|
-
property :duration
|
242
|
-
|
243
|
-
def duration
|
244
|
-
"6:53"
|
245
|
-
end
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
it { Object.new.extend(Mod).to_hash.must_equal("song"=>{"duration"=>"6:53"}) }
|
250
|
-
end
|
251
|
-
|
252
|
-
# define method inline with Decorator
|
253
|
-
describe "define method inline with Decorator" do
|
254
|
-
dec = Class.new(Representable::Decorator) do
|
255
|
-
include Representable::Hash
|
256
|
-
|
257
|
-
def song
|
258
|
-
"Object.new"
|
259
|
-
end
|
260
|
-
|
261
|
-
property :song, :exec_context => :decorator do
|
262
|
-
property :duration, :exec_context => :decorator
|
263
|
-
|
264
|
-
def duration
|
265
|
-
"6:53"
|
266
|
-
end
|
267
|
-
end
|
268
|
-
end
|
269
|
-
|
270
|
-
it { dec.new(Object.new).to_hash.must_equal("song"=>{"duration"=>"6:53"}) }
|
271
|
-
end
|
272
|
-
end
|