representable 1.7.7 → 1.8.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/CHANGES.md +42 -8
- data/README.md +208 -55
- data/Rakefile +0 -6
- data/lib/representable.rb +39 -43
- data/lib/representable/binding.rb +59 -37
- data/lib/representable/bindings/hash_bindings.rb +3 -4
- data/lib/representable/bindings/xml_bindings.rb +10 -10
- data/lib/representable/bindings/yaml_bindings.rb +2 -2
- data/lib/representable/coercion.rb +1 -1
- data/lib/representable/config.rb +11 -5
- data/lib/representable/definition.rb +67 -35
- data/lib/representable/deserializer.rb +23 -27
- data/lib/representable/hash.rb +15 -4
- data/lib/representable/hash/allow_symbols.rb +27 -0
- data/lib/representable/json.rb +0 -1
- data/lib/representable/json/collection.rb +0 -2
- data/lib/representable/mapper.rb +6 -13
- data/lib/representable/parse_strategies.rb +57 -0
- data/lib/representable/readable_writeable.rb +29 -0
- data/lib/representable/serializer.rb +9 -4
- data/lib/representable/version.rb +1 -1
- data/lib/representable/xml.rb +1 -1
- data/lib/representable/xml/collection.rb +0 -2
- data/lib/representable/yaml.rb +0 -1
- data/representable.gemspec +1 -0
- data/test/as_test.rb +43 -0
- data/test/class_test.rb +124 -0
- data/test/config_test.rb +13 -3
- data/test/decorator_scope_test.rb +28 -0
- data/test/definition_test.rb +46 -35
- data/test/exec_context_test.rb +93 -0
- data/test/generic_test.rb +0 -154
- data/test/getter_setter_test.rb +28 -0
- data/test/hash_bindings_test.rb +35 -35
- data/test/hash_test.rb +0 -20
- data/test/if_test.rb +78 -0
- data/test/inherit_test.rb +21 -1
- data/test/inheritance_test.rb +1 -1
- data/test/inline_test.rb +40 -2
- data/test/instance_test.rb +286 -0
- data/test/is_representable_test.rb +77 -0
- data/test/json_test.rb +6 -29
- data/test/nested_test.rb +30 -0
- data/test/parse_strategy_test.rb +249 -0
- data/test/pass_options_test.rb +27 -0
- data/test/prepare_test.rb +67 -0
- data/test/reader_writer_test.rb +19 -0
- data/test/representable_test.rb +25 -265
- data/test/stringify_hash_test.rb +41 -0
- data/test/test_helper.rb +12 -4
- data/test/wrap_test.rb +48 -0
- data/test/xml_bindings_test.rb +37 -37
- data/test/xml_test.rb +14 -14
- metadata +94 -30
- data/lib/representable/deprecations.rb +0 -4
- data/lib/representable/feature/readable_writeable.rb +0 -30
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class IsRepresentableTest < BaseTest
|
4
|
+
describe "representable: false, extend:" do
|
5
|
+
representer!(:inject => :song_representer) do
|
6
|
+
property :song,
|
7
|
+
:representable => false,
|
8
|
+
:extend => song_representer
|
9
|
+
end
|
10
|
+
|
11
|
+
it "does extend but doesn't call #to_hash" do
|
12
|
+
Struct.new(:song).new(song = Object.new).extend(representer).
|
13
|
+
to_hash.must_equal("song" => song)
|
14
|
+
song.must_be_kind_of Representable::Hash
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
describe "representable: true, no extend:" do
|
20
|
+
representer!(:inject => :song_representer) do
|
21
|
+
property :song,
|
22
|
+
:representable => true
|
23
|
+
end
|
24
|
+
|
25
|
+
it "doesn't extend but calls #to_hash" do
|
26
|
+
song = Object.new
|
27
|
+
song.instance_eval do
|
28
|
+
def to_hash(*)
|
29
|
+
1
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
Struct.new(:song).new(song).extend(representer).
|
34
|
+
to_hash.must_equal("song" => 1)
|
35
|
+
song.wont_be_kind_of Representable::Hash
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# TODO: TEST implement for from_hash.
|
40
|
+
|
41
|
+
describe "representable: false, with class:" do
|
42
|
+
representer!(:inject => :song_representer) do
|
43
|
+
property :song,
|
44
|
+
:representable => false, :class => OpenStruct, :extend => song_representer
|
45
|
+
end
|
46
|
+
|
47
|
+
it "does extend but doesn't call #from_hash" do
|
48
|
+
hit = Struct.new(:song).new.extend(representer).
|
49
|
+
from_hash("song" => 1)
|
50
|
+
|
51
|
+
hit.song.must_equal OpenStruct.new
|
52
|
+
hit.song.must_be_kind_of Representable::Hash
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
describe "representable: true, without extend: but class:" do
|
58
|
+
SongReader = Class.new do
|
59
|
+
def from_hash(*)
|
60
|
+
"Piano?"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
representer!(:inject => :song_representer) do
|
65
|
+
property :song,
|
66
|
+
:representable => true, :class => SongReader
|
67
|
+
end
|
68
|
+
|
69
|
+
it "doesn't extend but calls #from_hash" do
|
70
|
+
hit = Struct.new(:song).new.extend(representer).
|
71
|
+
from_hash("song" => "Sonata No.2")
|
72
|
+
|
73
|
+
hit.song.must_equal "Piano?"
|
74
|
+
hit.song.wont_be_kind_of Representable::Hash
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
data/test/json_test.rb
CHANGED
@@ -109,11 +109,6 @@ module JsonTest
|
|
109
109
|
assert_equal({"name"=>"Rise Against"}, hash)
|
110
110
|
end
|
111
111
|
|
112
|
-
it "respects #representation_wrap=" do
|
113
|
-
@Band.representation_wrap = :group
|
114
|
-
assert_equal({:group=>{"name"=>"Rise Against"}}, @Band.new("Rise Against").to_hash)
|
115
|
-
end
|
116
|
-
|
117
112
|
it "respects :wrap option" do
|
118
113
|
assert_equal({:band=>{"name"=>"NOFX"}}, @Band.new("NOFX").to_hash(:wrap => :band))
|
119
114
|
end
|
@@ -128,15 +123,15 @@ module JsonTest
|
|
128
123
|
|
129
124
|
describe "#build_for" do
|
130
125
|
it "returns TextBinding" do
|
131
|
-
assert_kind_of Representable::Hash::PropertyBinding, Representable::Hash::PropertyBinding.build_for(Def.new(:band), nil)
|
126
|
+
assert_kind_of Representable::Hash::PropertyBinding, Representable::Hash::PropertyBinding.build_for(Def.new(:band), nil, nil)
|
132
127
|
end
|
133
128
|
|
134
129
|
it "returns HashBinding" do
|
135
|
-
assert_kind_of Representable::Hash::HashBinding, Representable::Hash::PropertyBinding.build_for(Def.new(:band, :hash => true), nil)
|
130
|
+
assert_kind_of Representable::Hash::HashBinding, Representable::Hash::PropertyBinding.build_for(Def.new(:band, :hash => true), nil, nil)
|
136
131
|
end
|
137
132
|
|
138
133
|
it "returns CollectionBinding" do
|
139
|
-
assert_kind_of Representable::Hash::CollectionBinding, Representable::Hash::PropertyBinding.build_for(Def.new(:band, :collection => true), nil)
|
134
|
+
assert_kind_of Representable::Hash::CollectionBinding, Representable::Hash::PropertyBinding.build_for(Def.new(:band, :collection => true), nil, nil)
|
140
135
|
end
|
141
136
|
end
|
142
137
|
|
@@ -264,24 +259,6 @@ module JsonTest
|
|
264
259
|
end
|
265
260
|
end
|
266
261
|
|
267
|
-
describe ":from => :songName" do
|
268
|
-
class Song
|
269
|
-
include Representable::JSON
|
270
|
-
property :name, :from => :songName
|
271
|
-
attr_accessor :name
|
272
|
-
end
|
273
|
-
|
274
|
-
it "respects :from in #from_json" do
|
275
|
-
song = Song.from_json({:songName => "Run To The Hills"}.to_json)
|
276
|
-
assert_equal "Run To The Hills", song.name
|
277
|
-
end
|
278
|
-
|
279
|
-
it "respects :from in #to_json" do
|
280
|
-
song = Song.new; song.name = "Run To The Hills"
|
281
|
-
assert_json '{"songName":"Run To The Hills"}', song.to_json
|
282
|
-
end
|
283
|
-
end
|
284
|
-
|
285
262
|
describe ":as => :songName" do
|
286
263
|
class Song
|
287
264
|
include Representable::JSON
|
@@ -403,14 +380,14 @@ end
|
|
403
380
|
end
|
404
381
|
|
405
382
|
|
406
|
-
describe ":
|
383
|
+
describe ":as => :songList" do
|
407
384
|
class Songs
|
408
385
|
include Representable::JSON
|
409
|
-
collection :tracks, :
|
386
|
+
collection :tracks, :as => :songList
|
410
387
|
attr_accessor :tracks
|
411
388
|
end
|
412
389
|
|
413
|
-
it "respects :
|
390
|
+
it "respects :as in #from_json" do
|
414
391
|
songs = Songs.from_json({:songList => ["Out in the cold", "Microphone"]}.to_json)
|
415
392
|
assert_equal ["Out in the cold", "Microphone"], songs.tracks
|
416
393
|
end
|
data/test/nested_test.rb
CHANGED
@@ -76,4 +76,34 @@ class NestedTest < MiniTest::Spec
|
|
76
76
|
end
|
77
77
|
end
|
78
78
|
end
|
79
|
+
|
80
|
+
|
81
|
+
describe "::nested without block but with inherit:" do
|
82
|
+
|
83
|
+
representer!(:name => :parent) do
|
84
|
+
include Representable::Hash
|
85
|
+
|
86
|
+
nested :label do
|
87
|
+
property :owner
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
representer!(:module => Representable::Hash, :inject => :parent) do
|
92
|
+
include parent
|
93
|
+
nested :label, :inherit => true, :as => "Label"
|
94
|
+
end
|
95
|
+
|
96
|
+
let (:album) { representer.prepare(Album.new("Epitaph", "Brett Gurewitz", 19)) }
|
97
|
+
|
98
|
+
it "renders nested Album-properties in separate section" do
|
99
|
+
representer.prepare(album).to_hash.must_equal({"Label"=>{"owner"=>"Brett Gurewitz"}})
|
100
|
+
end
|
101
|
+
|
102
|
+
# it "parses nested properties to Album instance" do
|
103
|
+
# album = parse(representer.prepare(Album.new), output)
|
104
|
+
# album.label.must_equal "Epitaph"
|
105
|
+
# album.owner.must_equal "Brett Gurewitz"
|
106
|
+
# album.amount.must_equal 19
|
107
|
+
# end
|
108
|
+
end
|
79
109
|
end
|
@@ -0,0 +1,249 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
# parse_strategy: :sync
|
4
|
+
# parse_strategy: :replace
|
5
|
+
# parse_strategy: :find_or_instantiate ("expand" since we don't delete existing unmatched in target)
|
6
|
+
|
7
|
+
|
8
|
+
class ParseStrategySyncTest < BaseTest
|
9
|
+
for_formats(
|
10
|
+
:hash => [Representable::Hash, {"song"=>{"title"=>"Resist Stance"}}, {"song"=>{"title"=>"Suffer"}}],
|
11
|
+
:xml => [Representable::XML, "<open_struct><song><title>Resist Stance</title></song></open_struct>", "<open_struct><song><title>Suffer</title></song></open_struct>",],
|
12
|
+
:yaml => [Representable::YAML, "---\nsong:\n title: Resist Stance\n", "---\nsong:\n title: Suffer\n"],
|
13
|
+
) do |format, mod, output, input|
|
14
|
+
|
15
|
+
describe "[#{format}] property with parse_strategy: :sync" do # TODO: introduce :representable option?
|
16
|
+
let (:format) { format }
|
17
|
+
|
18
|
+
representer!(:module => mod, :name => :song_representer) do
|
19
|
+
property :title
|
20
|
+
self.representation_wrap = :song if format == :xml
|
21
|
+
end
|
22
|
+
|
23
|
+
representer!(:inject => :song_representer, :module => mod) do
|
24
|
+
property :song, :parse_strategy => :sync, :extend => song_representer
|
25
|
+
end
|
26
|
+
|
27
|
+
let (:hit) { hit = OpenStruct.new(:song => song).extend(representer) }
|
28
|
+
|
29
|
+
it "calls #to_hash on song instance, nothing else" do
|
30
|
+
render(hit).must_equal_document(output)
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
it "calls #from_hash on the existing song instance, nothing else" do
|
35
|
+
song_id = hit.song.object_id
|
36
|
+
|
37
|
+
parse(hit, input)
|
38
|
+
|
39
|
+
hit.song.title.must_equal "Suffer"
|
40
|
+
hit.song.object_id.must_equal song_id
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# FIXME: there's a bug with XML and the collection name!
|
46
|
+
for_formats(
|
47
|
+
:hash => [Representable::Hash, {"songs"=>[{"title"=>"Resist Stance"}]}, {"songs"=>[{"title"=>"Suffer"}]}],
|
48
|
+
#:json => [Representable::JSON, "{\"song\":{\"name\":\"Alive\"}}", "{\"song\":{\"name\":\"You've Taken Everything\"}}"],
|
49
|
+
:xml => [Representable::XML, "<open_struct><song><title>Resist Stance</title></song></open_struct>", "<open_struct><songs><title>Suffer</title></songs></open_struct>"],
|
50
|
+
:yaml => [Representable::YAML, "---\nsongs:\n- title: Resist Stance\n", "---\nsongs:\n- title: Suffer\n"],
|
51
|
+
) do |format, mod, output, input|
|
52
|
+
|
53
|
+
describe "[#{format}] collection with :parse_strategy: :sync" do # TODO: introduce :representable option?
|
54
|
+
let (:format) { format }
|
55
|
+
representer!(:module => mod, :name => :song_representer) do
|
56
|
+
property :title
|
57
|
+
self.representation_wrap = :song if format == :xml
|
58
|
+
end
|
59
|
+
|
60
|
+
representer!(:inject => :song_representer, :module => mod) do
|
61
|
+
collection :songs, :parse_strategy => :sync, :extend => song_representer
|
62
|
+
end
|
63
|
+
|
64
|
+
let (:album) { OpenStruct.new(:songs => [song]).extend(representer) }
|
65
|
+
|
66
|
+
it "calls #to_hash on song instances, nothing else" do
|
67
|
+
render(album).must_equal_document(output)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "calls #from_hash on the existing song instance, nothing else" do
|
71
|
+
collection_id = album.songs.object_id
|
72
|
+
song = album.songs.first
|
73
|
+
song_id = song.object_id
|
74
|
+
|
75
|
+
parse(album, input)
|
76
|
+
|
77
|
+
album.songs.first.title.must_equal "Suffer"
|
78
|
+
song.title.must_equal "Suffer"
|
79
|
+
#album.songs.object_id.must_equal collection_id # TODO: don't replace!
|
80
|
+
song.object_id.must_equal song_id
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
# Lonely Collection
|
87
|
+
for_formats(
|
88
|
+
:hash => [Representable::Hash::Collection, [{"title"=>"Resist Stance"}], [{"title"=>"Suffer"}]],
|
89
|
+
# :xml => [Representable::XML, "<open_struct><song><title>Resist Stance</title></song></open_struct>", "<open_struct><songs><title>Suffer</title></songs></open_struct>"],
|
90
|
+
) do |format, mod, output, input|
|
91
|
+
|
92
|
+
describe "[#{format}] lonely collection with :parse_strategy: :sync" do # TODO: introduce :representable option?
|
93
|
+
let (:format) { format }
|
94
|
+
representer!(:module => Representable::Hash, :name => :song_representer) do
|
95
|
+
property :title
|
96
|
+
self.representation_wrap = :song if format == :xml
|
97
|
+
end
|
98
|
+
|
99
|
+
representer!(:inject => :song_representer, :module => mod) do
|
100
|
+
items :parse_strategy => :sync, :extend => song_representer
|
101
|
+
end
|
102
|
+
|
103
|
+
let (:album) { [song].extend(representer) }
|
104
|
+
|
105
|
+
it "calls #to_hash on song instances, nothing else" do
|
106
|
+
render(album).must_equal_document(output)
|
107
|
+
end
|
108
|
+
|
109
|
+
it "calls #from_hash on the existing song instance, nothing else" do
|
110
|
+
#collection_id = album.object_id
|
111
|
+
song = album.first
|
112
|
+
song_id = song.object_id
|
113
|
+
|
114
|
+
parse(album, input)
|
115
|
+
|
116
|
+
album.first.title.must_equal "Suffer"
|
117
|
+
song.title.must_equal "Suffer"
|
118
|
+
song.object_id.must_equal song_id
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
class ParseStrategyFindOrInstantiateTest < BaseTest
|
126
|
+
# parse_strategy: :find_or_instantiate
|
127
|
+
|
128
|
+
Song = Struct.new(:id, :title)
|
129
|
+
Song.class_eval do
|
130
|
+
def self.find(id)
|
131
|
+
return new(1, "Resist Stan") if id==1# we should return the same object here
|
132
|
+
new
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
representer!(:name => :song_representer) do
|
137
|
+
property :title
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
describe "collection" do
|
142
|
+
representer!(:inject => :song_representer) do
|
143
|
+
collection :songs, :parse_strategy => :find_or_instantiate, :extend => song_representer, :class => Song
|
144
|
+
end
|
145
|
+
|
146
|
+
let (:album) { Struct.new(:songs).new([]).extend(representer) }
|
147
|
+
|
148
|
+
|
149
|
+
it "replaces the existing collection with a new consisting of existing items or new items" do
|
150
|
+
songs_id = album.songs.object_id
|
151
|
+
|
152
|
+
album.from_hash({"songs"=>[{"id" => 1, "title"=>"Resist Stance"}, {"title"=>"Suffer"}]})
|
153
|
+
|
154
|
+
album.songs[0].title.must_equal "Resist Stance" # note how title is updated from "Resist Stan"
|
155
|
+
album.songs[0].id.must_equal 1
|
156
|
+
album.songs[1].title.must_equal "Suffer"
|
157
|
+
album.songs[1].id.must_equal nil
|
158
|
+
|
159
|
+
album.songs.object_id.wont_equal songs_id
|
160
|
+
end
|
161
|
+
|
162
|
+
# TODO: test with existing collection
|
163
|
+
end
|
164
|
+
|
165
|
+
|
166
|
+
describe "property" do
|
167
|
+
representer!(:inject => :song_representer) do
|
168
|
+
property :song, :parse_strategy => :find_or_instantiate, :extend => song_representer, :class => Song
|
169
|
+
end
|
170
|
+
|
171
|
+
let (:album) { Struct.new(:song).new.extend(representer) }
|
172
|
+
|
173
|
+
|
174
|
+
it "finds song by id" do
|
175
|
+
album.from_hash({"song"=>{"id" => 1, "title"=>"Resist Stance"}})
|
176
|
+
|
177
|
+
album.song.title.must_equal "Resist Stance" # note how title is updated from "Resist Stan"
|
178
|
+
album.song.id.must_equal 1
|
179
|
+
end
|
180
|
+
|
181
|
+
it "creates song" do
|
182
|
+
album.from_hash({"song"=>{"title"=>"Off The Track"}})
|
183
|
+
|
184
|
+
album.song.title.must_equal "Off The Track"
|
185
|
+
album.song.id.must_equal nil
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
|
190
|
+
describe "property with dynamic :class" do
|
191
|
+
representer!(:inject => :song_representer) do
|
192
|
+
property :song, :parse_strategy => :find_or_instantiate, :extend => song_representer,
|
193
|
+
:class => lambda { |fragment, *args| fragment["class"] }
|
194
|
+
end
|
195
|
+
|
196
|
+
let (:album) { Struct.new(:song).new.extend(representer) }
|
197
|
+
|
198
|
+
|
199
|
+
it "finds song by id" do
|
200
|
+
album.from_hash({"song"=>{"id" => 1, "title"=>"Resist Stance", "class"=>Song}})
|
201
|
+
|
202
|
+
album.song.title.must_equal "Resist Stance" # note how title is updated from "Resist Stan"
|
203
|
+
album.song.id.must_equal 1
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
|
209
|
+
class ParseStrategyLambdaTest < MiniTest::Spec
|
210
|
+
Song = Struct.new(:id, :title)
|
211
|
+
Song.class_eval do
|
212
|
+
def self.find(id)
|
213
|
+
return new(1, "Resist Stan") if id==1# we should return the same object here
|
214
|
+
new
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
representer!(:name => :song_representer) do
|
219
|
+
property :title
|
220
|
+
end
|
221
|
+
|
222
|
+
|
223
|
+
describe "collection" do
|
224
|
+
representer!(:inject => :song_representer) do
|
225
|
+
collection :songs, :parse_strategy => lambda { |fragment, i, options|
|
226
|
+
songs << song = Song.new
|
227
|
+
song
|
228
|
+
}, :extend => song_representer
|
229
|
+
end
|
230
|
+
|
231
|
+
let (:album) { Struct.new(:songs).new([Song.new(1, "A Walk")]).extend(representer) }
|
232
|
+
|
233
|
+
|
234
|
+
it "adds to existing collection" do
|
235
|
+
songs_id = album.songs.object_id
|
236
|
+
|
237
|
+
album.from_hash({"songs"=>[{"title"=>"Resist Stance"}]})
|
238
|
+
|
239
|
+
album.songs[0].title.must_equal "A Walk" # note how title is updated from "Resist Stan"
|
240
|
+
album.songs[0].id.must_equal 1
|
241
|
+
album.songs[1].title.must_equal "Resist Stance"
|
242
|
+
album.songs[1].id.must_equal nil
|
243
|
+
|
244
|
+
album.songs.object_id.must_equal songs_id
|
245
|
+
end
|
246
|
+
|
247
|
+
# TODO: test with existing collection
|
248
|
+
end
|
249
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class PassOptionsTest < BaseTest
|
4
|
+
let (:format) { :hash }
|
5
|
+
let (:song) { Struct.new(:title).new("Revolution") }
|
6
|
+
let (:prepared) { representer.prepare song }
|
7
|
+
|
8
|
+
describe "module" do
|
9
|
+
representer! do
|
10
|
+
property :title, :pass_options => true,
|
11
|
+
:as => lambda { |args| [args.binding.name, args.user_options, args.represented, args.decorator] }
|
12
|
+
end
|
13
|
+
|
14
|
+
it { render(prepared, :volume => 1).must_equal_document({["title", {:volume=>1}, prepared, prepared] => "Revolution"}) }
|
15
|
+
# it { parse(prepared, {"args" => "Wie Es Geht"}).name.must_equal "Wie Es Geht" }
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "decorator" do
|
19
|
+
representer!(:decorator => true) do
|
20
|
+
property :title, :pass_options => true,
|
21
|
+
:as => lambda { |args| [args.binding.name, args.user_options, args.represented, args.decorator] }
|
22
|
+
end
|
23
|
+
|
24
|
+
it { render(prepared, :volume => 1).must_equal_document({["title", {:volume=>1}, song, prepared] => "Revolution"}) }
|
25
|
+
# it { parse(prepared, {"args" => "Wie Es Geht"}).name.must_equal "Wie Es Geht" }
|
26
|
+
end
|
27
|
+
end
|