representable 1.7.6 → 1.7.7
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|