representable 1.7.6 → 1.7.7
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 +6 -0
- data/README.md +106 -3
- data/lib/representable.rb +32 -6
- data/lib/representable/binding.rb +2 -0
- data/lib/representable/decorator.rb +1 -13
- data/lib/representable/hash.rb +1 -1
- data/lib/representable/version.rb +1 -1
- data/test/generic_test.rb +21 -0
- data/test/inherit_test.rb +76 -0
- data/test/inheritance_test.rb +2 -1
- data/test/inline_test.rb +73 -12
- data/test/nested_test.rb +34 -52
- metadata +29 -47
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 453857338b438b7d68ffcdc22c4a673132d3193e
|
4
|
+
data.tar.gz: 19635dc3d647a965fcfe0af872db31f3eb305db3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e20ce7e46c5a94ab219a8936c04fa1a6ed7c1f77f2be36fab23685b80c1fda109c950dd011ae35c5a638ba04e0ce739f64d612d4a01c826bc75bcdee16524e2b
|
7
|
+
data.tar.gz: 58791da0eef9d17e2c3f24c82fc9c532cbfdea78d159cd09be33bf91755257adb0dbf9cb889c4facc81a17a81995ae8d5e4712063aaf4549ab571db12d9426c4
|
data/CHANGES.md
CHANGED
@@ -7,6 +7,12 @@ h2. 1.8.0
|
|
7
7
|
-> make major steps lambda-able
|
8
8
|
-> strategies for deserialization (lambda-able!)
|
9
9
|
|
10
|
+
h2. 1.7.7
|
11
|
+
|
12
|
+
* Parsing an empty hash with a representer having a wrap does no longer throw an exception.
|
13
|
+
* `::nested` now works in modules, too! Nests are implemented as decorator representer, not as modules, so they don't pollute the represented object.
|
14
|
+
* Introduce `:inherit` to allow inheriting+overriding properties and inline representers (and properties in inline representers - it starts getting crazy!!!).
|
15
|
+
|
10
16
|
h2. 1.7.6
|
11
17
|
|
12
18
|
* Add `::nested` to nest blocks in the document whilst still using the same represented object. Use with `Decorator` only.
|
data/README.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# Representable
|
2
2
|
|
3
|
-
Representable maps
|
3
|
+
Representable maps Ruby objects to documents and back.
|
4
4
|
|
5
5
|
In other words: Take an object and decorate it with a representer module. This will allow you to render a JSON, XML or YAML document from that object. But that's only half of it! You can also use representers to parse a document and create or populate an object.
|
6
6
|
|
7
|
-
Representable is helpful for all kind of rendering and parsing workflows. However, it is mostly useful in API code. Are you planning to write a real REST API with representable? Then check out the [
|
7
|
+
Representable is helpful for all kind of rendering and parsing workflows. However, it is mostly useful in API code. Are you planning to write a real REST API with representable? Then check out the [Roar](http://github.com/apotonick/roar) gem first, save work and time and make the world a better place instead.
|
8
8
|
|
9
9
|
|
10
10
|
## Installation
|
@@ -264,7 +264,7 @@ end
|
|
264
264
|
|
265
265
|
Just use an inline representer or the `extend:` option to define nested properties. Accessors for nested properties will still be called on the outer object (here, `song`). And as always, this works both ways for rendering and parsing.
|
266
266
|
|
267
|
-
Note that
|
267
|
+
Note that `::nested` internally is implemented using `Decorator`. When adding methods inside the `nested` block, make sure to use `represented` (`self` will point to the decorator instance).
|
268
268
|
|
269
269
|
|
270
270
|
## Decorator vs. Extend
|
@@ -452,6 +452,15 @@ Song.new(:title => "Truth Hits Everybody", :copyright => "The Police").
|
|
452
452
|
#=> {"title":"Truth Hits Everybody","copyright":"The Police"}
|
453
453
|
```
|
454
454
|
|
455
|
+
With decorators, you - surprisingly - use class inheritance.
|
456
|
+
|
457
|
+
```ruby
|
458
|
+
class HitRepresenter < SongRepresenter
|
459
|
+
collection :airplays
|
460
|
+
```
|
461
|
+
|
462
|
+
|
463
|
+
|
455
464
|
## Overriding Properties
|
456
465
|
|
457
466
|
You might want to override a particular property in an inheriting representer. Successively calling `property(name)` will override the former definition for `name` just as you know it from overriding methods.
|
@@ -468,6 +477,90 @@ end
|
|
468
477
|
This behaviour was added in 1.7.
|
469
478
|
|
470
479
|
|
480
|
+
## Partly Overriding Properties
|
481
|
+
|
482
|
+
If you wanna override only certain options of the property, use `:inherit`.
|
483
|
+
|
484
|
+
```ruby
|
485
|
+
module SongRepresenter
|
486
|
+
include Representable::JSON
|
487
|
+
|
488
|
+
property :title, as: :known_as
|
489
|
+
end
|
490
|
+
```
|
491
|
+
|
492
|
+
You can now inherit but still override or add options.
|
493
|
+
|
494
|
+
```ruby
|
495
|
+
module CoverSongRepresenter
|
496
|
+
include Representable::JSON
|
497
|
+
include SongRepresenter
|
498
|
+
|
499
|
+
property :title, getter: lambda { Title.random }, inherit: true
|
500
|
+
end
|
501
|
+
```
|
502
|
+
|
503
|
+
This will result in a property having the following options.
|
504
|
+
|
505
|
+
```ruby
|
506
|
+
property :title,
|
507
|
+
as: :known_as, # inherited from SongRepresenter
|
508
|
+
getter: lambda { .. } # added in inheriting representer.
|
509
|
+
end
|
510
|
+
```
|
511
|
+
|
512
|
+
## Inheritance With Inline Representers
|
513
|
+
|
514
|
+
Inheriting also works for inline representers.
|
515
|
+
|
516
|
+
```ruby
|
517
|
+
module SongRepresenter
|
518
|
+
include Representable::JSON
|
519
|
+
|
520
|
+
property :title
|
521
|
+
property :label do
|
522
|
+
property :name
|
523
|
+
end
|
524
|
+
end
|
525
|
+
```
|
526
|
+
|
527
|
+
You can now override or add properties with the inline representer.
|
528
|
+
|
529
|
+
```ruby
|
530
|
+
module HitRepresenter
|
531
|
+
include Representable::JSON
|
532
|
+
include SongRepresenter
|
533
|
+
|
534
|
+
property :label, inherit: true do
|
535
|
+
property :country
|
536
|
+
end
|
537
|
+
end
|
538
|
+
```
|
539
|
+
|
540
|
+
Results in a combined inline representer as it inherits.
|
541
|
+
|
542
|
+
```ruby
|
543
|
+
property :label do
|
544
|
+
property :name
|
545
|
+
property :country
|
546
|
+
end
|
547
|
+
```
|
548
|
+
|
549
|
+
Note that the following also works.
|
550
|
+
|
551
|
+
```ruby
|
552
|
+
module HitRepresenter
|
553
|
+
include Representable::JSON
|
554
|
+
include SongRepresenter
|
555
|
+
|
556
|
+
property :label, as: :company, inherit: true
|
557
|
+
end
|
558
|
+
```
|
559
|
+
|
560
|
+
This renames the property but still inherits all the inlined configuration.
|
561
|
+
|
562
|
+
Basically, `:inherit` copies the configuration from the parent property, then merges it your options from the inheriting representer. It exposes the same behaviour as `super` in Ruby - when using `:inherit` the property must exist in the parent representer.
|
563
|
+
|
471
564
|
## Polymorphic Extend
|
472
565
|
|
473
566
|
Sometimes heterogenous collections of objects from different classes must be represented. Or you don't know which representer to use at compile-time and need to delay the computation until runtime. This is why `:extend` accepts a lambda, too.
|
@@ -874,6 +967,16 @@ hit.to_json # this will call hit.song.to_json
|
|
874
967
|
|
875
968
|
Rendering `collection`s works the same. Parsing doesn't work out-of-the-box, currently, as we're still unsure how to map items to fragments.
|
876
969
|
|
970
|
+
### Decorator In Module
|
971
|
+
|
972
|
+
Inline representers defined in a module can be implemented as a decorator, thus wrapping the represented object without pollution.
|
973
|
+
|
974
|
+
```ruby
|
975
|
+
property :label, decorator: true do
|
976
|
+
...
|
977
|
+
end
|
978
|
+
```
|
979
|
+
|
877
980
|
## Copyright
|
878
981
|
|
879
982
|
Representable started as a heavily simplified fork of the ROXML gem. Big thanks to Ben Woosley for his inspiring work.
|
data/lib/representable.rb
CHANGED
@@ -152,23 +152,49 @@ private
|
|
152
152
|
|
153
153
|
# Internal module for DSL sugar that should not go into the core library.
|
154
154
|
module DSLAdditions
|
155
|
+
# Allows you to nest a block of properties in a separate section while still mapping them to the outer object.
|
156
|
+
def nested(name, options={}, &block)
|
157
|
+
options = options.merge(
|
158
|
+
:decorator => true,
|
159
|
+
:getter => lambda { |*| self },
|
160
|
+
:setter => lambda { |*| },
|
161
|
+
:instance => lambda { |*| self }
|
162
|
+
)
|
163
|
+
|
164
|
+
property(name, options, &block)
|
165
|
+
end
|
166
|
+
|
155
167
|
def property(name, options={}, &block)
|
156
|
-
|
168
|
+
parent = representable_attrs[name]
|
157
169
|
|
158
|
-
|
159
|
-
|
170
|
+
if block_given?
|
171
|
+
options[:extend] = inline_representer_for(parent, name, options, &block) # FIXME: passing parent sucks since we don't use it all the time.
|
172
|
+
end
|
173
|
+
|
174
|
+
if options[:inherit]
|
175
|
+
parent.options.merge!(options) and return parent
|
176
|
+
end # FIXME: can we handle this in super/Definition.new ?
|
160
177
|
|
161
|
-
options[:extend] = inline
|
162
178
|
super
|
163
179
|
end
|
164
180
|
|
165
|
-
private
|
166
181
|
def inline_representer(base_module, name, options, &block) # DISCUSS: separate module?
|
167
182
|
Module.new do
|
168
|
-
include base_module
|
183
|
+
include *base_module # Representable::JSON or similar.
|
169
184
|
instance_exec &block
|
170
185
|
end
|
171
186
|
end
|
187
|
+
|
188
|
+
private
|
189
|
+
def inline_representer_for(parent, name, options, &block)
|
190
|
+
representer = options[:decorator] ? Decorator : self
|
191
|
+
|
192
|
+
modules = [representer_engine]
|
193
|
+
modules << parent.representer_module if options[:inherit]
|
194
|
+
modules << options[:extend]
|
195
|
+
|
196
|
+
representer.inline_representer(modules.compact.reverse, name, options, &block)
|
197
|
+
end
|
172
198
|
end # DSLAdditions
|
173
199
|
end
|
174
200
|
|
@@ -15,24 +15,12 @@ module Representable
|
|
15
15
|
representable_attrs.clear
|
16
16
|
representable_attrs.inheritable_arrays.clear
|
17
17
|
|
18
|
-
include base_module
|
18
|
+
include *base_module
|
19
19
|
instance_exec &block
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
# Allows you to nest a block of properties in a separate section while still mapping them to the outer object.
|
25
|
-
def self.nested(name, options={}, &block)
|
26
|
-
options = options.merge(
|
27
|
-
:nested => true,
|
28
|
-
:getter => lambda { |*| self },
|
29
|
-
:setter => lambda { |*| },
|
30
|
-
:instance => lambda { |*| self }
|
31
|
-
)
|
32
|
-
|
33
|
-
property(name, options, &block)
|
34
|
-
end
|
35
|
-
|
36
24
|
include Representable # include after class methods so Decorator::prepare can't be overwritten by Representable::prepare.
|
37
25
|
|
38
26
|
def initialize(represented)
|
data/lib/representable/hash.rb
CHANGED
@@ -28,7 +28,7 @@ module Representable
|
|
28
28
|
|
29
29
|
def from_hash(data, options={}, binding_builder=PropertyBinding)
|
30
30
|
if wrap = options[:wrap] || representation_wrap
|
31
|
-
data = data[wrap.to_s]
|
31
|
+
data = data[wrap.to_s] || {} # DISCUSS: don't initialize this more than once. # TODO: this should be done with #read.
|
32
32
|
end
|
33
33
|
|
34
34
|
update_properties_from(data, options, binding_builder)
|
data/test/generic_test.rb
CHANGED
@@ -225,4 +225,25 @@ class GenericTest < MiniTest::Spec
|
|
225
225
|
must_equal({"song"=>{"artist"=>"Strung Out", "title"=>"The Fever And The Sound"}})
|
226
226
|
end
|
227
227
|
end
|
228
|
+
|
229
|
+
|
230
|
+
# wrap_test
|
231
|
+
for_formats(
|
232
|
+
:hash => [Representable::Hash, {}],
|
233
|
+
# :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>"],
|
234
|
+
# :yaml => [Representable::YAML, "---\nsong:\n name: Alive\n", "---\nsong:\n name: You've Taken Everything\n"],
|
235
|
+
) do |format, mod, input|
|
236
|
+
|
237
|
+
describe "parsing [#{format}] with wrap where wrap is missing" do
|
238
|
+
representer!(:module => mod) do
|
239
|
+
self.representation_wrap = :song
|
240
|
+
|
241
|
+
property :title
|
242
|
+
end
|
243
|
+
|
244
|
+
it "doesn't change represented object" do
|
245
|
+
song.extend(representer).send("from_#{format}", input).title.must_equal "Resist Stance"
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
228
249
|
end
|
@@ -0,0 +1,76 @@
|
|
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
|
+
it { representer.prepare( Song.new(Struct.new(:string).new("Believe It"), 1)).to_hash.must_equal({"title"=>{"str"=>"Believe It"}, "no"=>1}) }
|
37
|
+
end
|
38
|
+
|
39
|
+
describe ":inherit with overriding inline representer" do
|
40
|
+
representer! do
|
41
|
+
include SongRepresenter
|
42
|
+
|
43
|
+
property :name, :inherit => true do # inherit as: title
|
44
|
+
property :string, :as => :s
|
45
|
+
property :length
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
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}) }
|
50
|
+
end
|
51
|
+
|
52
|
+
describe ":inherit with empty inline and options" do
|
53
|
+
representer! do
|
54
|
+
include SongRepresenter
|
55
|
+
|
56
|
+
property :name, :inherit => true, :as => :name do # inherit module, only.
|
57
|
+
# that doesn't make sense.
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it { SongRepresenter.prepare(Song.new(Struct.new(:string).new("Believe It"), 1)).to_hash.must_equal({"title"=>{"str"=>"Believe It"}, "no"=>1}) }
|
62
|
+
it { representer.prepare( Song.new(Struct.new(:string).new("Believe It"), 1)).to_hash.must_equal({"name"=>{"str"=>"Believe It"}, "no"=>1}) }
|
63
|
+
end
|
64
|
+
|
65
|
+
describe ":inherit with inline without block but options" do
|
66
|
+
representer! do
|
67
|
+
include SongRepresenter
|
68
|
+
|
69
|
+
property :name, :inherit => true, :as => :name
|
70
|
+
end
|
71
|
+
|
72
|
+
it { SongRepresenter.prepare(Song.new(Struct.new(:string).new("Believe It"), 1)).to_hash.must_equal({"title"=>{"str"=>"Believe It"}, "no"=>1}) }
|
73
|
+
it { representer.prepare( Song.new(Struct.new(:string).new("Believe It"), 1)).to_hash.must_equal({"name"=>{"str"=>"Believe It"}, "no"=>1}) }
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
data/test/inheritance_test.rb
CHANGED
data/test/inline_test.rb
CHANGED
@@ -57,28 +57,55 @@ class InlineTest < MiniTest::Spec
|
|
57
57
|
it { request.to_hash.must_equal({"song"=>{"name"=>"Alive"}}) }
|
58
58
|
end
|
59
59
|
|
60
|
-
describe "decorator" do
|
61
|
-
let (:request) { representer.prepare(OpenStruct.new(:song => song, :who => "Josephine")) }
|
62
60
|
|
63
|
-
|
64
|
-
|
65
|
-
|
61
|
+
for_formats(
|
62
|
+
:hash => [Representable::Hash, {}],
|
63
|
+
# :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>"],
|
64
|
+
# :yaml => [Representable::YAML, "---\nsong:\n name: Alive\n", "---\nsong:\n name: You've Taken Everything\n"],
|
65
|
+
) do |format, mod, input|
|
66
|
+
|
67
|
+
describe "parsing [#{format}] where nested property missing" do
|
68
|
+
representer!(:module => mod) do
|
69
|
+
property :song do
|
70
|
+
property :name
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it "doesn't change represented object" do
|
75
|
+
request.send("from_#{format}", input).song.must_equal song
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
66
79
|
|
67
|
-
|
80
|
+
|
81
|
+
describe "inheriting from outer representer" do
|
82
|
+
let (:request) { Struct.new(:song, :requester).new(song, "Josephine") }
|
83
|
+
|
84
|
+
[false, true].each do |is_decorator| # test for module and decorator.
|
85
|
+
representer!(:decorator => is_decorator) do
|
86
|
+
property :requester
|
68
87
|
|
69
88
|
property :song, :class => Song do
|
70
89
|
property :name
|
71
90
|
end
|
72
|
-
|
73
|
-
self
|
74
91
|
end
|
92
|
+
|
93
|
+
let (:decorator) { representer.prepare(request) }
|
94
|
+
|
95
|
+
it { decorator.to_hash.must_equal({"requester"=>"Josephine", "song"=>{"name"=>"Alive"}}) }
|
96
|
+
it { decorator.from_hash({"song"=>{"name"=>"You've Taken Everything"}}).song.name.must_equal "You've Taken Everything"}
|
75
97
|
end
|
98
|
+
end
|
76
99
|
|
77
|
-
|
78
|
-
|
100
|
+
describe "object pollution" do
|
101
|
+
representer!(:decorator => true) do
|
102
|
+
property :song do
|
103
|
+
property :name
|
104
|
+
end
|
105
|
+
end
|
79
106
|
|
80
|
-
it "uses an inline decorator" do
|
81
|
-
|
107
|
+
it "uses an inline decorator and doesn't alter represented" do
|
108
|
+
representer.prepare(Struct.new(:song).new(song)).to_hash
|
82
109
|
song.wont_be_kind_of Representable
|
83
110
|
end
|
84
111
|
end
|
@@ -141,4 +168,38 @@ class InlineTest < MiniTest::Spec
|
|
141
168
|
end
|
142
169
|
end
|
143
170
|
end
|
171
|
+
|
172
|
+
|
173
|
+
# test helper methods within inline representer
|
174
|
+
for_formats({
|
175
|
+
:hash => [Representable::Hash, {"song"=>{"name"=>"ALIVE"}}],
|
176
|
+
:xml => [Representable::XML, "<request>\n <song>\n <name>ALIVE</name>\n </song>\n</request>"],
|
177
|
+
:yaml => [Representable::YAML, "---\nsong:\n name: ALIVE\n"],
|
178
|
+
}) do |format, mod, output|
|
179
|
+
|
180
|
+
describe "helper method within inline representer [#{format}]" do
|
181
|
+
let (:format) { format }
|
182
|
+
|
183
|
+
representer!(:module => mod, :decorator => true) do
|
184
|
+
self.representation_wrap = :request if format == :xml
|
185
|
+
|
186
|
+
property :requester
|
187
|
+
property :song do
|
188
|
+
property :name, :decorator_scope => true
|
189
|
+
|
190
|
+
define_method :name do
|
191
|
+
represented.name.upcase
|
192
|
+
end
|
193
|
+
|
194
|
+
self.representation_wrap = :song if format == :xml
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
let (:request) { representer.prepare(OpenStruct.new(:song => Song.new("Alive"))) }
|
199
|
+
|
200
|
+
it do
|
201
|
+
render(request).must_equal_document output
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
144
205
|
end
|
data/test/nested_test.rb
CHANGED
@@ -1,41 +1,46 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class NestedTest < MiniTest::Spec
|
4
|
-
Album = Struct.new(:label, :owner)
|
4
|
+
Album = Struct.new(:label, :owner, :amount)
|
5
5
|
|
6
6
|
for_formats(
|
7
|
-
:hash => [Representable::Hash, {"label" => {"label"=>"Epitaph", "owner"=>"Brett Gurewitz"}}],
|
7
|
+
:hash => [Representable::Hash, {"label" => {"label"=>"Epitaph", "owner"=>"Brett Gurewitz", "releases"=>{"amount"=>19}}}],
|
8
8
|
# :xml => [Representable::XML, "<open_struct></open_struct>"],
|
9
|
-
:yaml => [Representable::YAML, "---\nlabel:\n label: Epitaph\n owner: Brett Gurewitz\n"]
|
9
|
+
:yaml => [Representable::YAML, "---\nlabel:\n label: Epitaph\n owner: Brett Gurewitz\n releases:\n amount: 19\n"]
|
10
10
|
) do |format, mod, output, input|
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
[false, true].each do |is_decorator|
|
13
|
+
describe "::nested with (inline representer|decorator): #{is_decorator}" do
|
14
|
+
let (:format) { format }
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
representer!(:module => mod, :decorator => is_decorator) do
|
17
|
+
nested :label do
|
18
|
+
property :label
|
19
|
+
property :owner
|
19
20
|
|
20
|
-
|
21
|
-
|
21
|
+
# self.representation_wrap = nil if format == :xml
|
22
|
+
nested :releases do
|
23
|
+
property :amount
|
24
|
+
end
|
25
|
+
end
|
22
26
|
|
27
|
+
# self.representation_wrap = :album if format == :xml
|
28
|
+
end
|
23
29
|
|
24
|
-
|
25
|
-
# end
|
30
|
+
let (:album) { representer.prepare(Album.new("Epitaph", "Brett Gurewitz", 19)) }
|
26
31
|
|
27
|
-
|
32
|
+
it "renders nested Album-properties in separate section" do
|
33
|
+
render(album).must_equal_document output
|
34
|
+
end
|
28
35
|
|
29
|
-
|
30
|
-
|
31
|
-
|
36
|
+
it "parses nested properties to Album instance" do
|
37
|
+
album = parse(representer.prepare(Album.new), output)
|
38
|
+
album.label.must_equal "Epitaph"
|
39
|
+
album.owner.must_equal "Brett Gurewitz"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
32
43
|
|
33
|
-
# it "parses nested properties to Album instance" do
|
34
|
-
# album = parse(Album.new.extend(representer), output)
|
35
|
-
# album.label.must_equal "Epitaph"
|
36
|
-
# album.owner.must_equal "Brett Gurewitz"
|
37
|
-
# end
|
38
|
-
# end
|
39
44
|
|
40
45
|
describe "Decorator ::nested with extend:" do
|
41
46
|
let (:format) { format }
|
@@ -44,6 +49,10 @@ class NestedTest < MiniTest::Spec
|
|
44
49
|
include mod
|
45
50
|
property :label
|
46
51
|
property :owner
|
52
|
+
|
53
|
+
nested :releases do # DISCUSS: do we need to test this?
|
54
|
+
property :amount
|
55
|
+
end
|
47
56
|
end
|
48
57
|
|
49
58
|
representer!(:module => mod, :decorator => true, :inject => :label_rpr) do
|
@@ -52,7 +61,7 @@ class NestedTest < MiniTest::Spec
|
|
52
61
|
self.representation_wrap = :album if format == :xml
|
53
62
|
end
|
54
63
|
|
55
|
-
let (:album) { representer.prepare(Album.new("Epitaph", "Brett Gurewitz")) }
|
64
|
+
let (:album) { representer.prepare(Album.new("Epitaph", "Brett Gurewitz", 19)) }
|
56
65
|
|
57
66
|
# TODO: shared example with above.
|
58
67
|
it "renders nested Album-properties in separate section" do
|
@@ -63,34 +72,7 @@ class NestedTest < MiniTest::Spec
|
|
63
72
|
album = parse(representer.prepare(Album.new), output)
|
64
73
|
album.label.must_equal "Epitaph"
|
65
74
|
album.owner.must_equal "Brett Gurewitz"
|
66
|
-
|
67
|
-
end
|
68
|
-
|
69
|
-
describe "Decorator ::nested" do
|
70
|
-
let (:format) { format }
|
71
|
-
|
72
|
-
representer!(:module => mod, :decorator => true) do
|
73
|
-
nested :label do
|
74
|
-
property :label
|
75
|
-
property :owner
|
76
|
-
|
77
|
-
# self.representation_wrap = nil if format == :xml
|
78
|
-
end
|
79
|
-
|
80
|
-
|
81
|
-
self.representation_wrap = :album if format == :xml
|
82
|
-
end
|
83
|
-
|
84
|
-
let (:album) { representer.prepare(Album.new("Epitaph", "Brett Gurewitz")) }
|
85
|
-
|
86
|
-
it "renders nested Album-properties in separate section" do
|
87
|
-
render(album).must_equal_document output
|
88
|
-
end
|
89
|
-
|
90
|
-
it "parses nested properties to Album instance" do
|
91
|
-
album = parse(representer.prepare(Album.new), output)
|
92
|
-
album.label.must_equal "Epitaph"
|
93
|
-
album.owner.must_equal "Brett Gurewitz"
|
75
|
+
album.amount.must_equal 19
|
94
76
|
end
|
95
77
|
end
|
96
78
|
end
|
metadata
CHANGED
@@ -1,153 +1,153 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: representable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.7.
|
4
|
+
version: 1.7.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nick Sutterer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: multi_json
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - '>='
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - '>='
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - '>='
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - '>='
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: test_xml
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: 0.1.6
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - '>='
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 0.1.6
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: minitest
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ~>
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: 5.0.0
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ~>
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 5.0.0
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: mocha
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - '>='
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: 0.13.0
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- -
|
94
|
+
- - '>='
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: 0.13.0
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: mongoid
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- -
|
101
|
+
- - '>='
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '0'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- -
|
108
|
+
- - '>='
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: virtus
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
|
-
- -
|
115
|
+
- - ~>
|
116
116
|
- !ruby/object:Gem::Version
|
117
117
|
version: 0.5.0
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
|
-
- -
|
122
|
+
- - ~>
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: 0.5.0
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: yajl-ruby
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
128
128
|
requirements:
|
129
|
-
- -
|
129
|
+
- - '>='
|
130
130
|
- !ruby/object:Gem::Version
|
131
131
|
version: '0'
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
134
|
version_requirements: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
|
-
- -
|
136
|
+
- - '>='
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0'
|
139
139
|
- !ruby/object:Gem::Dependency
|
140
140
|
name: json
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
142
142
|
requirements:
|
143
|
-
- -
|
143
|
+
- - ~>
|
144
144
|
- !ruby/object:Gem::Version
|
145
145
|
version: 1.7.7
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
|
-
- -
|
150
|
+
- - ~>
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: 1.7.7
|
153
153
|
description: Renders and parses JSON/XML/YAML documents from and to Ruby objects.
|
@@ -158,8 +158,8 @@ executables: []
|
|
158
158
|
extensions: []
|
159
159
|
extra_rdoc_files: []
|
160
160
|
files:
|
161
|
-
-
|
162
|
-
-
|
161
|
+
- .gitignore
|
162
|
+
- .travis.yml
|
163
163
|
- CHANGES.md
|
164
164
|
- Gemfile
|
165
165
|
- LICENSE
|
@@ -202,6 +202,7 @@ files:
|
|
202
202
|
- test/generic_test.rb
|
203
203
|
- test/hash_bindings_test.rb
|
204
204
|
- test/hash_test.rb
|
205
|
+
- test/inherit_test.rb
|
205
206
|
- test/inheritance_test.rb
|
206
207
|
- test/inline_test.rb
|
207
208
|
- test/json_test.rb
|
@@ -222,38 +223,19 @@ require_paths:
|
|
222
223
|
- lib
|
223
224
|
required_ruby_version: !ruby/object:Gem::Requirement
|
224
225
|
requirements:
|
225
|
-
- -
|
226
|
+
- - '>='
|
226
227
|
- !ruby/object:Gem::Version
|
227
228
|
version: '0'
|
228
229
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
229
230
|
requirements:
|
230
|
-
- -
|
231
|
+
- - '>='
|
231
232
|
- !ruby/object:Gem::Version
|
232
233
|
version: '0'
|
233
234
|
requirements: []
|
234
235
|
rubyforge_project:
|
235
|
-
rubygems_version: 2.2
|
236
|
+
rubygems_version: 2.0.2
|
236
237
|
signing_key:
|
237
238
|
specification_version: 4
|
238
239
|
summary: Renders and parses JSON/XML/YAML documents from and to Ruby objects. Includes
|
239
240
|
plain properties, collections, nesting, coercion and more.
|
240
|
-
test_files:
|
241
|
-
- test/coercion_test.rb
|
242
|
-
- test/config_test.rb
|
243
|
-
- test/decorator_test.rb
|
244
|
-
- test/definition_test.rb
|
245
|
-
- test/example.rb
|
246
|
-
- test/generic_test.rb
|
247
|
-
- test/hash_bindings_test.rb
|
248
|
-
- test/hash_test.rb
|
249
|
-
- test/inheritance_test.rb
|
250
|
-
- test/inline_test.rb
|
251
|
-
- test/json_test.rb
|
252
|
-
- test/mongoid_test.rb
|
253
|
-
- test/nested_test.rb
|
254
|
-
- test/representable_test.rb
|
255
|
-
- test/test_helper.rb
|
256
|
-
- test/test_helper_test.rb
|
257
|
-
- test/xml_bindings_test.rb
|
258
|
-
- test/xml_test.rb
|
259
|
-
- test/yaml_test.rb
|
241
|
+
test_files: []
|