representable 1.2.3 → 1.2.4
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.
- data/.gitignore +5 -0
- data/.travis.yml +7 -1
- data/CHANGES.textile +5 -0
- data/README.rdoc +21 -1
- data/gemfiles/Gemfile.mongoid-2.4 +6 -0
- data/lib/representable/binding.rb +20 -0
- data/lib/representable/bindings/json_bindings.rb +5 -10
- data/lib/representable/bindings/xml_bindings.rb +33 -27
- data/lib/representable/json/hash.rb +6 -6
- data/lib/representable/version.rb +1 -1
- data/lib/representable/xml/hash.rb +13 -13
- data/test/json_test.rb +127 -127
- data/test/representable_test.rb +27 -12
- data/test/test_helper.rb +11 -1
- data/test/test_helper_test.rb +25 -0
- data/test/xml_test.rb +49 -7
- metadata +4 -2
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/CHANGES.textile
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
h2. 1.2.4
|
|
2
|
+
|
|
3
|
+
* ObjectBinding no longer tries to extend nil values when rendering and @:render_nil@ is set.
|
|
4
|
+
* In XML you can now use @:wrap@ to define an additional container tag around properties and collections.
|
|
5
|
+
|
|
1
6
|
h2. 1.2.3
|
|
2
7
|
|
|
3
8
|
* Using virtus for coercion now works in both classes and modules. Thanks to @solnic for a great collaboration. Open-source rocks!
|
data/README.rdoc
CHANGED
|
@@ -15,7 +15,7 @@ This keeps your representation knowledge in one place when implementing REST ser
|
|
|
15
15
|
* Bidirectional - rendering and parsing
|
|
16
16
|
* OOP access to documents
|
|
17
17
|
* Support for JSON and XML
|
|
18
|
-
* Coercion support with virtus[https://github.com/solnic/virtus
|
|
18
|
+
* Coercion support with virtus[https://github.com/solnic/virtus]
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
== Example
|
|
@@ -317,6 +317,26 @@ You can also map properties to tag attributes in representable.
|
|
|
317
317
|
|
|
318
318
|
Naturally, this works for both ways.
|
|
319
319
|
|
|
320
|
+
=== Wrapping collections
|
|
321
|
+
|
|
322
|
+
It is sometimes unavoidable to wrap tag lists in a container tag.
|
|
323
|
+
|
|
324
|
+
module AlbumRepresenter
|
|
325
|
+
include Representable::XML
|
|
326
|
+
|
|
327
|
+
collection :songs, :from => :song, :wrap => :songs
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
Note that +:wrap+ defines the container tag name.
|
|
331
|
+
|
|
332
|
+
Album.new.to_xml #=>
|
|
333
|
+
<album>
|
|
334
|
+
<songs>
|
|
335
|
+
<song>Laundry Basket</song>
|
|
336
|
+
<song>Two Kevins</song>
|
|
337
|
+
<song>Wright and Rong</song>
|
|
338
|
+
</songs>
|
|
339
|
+
</album>
|
|
320
340
|
|
|
321
341
|
== Coercion
|
|
322
342
|
|
|
@@ -44,5 +44,25 @@ module Representable
|
|
|
44
44
|
object
|
|
45
45
|
end
|
|
46
46
|
end
|
|
47
|
+
|
|
48
|
+
module Object
|
|
49
|
+
include Binding::Extend # provides #serialize/#deserialize with extend.
|
|
50
|
+
|
|
51
|
+
def serialize(object)
|
|
52
|
+
return object if object.nil?
|
|
53
|
+
|
|
54
|
+
super(object).send(serialize_method, :wrap => false)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def deserialize(data)
|
|
58
|
+
# DISCUSS: does it make sense to skip deserialization of nil-values here?
|
|
59
|
+
super(create_object).send(deserialize_method, data)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def create_object
|
|
63
|
+
definition.sought_type.new
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
47
67
|
end
|
|
48
68
|
end
|
|
@@ -3,19 +3,14 @@ require 'representable/binding'
|
|
|
3
3
|
module Representable
|
|
4
4
|
module JSON
|
|
5
5
|
module ObjectBinding
|
|
6
|
-
|
|
7
|
-
include Binding::Extend # provides #serialize/#deserialize with extend.
|
|
6
|
+
include Binding::Object
|
|
8
7
|
|
|
9
|
-
def
|
|
10
|
-
|
|
8
|
+
def serialize_method
|
|
9
|
+
:to_hash
|
|
11
10
|
end
|
|
12
11
|
|
|
13
|
-
def
|
|
14
|
-
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def create_object
|
|
18
|
-
definition.sought_type.new
|
|
12
|
+
def deserialize_method
|
|
13
|
+
:from_hash
|
|
19
14
|
end
|
|
20
15
|
end
|
|
21
16
|
|
|
@@ -3,15 +3,14 @@ require 'representable/binding'
|
|
|
3
3
|
module Representable
|
|
4
4
|
module XML
|
|
5
5
|
module ObjectBinding
|
|
6
|
-
|
|
7
|
-
include Binding::Extend # provides #serialize/#deserialize with extend.
|
|
6
|
+
include Binding::Object
|
|
8
7
|
|
|
9
|
-
def
|
|
10
|
-
|
|
8
|
+
def serialize_method
|
|
9
|
+
:to_node
|
|
11
10
|
end
|
|
12
11
|
|
|
13
|
-
def
|
|
14
|
-
|
|
12
|
+
def deserialize_method
|
|
13
|
+
:from_node
|
|
15
14
|
end
|
|
16
15
|
|
|
17
16
|
def deserialize_node(node)
|
|
@@ -21,10 +20,6 @@ module Representable
|
|
|
21
20
|
def serialize_node(node, value)
|
|
22
21
|
serialize(value)
|
|
23
22
|
end
|
|
24
|
-
|
|
25
|
-
def create_object
|
|
26
|
-
definition.sought_type.new
|
|
27
|
-
end
|
|
28
23
|
end
|
|
29
24
|
|
|
30
25
|
|
|
@@ -35,11 +30,20 @@ module Representable
|
|
|
35
30
|
end
|
|
36
31
|
|
|
37
32
|
def write(parent, value)
|
|
38
|
-
|
|
33
|
+
wrap_node = parent
|
|
34
|
+
|
|
35
|
+
if wrap = definition.options[:wrap]
|
|
36
|
+
parent << wrap_node = node_for(parent, wrap)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
wrap_node << serialize_for(value, parent)
|
|
39
40
|
end
|
|
40
41
|
|
|
41
42
|
def read(node)
|
|
42
|
-
|
|
43
|
+
selector = "./#{xpath}"
|
|
44
|
+
selector = "./#{definition.options[:wrap]}/#{xpath}" if definition.options[:wrap]
|
|
45
|
+
nodes = node.search(selector)
|
|
46
|
+
|
|
43
47
|
return FragmentNotFound if nodes.size == 0 # TODO: write dedicated test!
|
|
44
48
|
|
|
45
49
|
deserialize_from(nodes)
|
|
@@ -48,7 +52,7 @@ module Representable
|
|
|
48
52
|
# Creates wrapped node for the property.
|
|
49
53
|
def serialize_for(value, parent)
|
|
50
54
|
#def serialize_for(value, parent, tag_name=definition.from)
|
|
51
|
-
node =
|
|
55
|
+
node = node_for(parent, definition.from)
|
|
52
56
|
serialize_node(node, value)
|
|
53
57
|
end
|
|
54
58
|
|
|
@@ -70,19 +74,16 @@ module Representable
|
|
|
70
74
|
def xpath
|
|
71
75
|
definition.from
|
|
72
76
|
end
|
|
77
|
+
|
|
78
|
+
def node_for(parent, name)
|
|
79
|
+
Nokogiri::XML::Node.new(name.to_s, parent.document)
|
|
80
|
+
end
|
|
73
81
|
end
|
|
74
82
|
|
|
75
83
|
class CollectionBinding < PropertyBinding
|
|
76
|
-
def
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
end
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def serialize_items(value, parent)
|
|
83
|
-
value.collect do |obj|
|
|
84
|
-
serialize_for(obj, parent)
|
|
85
|
-
end
|
|
84
|
+
def serialize_for(value, parent)
|
|
85
|
+
# return NodeSet so << works.
|
|
86
|
+
set_for(parent, value.collect { |item| super(item, parent) })
|
|
86
87
|
end
|
|
87
88
|
|
|
88
89
|
def deserialize_from(nodes)
|
|
@@ -90,15 +91,20 @@ module Representable
|
|
|
90
91
|
deserialize_node(item)
|
|
91
92
|
end
|
|
92
93
|
end
|
|
94
|
+
|
|
95
|
+
private
|
|
96
|
+
def set_for(parent, nodes)
|
|
97
|
+
Nokogiri::XML::NodeSet.new(parent.document, nodes)
|
|
98
|
+
end
|
|
93
99
|
end
|
|
94
100
|
|
|
95
101
|
|
|
96
102
|
class HashBinding < CollectionBinding
|
|
97
|
-
def
|
|
98
|
-
value.collect do |k, v|
|
|
99
|
-
node =
|
|
103
|
+
def serialize_for(value, parent)
|
|
104
|
+
set_for(parent, value.collect do |k, v|
|
|
105
|
+
node = node_for(parent, k)
|
|
100
106
|
serialize_node(node, v)
|
|
101
|
-
end
|
|
107
|
+
end)
|
|
102
108
|
end
|
|
103
109
|
|
|
104
110
|
def deserialize_from(nodes)
|
|
@@ -4,24 +4,24 @@ module Representable::JSON
|
|
|
4
4
|
module Hash
|
|
5
5
|
include Representable::JSON
|
|
6
6
|
include HashMethods
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
def self.included(base)
|
|
9
9
|
base.class_eval do
|
|
10
10
|
include Representable
|
|
11
11
|
extend ClassMethods
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
|
|
15
|
+
|
|
16
16
|
module ClassMethods
|
|
17
17
|
def values(options)
|
|
18
18
|
hash :_self, options
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
|
|
22
|
+
|
|
23
23
|
def definition_opts
|
|
24
|
-
[:_self, :hash => true, :use_attributes => true]
|
|
24
|
+
[:_self, {:hash => true, :use_attributes => true}]
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
end
|
|
@@ -4,48 +4,48 @@ module Representable::XML
|
|
|
4
4
|
module AttributeHash
|
|
5
5
|
include Representable::XML
|
|
6
6
|
include Representable::HashMethods
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
def self.included(base)
|
|
9
9
|
base.class_eval do
|
|
10
10
|
include Representable
|
|
11
11
|
extend ClassMethods
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
|
|
15
|
+
|
|
16
16
|
module ClassMethods
|
|
17
17
|
def values(options)
|
|
18
18
|
hash :_self, options.merge!(:use_attributes => true)
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
|
|
22
|
+
|
|
23
23
|
def definition_opts
|
|
24
|
-
[:_self, :hash => true, :use_attributes => true]
|
|
24
|
+
[:_self, {:hash => true, :use_attributes => true}]
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
module Hash
|
|
29
29
|
include Representable::XML
|
|
30
30
|
include HashMethods
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
def self.included(base)
|
|
33
33
|
base.class_eval do
|
|
34
34
|
include Representable
|
|
35
35
|
extend ClassMethods
|
|
36
36
|
end
|
|
37
37
|
end
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
|
|
39
|
+
|
|
40
40
|
module ClassMethods
|
|
41
41
|
def values(options)
|
|
42
42
|
hash :_self, options
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
|
|
46
|
+
|
|
47
47
|
def definition_opts
|
|
48
|
-
[:_self, :hash => true]
|
|
48
|
+
[:_self, {:hash => true}]
|
|
49
49
|
end
|
|
50
50
|
end
|
|
51
51
|
end
|
data/test/json_test.rb
CHANGED
|
@@ -4,7 +4,7 @@ module JsonTest
|
|
|
4
4
|
class APITest < MiniTest::Spec
|
|
5
5
|
Json = Representable::JSON
|
|
6
6
|
Def = Representable::Definition
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
describe "JSON module" do
|
|
9
9
|
before do
|
|
10
10
|
@Band = Class.new do
|
|
@@ -12,23 +12,23 @@ module JsonTest
|
|
|
12
12
|
property :name
|
|
13
13
|
property :label
|
|
14
14
|
attr_accessor :name, :label
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
def initialize(name=nil)
|
|
17
17
|
self.name = name if name
|
|
18
18
|
end
|
|
19
19
|
end
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
@band = @Band.new
|
|
22
22
|
end
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
|
|
24
|
+
|
|
25
25
|
describe ".from_json" do
|
|
26
26
|
it "is delegated to #from_json" do
|
|
27
27
|
block = lambda {|*args|}
|
|
28
28
|
@Band.any_instance.expects(:from_json).with("{document}", "options") # FIXME: how to NOT expect block?
|
|
29
29
|
@Band.from_json("{document}", "options", &block)
|
|
30
30
|
end
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
it "yields new object and options to block" do
|
|
33
33
|
@Band.class_eval { attr_accessor :new_name }
|
|
34
34
|
@band = @Band.from_json("{}", :new_name => "Diesel Boy") do |band, options|
|
|
@@ -37,113 +37,113 @@ module JsonTest
|
|
|
37
37
|
assert_equal "Diesel Boy", @band.new_name
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
|
|
41
|
+
|
|
42
42
|
describe ".from_hash" do
|
|
43
43
|
it "is delegated to #from_hash not passing the block" do
|
|
44
44
|
block = lambda {|*args|}
|
|
45
45
|
@Band.any_instance.expects(:from_hash).with("{document}", "options") # FIXME: how to NOT expect block?
|
|
46
46
|
@Band.from_hash("{document}", "options", &block)
|
|
47
47
|
end
|
|
48
|
-
|
|
48
|
+
|
|
49
49
|
it "yields new object and options to block" do
|
|
50
50
|
@Band.class_eval { attr_accessor :new_name }
|
|
51
51
|
@band = @Band.from_hash({}, :new_name => "Diesel Boy") do |band, options|
|
|
52
52
|
band.new_name= options[:new_name]
|
|
53
53
|
end
|
|
54
|
-
|
|
54
|
+
|
|
55
55
|
assert_equal "Diesel Boy", @band.new_name
|
|
56
56
|
end
|
|
57
57
|
end
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
|
|
59
|
+
|
|
60
60
|
describe "#from_json" do
|
|
61
61
|
before do
|
|
62
62
|
@band = @Band.new
|
|
63
63
|
@json = {:name => "Nofx", :label => "NOFX"}.to_json
|
|
64
64
|
end
|
|
65
|
-
|
|
65
|
+
|
|
66
66
|
it "parses JSON and assigns properties" do
|
|
67
67
|
@band.from_json(@json)
|
|
68
68
|
assert_equal ["Nofx", "NOFX"], [@band.name, @band.label]
|
|
69
69
|
end
|
|
70
70
|
end
|
|
71
|
-
|
|
72
|
-
|
|
71
|
+
|
|
72
|
+
|
|
73
73
|
describe "#from_hash" do
|
|
74
74
|
before do
|
|
75
75
|
@band = @Band.new
|
|
76
76
|
@hash = {"name" => "Nofx", "label" => "NOFX"}
|
|
77
77
|
end
|
|
78
|
-
|
|
78
|
+
|
|
79
79
|
it "receives hash and assigns properties" do
|
|
80
80
|
@band.from_hash(@hash)
|
|
81
81
|
assert_equal ["Nofx", "NOFX"], [@band.name, @band.label]
|
|
82
82
|
end
|
|
83
|
-
|
|
83
|
+
|
|
84
84
|
it "respects :wrap option" do
|
|
85
85
|
@band.from_hash({"band" => {"name" => "This Is A Standoff"}}, :wrap => :band)
|
|
86
86
|
assert_equal "This Is A Standoff", @band.name
|
|
87
87
|
end
|
|
88
|
-
|
|
88
|
+
|
|
89
89
|
it "respects :wrap option over representation_wrap" do
|
|
90
90
|
@Band.class_eval do
|
|
91
|
-
self.representation_wrap = :group
|
|
91
|
+
self.representation_wrap = :group
|
|
92
92
|
end
|
|
93
93
|
@band.from_hash({"band" => {"name" => "This Is A Standoff"}}, :wrap => :band)
|
|
94
94
|
assert_equal "This Is A Standoff", @band.name
|
|
95
95
|
end
|
|
96
96
|
end
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
|
|
98
|
+
|
|
99
99
|
describe "#to_json" do
|
|
100
100
|
it "delegates to #to_hash and returns string" do
|
|
101
|
-
|
|
101
|
+
assert_json "{\"name\":\"Rise Against\"}", @Band.new("Rise Against").to_json
|
|
102
102
|
end
|
|
103
103
|
end
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
|
|
105
|
+
|
|
106
106
|
describe "#to_hash" do
|
|
107
107
|
it "returns unwrapped hash" do
|
|
108
108
|
hash = @Band.new("Rise Against").to_hash
|
|
109
109
|
assert_equal({"name"=>"Rise Against"}, hash)
|
|
110
110
|
end
|
|
111
|
-
|
|
111
|
+
|
|
112
112
|
it "respects #representation_wrap=" do
|
|
113
113
|
@Band.representation_wrap = :group
|
|
114
114
|
assert_equal({:group=>{"name"=>"Rise Against"}}, @Band.new("Rise Against").to_hash)
|
|
115
115
|
end
|
|
116
|
-
|
|
116
|
+
|
|
117
117
|
it "respects :wrap option" do
|
|
118
118
|
assert_equal({:band=>{"name"=>"NOFX"}}, @Band.new("NOFX").to_hash(:wrap => :band))
|
|
119
119
|
end
|
|
120
|
-
|
|
120
|
+
|
|
121
121
|
it "respects :wrap option over representation_wrap" do
|
|
122
122
|
@Band.class_eval do
|
|
123
|
-
self.representation_wrap = :group
|
|
123
|
+
self.representation_wrap = :group
|
|
124
124
|
end
|
|
125
125
|
assert_equal({:band=>{"name"=>"Rise Against"}}, @Band.new("Rise Against").to_hash(:wrap => :band))
|
|
126
126
|
end
|
|
127
127
|
end
|
|
128
|
-
|
|
128
|
+
|
|
129
129
|
describe "#binding_for_definition" do
|
|
130
130
|
it "returns ObjectBinding" do
|
|
131
131
|
assert_kind_of Json::ObjectBinding, Json.binding_for_definition(Def.new(:band, :class => Hash))
|
|
132
132
|
end
|
|
133
|
-
|
|
133
|
+
|
|
134
134
|
it "returns TextBinding" do
|
|
135
135
|
assert_kind_of Json::PropertyBinding, Json.binding_for_definition(Def.new(:band))
|
|
136
136
|
end
|
|
137
|
-
|
|
137
|
+
|
|
138
138
|
it "returns HashBinding" do
|
|
139
139
|
assert_kind_of Json::HashBinding, Json.binding_for_definition(Def.new(:band, :hash => true))
|
|
140
140
|
end
|
|
141
|
-
|
|
141
|
+
|
|
142
142
|
it "returns CollectionBinding" do
|
|
143
143
|
assert_kind_of Json::CollectionBinding, Json.binding_for_definition(Def.new(:band, :collection => true))
|
|
144
144
|
end
|
|
145
145
|
end
|
|
146
|
-
|
|
146
|
+
|
|
147
147
|
describe "#representable_bindings" do
|
|
148
148
|
it "returns bindings for each property" do
|
|
149
149
|
assert_equal 2, @band.send(:representable_bindings_for, Json).size
|
|
@@ -151,27 +151,27 @@ module JsonTest
|
|
|
151
151
|
end
|
|
152
152
|
end
|
|
153
153
|
end
|
|
154
|
-
|
|
155
|
-
|
|
154
|
+
|
|
155
|
+
|
|
156
156
|
describe "DCI" do
|
|
157
157
|
module SongRepresenter
|
|
158
158
|
include Representable::JSON
|
|
159
159
|
property :name
|
|
160
160
|
end
|
|
161
|
-
|
|
161
|
+
|
|
162
162
|
module AlbumRepresenter
|
|
163
163
|
include Representable::JSON
|
|
164
164
|
property :best_song, :class => Song, :extend => SongRepresenter
|
|
165
165
|
collection :songs, :class => Song, :extend => [SongRepresenter]
|
|
166
166
|
end
|
|
167
|
-
|
|
168
|
-
|
|
167
|
+
|
|
168
|
+
|
|
169
169
|
it "allows adding the representer by using #extend" do
|
|
170
170
|
module BandRepresenter
|
|
171
171
|
include Representable::JSON
|
|
172
172
|
property :name
|
|
173
173
|
end
|
|
174
|
-
|
|
174
|
+
|
|
175
175
|
civ = Object.new
|
|
176
176
|
civ.instance_eval do
|
|
177
177
|
def name; "CIV"; end
|
|
@@ -179,30 +179,30 @@ module JsonTest
|
|
|
179
179
|
@name = v
|
|
180
180
|
end
|
|
181
181
|
end
|
|
182
|
-
|
|
182
|
+
|
|
183
183
|
civ.extend(BandRepresenter)
|
|
184
|
-
|
|
184
|
+
assert_json "{\"name\":\"CIV\"}", civ.to_json
|
|
185
185
|
end
|
|
186
|
-
|
|
186
|
+
|
|
187
187
|
it "extends contained models when serializing" do
|
|
188
188
|
@album = Album.new(Song.new("I Hate My Brain"), Song.new("Mr. Charisma"))
|
|
189
189
|
@album.extend(AlbumRepresenter)
|
|
190
|
-
|
|
191
|
-
|
|
190
|
+
|
|
191
|
+
assert_json "{\"best_song\":{\"name\":\"Mr. Charisma\"},\"songs\":[{\"name\":\"I Hate My Brain\"},{\"name\":\"Mr. Charisma\"}]}", @album.to_json
|
|
192
192
|
end
|
|
193
|
-
|
|
193
|
+
|
|
194
194
|
it "extends contained models when deserializing" do
|
|
195
195
|
#@album = Album.new(Song.new("I Hate My Brain"), Song.new("Mr. Charisma"))
|
|
196
196
|
@album = Album.new
|
|
197
197
|
@album.extend(AlbumRepresenter)
|
|
198
|
-
|
|
198
|
+
|
|
199
199
|
@album.from_json("{\"best_song\":{\"name\":\"Mr. Charisma\"},\"songs\":[{\"name\":\"I Hate My Brain\"},{\"name\":\"Mr. Charisma\"}]}")
|
|
200
200
|
assert_equal "Mr. Charisma", @album.best_song.name
|
|
201
201
|
end
|
|
202
202
|
end
|
|
203
203
|
end
|
|
204
|
-
|
|
205
|
-
|
|
204
|
+
|
|
205
|
+
|
|
206
206
|
class PropertyTest < MiniTest::Spec
|
|
207
207
|
describe "property :name" do
|
|
208
208
|
class Band
|
|
@@ -210,45 +210,45 @@ module JsonTest
|
|
|
210
210
|
property :name
|
|
211
211
|
attr_accessor :name
|
|
212
212
|
end
|
|
213
|
-
|
|
213
|
+
|
|
214
214
|
it "#from_json creates correct accessors" do
|
|
215
215
|
band = Band.from_json({:name => "Bombshell Rocks"}.to_json)
|
|
216
216
|
assert_equal "Bombshell Rocks", band.name
|
|
217
217
|
end
|
|
218
|
-
|
|
218
|
+
|
|
219
219
|
it "#to_json serializes correctly" do
|
|
220
220
|
band = Band.new
|
|
221
221
|
band.name = "Cigar"
|
|
222
|
-
|
|
223
|
-
|
|
222
|
+
|
|
223
|
+
assert_json '{"name":"Cigar"}', band.to_json
|
|
224
224
|
end
|
|
225
225
|
end
|
|
226
|
-
|
|
226
|
+
|
|
227
227
|
describe ":class => Item" do
|
|
228
228
|
class Label
|
|
229
229
|
include Representable::JSON
|
|
230
230
|
property :name
|
|
231
231
|
attr_accessor :name
|
|
232
232
|
end
|
|
233
|
-
|
|
233
|
+
|
|
234
234
|
class Album
|
|
235
235
|
include Representable::JSON
|
|
236
236
|
property :label, :class => Label
|
|
237
237
|
attr_accessor :label
|
|
238
238
|
end
|
|
239
|
-
|
|
239
|
+
|
|
240
240
|
it "#from_json creates one Item instance" do
|
|
241
241
|
album = Album.from_json('{"label":{"name":"Fat Wreck"}}')
|
|
242
242
|
assert_equal "Fat Wreck", album.label.name
|
|
243
243
|
end
|
|
244
|
-
|
|
244
|
+
|
|
245
245
|
it "#to_json serializes" do
|
|
246
246
|
label = Label.new; label.name = "Fat Wreck"
|
|
247
247
|
album = Album.new; album.label = label
|
|
248
|
-
|
|
249
|
-
|
|
248
|
+
|
|
249
|
+
assert_json '{"label":{"name":"Fat Wreck"}}', album.to_json
|
|
250
250
|
end
|
|
251
|
-
|
|
251
|
+
|
|
252
252
|
describe ":different_name, :class => Label" do
|
|
253
253
|
before do
|
|
254
254
|
@Album = Class.new do
|
|
@@ -257,34 +257,34 @@ module JsonTest
|
|
|
257
257
|
attr_accessor :seller
|
|
258
258
|
end
|
|
259
259
|
end
|
|
260
|
-
|
|
260
|
+
|
|
261
261
|
it "#to_xml respects the different name" do
|
|
262
262
|
label = Label.new; label.name = "Fat Wreck"
|
|
263
263
|
album = @Album.new; album.seller = label
|
|
264
|
-
|
|
265
|
-
|
|
264
|
+
|
|
265
|
+
assert_json "{\"seller\":{\"name\":\"Fat Wreck\"}}", album.to_json(:wrap => false)
|
|
266
266
|
end
|
|
267
267
|
end
|
|
268
268
|
end
|
|
269
|
-
|
|
269
|
+
|
|
270
270
|
describe ":from => :songName" do
|
|
271
271
|
class Song
|
|
272
272
|
include Representable::JSON
|
|
273
273
|
property :name, :from => :songName
|
|
274
274
|
attr_accessor :name
|
|
275
275
|
end
|
|
276
|
-
|
|
276
|
+
|
|
277
277
|
it "respects :from in #from_json" do
|
|
278
278
|
song = Song.from_json({:songName => "Run To The Hills"}.to_json)
|
|
279
279
|
assert_equal "Run To The Hills", song.name
|
|
280
280
|
end
|
|
281
|
-
|
|
281
|
+
|
|
282
282
|
it "respects :from in #to_json" do
|
|
283
283
|
song = Song.new; song.name = "Run To The Hills"
|
|
284
|
-
|
|
284
|
+
assert_json '{"songName":"Run To The Hills"}', song.to_json
|
|
285
285
|
end
|
|
286
286
|
end
|
|
287
|
-
|
|
287
|
+
|
|
288
288
|
describe ":default => :value" do
|
|
289
289
|
before do
|
|
290
290
|
@Album = Class.new do
|
|
@@ -293,39 +293,39 @@ module JsonTest
|
|
|
293
293
|
attr_accessor :name
|
|
294
294
|
end
|
|
295
295
|
end
|
|
296
|
-
|
|
296
|
+
|
|
297
297
|
describe "#from_json" do
|
|
298
298
|
it "uses default when property nil in doc" do
|
|
299
299
|
album = @Album.from_json({}.to_json)
|
|
300
300
|
assert_equal "30 Years Live", album.name
|
|
301
301
|
end
|
|
302
|
-
|
|
302
|
+
|
|
303
303
|
it "uses value from doc when present" do
|
|
304
304
|
album = @Album.from_json({:name => "Live At The Wireless"}.to_json)
|
|
305
305
|
assert_equal "Live At The Wireless", album.name
|
|
306
306
|
end
|
|
307
|
-
|
|
307
|
+
|
|
308
308
|
it "uses value from doc when empty string" do
|
|
309
309
|
album = @Album.from_json({:name => ""}.to_json)
|
|
310
310
|
assert_equal "", album.name
|
|
311
311
|
end
|
|
312
312
|
end
|
|
313
|
-
|
|
313
|
+
|
|
314
314
|
describe "#to_json" do
|
|
315
315
|
it "uses default when not available in object" do
|
|
316
|
-
|
|
316
|
+
assert_json "{\"name\":\"30 Years Live\"}", @Album.new.to_json
|
|
317
317
|
end
|
|
318
|
-
|
|
318
|
+
|
|
319
319
|
it "uses value from represented object when present" do
|
|
320
320
|
album = @Album.new
|
|
321
321
|
album.name = "Live At The Wireless"
|
|
322
|
-
|
|
322
|
+
assert_json "{\"name\":\"Live At The Wireless\"}", album.to_json
|
|
323
323
|
end
|
|
324
|
-
|
|
324
|
+
|
|
325
325
|
it "uses value from represented object when emtpy string" do
|
|
326
326
|
album = @Album.new
|
|
327
327
|
album.name = ""
|
|
328
|
-
|
|
328
|
+
assert_json "{\"name\":\"\"}", album.to_json
|
|
329
329
|
end
|
|
330
330
|
end
|
|
331
331
|
end
|
|
@@ -339,37 +339,37 @@ end
|
|
|
339
339
|
collection :songs
|
|
340
340
|
attr_accessor :songs
|
|
341
341
|
end
|
|
342
|
-
|
|
342
|
+
|
|
343
343
|
it "#from_json creates correct accessors" do
|
|
344
344
|
cd = CD.from_json({:songs => ["Out in the cold", "Microphone"]}.to_json)
|
|
345
345
|
assert_equal ["Out in the cold", "Microphone"], cd.songs
|
|
346
346
|
end
|
|
347
|
-
|
|
347
|
+
|
|
348
348
|
it "#to_json serializes correctly" do
|
|
349
349
|
cd = CD.new
|
|
350
350
|
cd.songs = ["Out in the cold", "Microphone"]
|
|
351
|
-
|
|
352
|
-
|
|
351
|
+
|
|
352
|
+
assert_json '{"songs":["Out in the cold","Microphone"]}', cd.to_json
|
|
353
353
|
end
|
|
354
354
|
end
|
|
355
|
-
|
|
355
|
+
|
|
356
356
|
describe "collection :name, :class => Band" do
|
|
357
357
|
class Band
|
|
358
358
|
include Representable::JSON
|
|
359
359
|
property :name
|
|
360
360
|
attr_accessor :name
|
|
361
|
-
|
|
361
|
+
|
|
362
362
|
def initialize(name="")
|
|
363
363
|
self.name = name
|
|
364
364
|
end
|
|
365
365
|
end
|
|
366
|
-
|
|
366
|
+
|
|
367
367
|
class Compilation
|
|
368
368
|
include Representable::JSON
|
|
369
369
|
collection :bands, :class => Band
|
|
370
370
|
attr_accessor :bands
|
|
371
371
|
end
|
|
372
|
-
|
|
372
|
+
|
|
373
373
|
describe "#from_json" do
|
|
374
374
|
it "pushes collection items to array" do
|
|
375
375
|
cd = Compilation.from_json({:bands => [
|
|
@@ -377,43 +377,43 @@ end
|
|
|
377
377
|
{:name => "Diesel Boy"}]}.to_json)
|
|
378
378
|
assert_equal ["Cobra Skulls", "Diesel Boy"], cd.bands.map(&:name).sort
|
|
379
379
|
end
|
|
380
|
-
|
|
380
|
+
|
|
381
381
|
it "creates emtpy array from default if configured" do
|
|
382
382
|
cd = Compilation.from_json({}.to_json)
|
|
383
383
|
assert_equal [], cd.bands
|
|
384
384
|
end
|
|
385
385
|
end
|
|
386
|
-
|
|
386
|
+
|
|
387
387
|
it "responds to #to_json" do
|
|
388
388
|
cd = Compilation.new
|
|
389
389
|
cd.bands = [Band.new("Diesel Boy"), Band.new("Bad Religion")]
|
|
390
|
-
|
|
391
|
-
|
|
390
|
+
|
|
391
|
+
assert_json '{"bands":[{"name":"Diesel Boy"},{"name":"Bad Religion"}]}', cd.to_json
|
|
392
392
|
end
|
|
393
393
|
end
|
|
394
|
-
|
|
395
|
-
|
|
394
|
+
|
|
395
|
+
|
|
396
396
|
describe ":from => :songList" do
|
|
397
397
|
class Songs
|
|
398
398
|
include Representable::JSON
|
|
399
399
|
collection :tracks, :from => :songList
|
|
400
400
|
attr_accessor :tracks
|
|
401
401
|
end
|
|
402
|
-
|
|
402
|
+
|
|
403
403
|
it "respects :from in #from_json" do
|
|
404
404
|
songs = Songs.from_json({:songList => ["Out in the cold", "Microphone"]}.to_json)
|
|
405
405
|
assert_equal ["Out in the cold", "Microphone"], songs.tracks
|
|
406
406
|
end
|
|
407
|
-
|
|
407
|
+
|
|
408
408
|
it "respects option in #to_json" do
|
|
409
409
|
songs = Songs.new
|
|
410
410
|
songs.tracks = ["Out in the cold", "Microphone"]
|
|
411
|
-
|
|
412
|
-
|
|
411
|
+
|
|
412
|
+
assert_json '{"songList":["Out in the cold","Microphone"]}', songs.to_json
|
|
413
413
|
end
|
|
414
414
|
end
|
|
415
415
|
end
|
|
416
|
-
|
|
416
|
+
|
|
417
417
|
class HashTest < MiniTest::Spec
|
|
418
418
|
describe "hash :songs" do
|
|
419
419
|
before do
|
|
@@ -421,34 +421,34 @@ end
|
|
|
421
421
|
include Representable::JSON
|
|
422
422
|
hash :songs
|
|
423
423
|
end
|
|
424
|
-
|
|
424
|
+
|
|
425
425
|
class SongList
|
|
426
426
|
attr_accessor :songs
|
|
427
427
|
end
|
|
428
|
-
|
|
428
|
+
|
|
429
429
|
@list = SongList.new.extend(representer)
|
|
430
430
|
end
|
|
431
|
-
|
|
431
|
+
|
|
432
432
|
it "renders with #to_json" do
|
|
433
433
|
@list.songs = {:one => "65", :two => "Emo Boy"}
|
|
434
|
-
|
|
434
|
+
assert_json "{\"songs\":{\"one\":\"65\",\"two\":\"Emo Boy\"}}", @list.to_json
|
|
435
435
|
end
|
|
436
|
-
|
|
436
|
+
|
|
437
437
|
it "parses with #from_json" do
|
|
438
438
|
assert_equal({"one" => "65", "two" => ["Emo Boy"]}, @list.from_json("{\"songs\":{\"one\":\"65\",\"two\":[\"Emo Boy\"]}}").songs)
|
|
439
439
|
end
|
|
440
440
|
end
|
|
441
|
-
|
|
441
|
+
|
|
442
442
|
end
|
|
443
|
-
|
|
444
|
-
|
|
443
|
+
|
|
444
|
+
|
|
445
445
|
require 'representable/json/collection'
|
|
446
446
|
class CollectionRepresenterTest < MiniTest::Spec
|
|
447
447
|
module SongRepresenter
|
|
448
448
|
include Representable::JSON
|
|
449
449
|
property :name
|
|
450
450
|
end
|
|
451
|
-
|
|
451
|
+
|
|
452
452
|
describe "JSON::Collection" do
|
|
453
453
|
describe "with contained objects" do
|
|
454
454
|
before do
|
|
@@ -457,42 +457,42 @@ end
|
|
|
457
457
|
items :class => Song, :extend => SongRepresenter
|
|
458
458
|
end
|
|
459
459
|
end
|
|
460
|
-
|
|
460
|
+
|
|
461
461
|
it "renders objects with #to_json" do
|
|
462
|
-
|
|
462
|
+
assert_json "[{\"name\":\"Days Go By\"},{\"name\":\"Can't Take Them All\"}]", [Song.new("Days Go By"), Song.new("Can't Take Them All")].extend(@songs_representer).to_json
|
|
463
463
|
end
|
|
464
|
-
|
|
464
|
+
|
|
465
465
|
it "returns objects array from #from_json" do
|
|
466
466
|
assert_equal [Song.new("Days Go By"), Song.new("Can't Take Them All")], [].extend(@songs_representer).from_json("[{\"name\":\"Days Go By\"},{\"name\":\"Can't Take Them All\"}]")
|
|
467
467
|
end
|
|
468
468
|
end
|
|
469
|
-
|
|
469
|
+
|
|
470
470
|
describe "with contained text" do
|
|
471
471
|
before do
|
|
472
472
|
@songs_representer = Module.new do
|
|
473
473
|
include Representable::JSON::Collection
|
|
474
474
|
end
|
|
475
475
|
end
|
|
476
|
-
|
|
476
|
+
|
|
477
477
|
it "renders contained items #to_json" do
|
|
478
|
-
|
|
478
|
+
assert_json "[\"Days Go By\",\"Can't Take Them All\"]", ["Days Go By", "Can't Take Them All"].extend(@songs_representer).to_json
|
|
479
479
|
end
|
|
480
|
-
|
|
480
|
+
|
|
481
481
|
it "returns objects array from #from_json" do
|
|
482
482
|
assert_equal ["Days Go By", "Can't Take Them All"], [].extend(@songs_representer).from_json("[\"Days Go By\",\"Can't Take Them All\"]")
|
|
483
483
|
end
|
|
484
484
|
end
|
|
485
485
|
end
|
|
486
486
|
end
|
|
487
|
-
|
|
488
|
-
|
|
487
|
+
|
|
488
|
+
|
|
489
489
|
require 'representable/json/hash'
|
|
490
490
|
class HashRepresenterTest < MiniTest::Spec
|
|
491
491
|
module SongRepresenter
|
|
492
492
|
include Representable::JSON
|
|
493
493
|
property :name
|
|
494
494
|
end
|
|
495
|
-
|
|
495
|
+
|
|
496
496
|
describe "JSON::Hash" do # TODO: move to HashTest.
|
|
497
497
|
describe "with contained objects" do
|
|
498
498
|
before do
|
|
@@ -501,47 +501,47 @@ end
|
|
|
501
501
|
values :class => Song, :extend => SongRepresenter
|
|
502
502
|
end
|
|
503
503
|
end
|
|
504
|
-
|
|
504
|
+
|
|
505
505
|
describe "#to_json" do
|
|
506
506
|
it "renders objects" do
|
|
507
|
-
|
|
507
|
+
assert_json "{\"one\":{\"name\":\"Days Go By\"},\"two\":{\"name\":\"Can't Take Them All\"}}", {:one => Song.new("Days Go By"), :two => Song.new("Can't Take Them All")}.extend(@songs_representer).to_json
|
|
508
508
|
end
|
|
509
|
-
|
|
509
|
+
|
|
510
510
|
it "respects :exclude" do
|
|
511
|
-
|
|
511
|
+
assert_json "{\"two\":{\"name\":\"Can't Take Them All\"}}", {:one => Song.new("Days Go By"), :two => Song.new("Can't Take Them All")}.extend(@songs_representer).to_json(:exclude => [:one])
|
|
512
512
|
end
|
|
513
|
-
|
|
513
|
+
|
|
514
514
|
it "respects :include" do
|
|
515
|
-
|
|
515
|
+
assert_json "{\"two\":{\"name\":\"Can't Take Them All\"}}", {:one => Song.new("Days Go By"), :two => Song.new("Can't Take Them All")}.extend(@songs_representer).to_json(:include => [:two])
|
|
516
516
|
end
|
|
517
517
|
end
|
|
518
|
-
|
|
518
|
+
|
|
519
519
|
describe "#from_json" do
|
|
520
520
|
it "returns objects array" do
|
|
521
521
|
assert_equal({"one" => Song.new("Days Go By"), "two" => Song.new("Can't Take Them All")}, {}.extend(@songs_representer).from_json("{\"one\":{\"name\":\"Days Go By\"},\"two\":{\"name\":\"Can't Take Them All\"}}"))
|
|
522
522
|
end
|
|
523
|
-
|
|
523
|
+
|
|
524
524
|
it "respects :exclude" do
|
|
525
525
|
assert_equal({"two" => Song.new("Can't Take Them All")}, {}.extend(@songs_representer).from_json("{\"one\":{\"name\":\"Days Go By\"},\"two\":{\"name\":\"Can't Take Them All\"}}", :exclude => [:one]))
|
|
526
526
|
end
|
|
527
|
-
|
|
527
|
+
|
|
528
528
|
it "respects :include" do
|
|
529
529
|
assert_equal({"one" => Song.new("Days Go By")}, {}.extend(@songs_representer).from_json("{\"one\":{\"name\":\"Days Go By\"},\"two\":{\"name\":\"Can't Take Them All\"}}", :include => [:one]))
|
|
530
530
|
end
|
|
531
531
|
end
|
|
532
532
|
end
|
|
533
|
-
|
|
533
|
+
|
|
534
534
|
describe "with contained text" do
|
|
535
535
|
before do
|
|
536
536
|
@songs_representer = Module.new do
|
|
537
537
|
include Representable::JSON::Collection
|
|
538
538
|
end
|
|
539
539
|
end
|
|
540
|
-
|
|
540
|
+
|
|
541
541
|
it "renders contained items #to_json" do
|
|
542
|
-
|
|
542
|
+
assert_json "[\"Days Go By\",\"Can't Take Them All\"]", ["Days Go By", "Can't Take Them All"].extend(@songs_representer).to_json
|
|
543
543
|
end
|
|
544
|
-
|
|
544
|
+
|
|
545
545
|
it "returns objects array from #from_json" do
|
|
546
546
|
assert_equal ["Days Go By", "Can't Take Them All"], [].extend(@songs_representer).from_json("[\"Days Go By\",\"Can't Take Them All\"]")
|
|
547
547
|
end
|
data/test/representable_test.rb
CHANGED
|
@@ -63,7 +63,7 @@ class RepresentableTest < MiniTest::Spec
|
|
|
63
63
|
end.new
|
|
64
64
|
vd.name = "Vention Dention"
|
|
65
65
|
vd.street_cred = 1
|
|
66
|
-
|
|
66
|
+
assert_json "{\"name\":\"Vention Dention\",\"street_cred\":1}", vd.to_json
|
|
67
67
|
end
|
|
68
68
|
|
|
69
69
|
#it "allows including the concrete representer module only" do
|
|
@@ -113,7 +113,7 @@ class RepresentableTest < MiniTest::Spec
|
|
|
113
113
|
band = Bodyjar.new
|
|
114
114
|
band.name = "Bodyjar"
|
|
115
115
|
|
|
116
|
-
|
|
116
|
+
assert_json "{\"band\":{\"name\":\"Bodyjar\"}}", band.to_json
|
|
117
117
|
assert_xml_equal "<band><name>Bodyjar</name></band>", band.to_xml
|
|
118
118
|
end
|
|
119
119
|
|
|
@@ -130,7 +130,7 @@ class RepresentableTest < MiniTest::Spec
|
|
|
130
130
|
|
|
131
131
|
@song = Song.new("Days Go By")
|
|
132
132
|
assert_xml_equal "<song name=\"Days Go By\"/>", @song.extend(SongXmlRepresenter).to_xml
|
|
133
|
-
|
|
133
|
+
assert_json "{\"name\":\"Days Go By\"}", @song.extend(SongJsonRepresenter).to_json
|
|
134
134
|
end
|
|
135
135
|
end
|
|
136
136
|
|
|
@@ -310,17 +310,32 @@ class RepresentableTest < MiniTest::Spec
|
|
|
310
310
|
assert_equal({"name"=>"No One's Choice","groupies"=>false}, @band.send(:create_representation_with, {}, {}, Representable::JSON))
|
|
311
311
|
end
|
|
312
312
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
313
|
+
describe "when :render_nil is true" do
|
|
314
|
+
it "includes nil attribute" do
|
|
315
|
+
mod = Module.new do
|
|
316
|
+
include Representable::JSON
|
|
317
|
+
property :name
|
|
318
|
+
property :groupies, :render_nil => true
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
@band.extend(mod) # FIXME: use clean object.
|
|
322
|
+
@band.groupies = nil
|
|
323
|
+
hash = @band.send(:create_representation_with, {}, {}, Representable::JSON)
|
|
324
|
+
assert_equal({"name"=>"No One's Choice", "groupies" => nil}, hash)
|
|
318
325
|
end
|
|
319
326
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
327
|
+
it "includes nil attribute without extending" do
|
|
328
|
+
mod = Module.new do
|
|
329
|
+
include Representable::JSON
|
|
330
|
+
property :name
|
|
331
|
+
property :groupies, :render_nil => true, :extend => BandRepresentation
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
@band.extend(mod) # FIXME: use clean object.
|
|
335
|
+
@band.groupies = nil
|
|
336
|
+
hash = @band.send(:create_representation_with, {}, {}, Representable::JSON)
|
|
337
|
+
assert_equal({"name"=>"No One's Choice", "groupies" => nil}, hash)
|
|
338
|
+
end
|
|
324
339
|
end
|
|
325
340
|
end
|
|
326
341
|
|
data/test/test_helper.rb
CHANGED
|
@@ -24,7 +24,7 @@ class Song
|
|
|
24
24
|
def initialize(name=nil)
|
|
25
25
|
@name = name
|
|
26
26
|
end
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
def ==(other)
|
|
29
29
|
name == other.name
|
|
30
30
|
end
|
|
@@ -36,6 +36,16 @@ module XmlHelper
|
|
|
36
36
|
end
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
+
module AssertJson
|
|
40
|
+
module Assertions
|
|
41
|
+
def assert_json(expected, actual, msg=nil)
|
|
42
|
+
msg = message(msg, "") { diff expected, actual }
|
|
43
|
+
assert(expected.split("").sort == actual.split("").sort, msg)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
39
48
|
MiniTest::Spec.class_eval do
|
|
49
|
+
include AssertJson::Assertions
|
|
40
50
|
include XmlHelper
|
|
41
51
|
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class TestHelperTest < MiniTest::Spec
|
|
4
|
+
describe "#assert_json" do
|
|
5
|
+
it "tests for equality" do
|
|
6
|
+
assert_json "{\"songs\":{\"one\":\"65\",\"two\":\"Emo Boy\"}}", "{\"songs\":{\"one\":\"65\",\"two\":\"Emo Boy\"}}"
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "allows different key orders" do
|
|
10
|
+
assert_json "{\"songs\":{\"one\":\"65\",\"two\":\"Emo Boy\"}}", "{\"songs\":{\"two\":\"Emo Boy\",\"one\":\"65\"}}"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "complains when expected hash is subset" do
|
|
14
|
+
assert_raises MiniTest::Assertion do
|
|
15
|
+
assert_json "{\"songs\":{\"one\":\"65\"}}", "{\"songs\":{\"two\":\"Emo Boy\",\"one\":\"65\"}}"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it "complains when source hash is subset" do
|
|
20
|
+
assert_raises MiniTest::Assertion do
|
|
21
|
+
assert_json "{\"songs\":{\"two\":\"Emo Boy\",\"one\":\"65\"}}", "{\"songs\":{\"one\":\"65\"}}"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
data/test/xml_test.rb
CHANGED
|
@@ -11,7 +11,9 @@ class Band
|
|
|
11
11
|
end
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
class Album
|
|
15
|
+
attr_accessor :songs
|
|
16
|
+
end
|
|
15
17
|
|
|
16
18
|
|
|
17
19
|
class XmlTest < MiniTest::Spec
|
|
@@ -319,14 +321,14 @@ class CollectionTest < MiniTest::Spec
|
|
|
319
321
|
|
|
320
322
|
|
|
321
323
|
describe ":from" do
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
324
|
+
let(:xml) {
|
|
325
|
+
Module.new do
|
|
326
|
+
include Representable::XML
|
|
327
|
+
collection :songs, :from => :song
|
|
328
|
+
end }
|
|
327
329
|
|
|
328
330
|
it "collects untyped items" do
|
|
329
|
-
album = Album.from_xml(%{
|
|
331
|
+
album = Album.new.extend(xml).from_xml(%{
|
|
330
332
|
<album>
|
|
331
333
|
<song>Two Kevins</song>
|
|
332
334
|
<song>Wright and Rong</song>
|
|
@@ -336,6 +338,46 @@ class CollectionTest < MiniTest::Spec
|
|
|
336
338
|
assert_equal ["Laundry Basket", "Two Kevins", "Wright and Rong"].sort, album.songs.sort
|
|
337
339
|
end
|
|
338
340
|
end
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
describe ":wrap" do
|
|
344
|
+
let (:album) { Album.new.extend(xml) }
|
|
345
|
+
let (:xml) {
|
|
346
|
+
Module.new do
|
|
347
|
+
include Representable::XML
|
|
348
|
+
collection :songs, :from => :song, :wrap => :songs
|
|
349
|
+
end }
|
|
350
|
+
|
|
351
|
+
describe "#from_xml" do
|
|
352
|
+
it "finds items in wrapped collection" do
|
|
353
|
+
album.from_xml(%{
|
|
354
|
+
<album>
|
|
355
|
+
<songs>
|
|
356
|
+
<song>Two Kevins</song>
|
|
357
|
+
<song>Wright and Rong</song>
|
|
358
|
+
<song>Laundry Basket</song>
|
|
359
|
+
</songs>
|
|
360
|
+
</album>
|
|
361
|
+
})
|
|
362
|
+
assert_equal ["Laundry Basket", "Two Kevins", "Wright and Rong"].sort, album.songs.sort
|
|
363
|
+
end
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
describe "#to_xml" do
|
|
367
|
+
it "wraps items" do
|
|
368
|
+
album.songs = ["Laundry Basket", "Two Kevins", "Wright and Rong"]
|
|
369
|
+
assert_xml_equal %{
|
|
370
|
+
<album>
|
|
371
|
+
<songs>
|
|
372
|
+
<song>Laundry Basket</song>
|
|
373
|
+
<song>Two Kevins</song>
|
|
374
|
+
<song>Wright and Rong</song>
|
|
375
|
+
</songs>
|
|
376
|
+
</album>
|
|
377
|
+
}, album.to_xml
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
end
|
|
339
381
|
|
|
340
382
|
require 'representable/xml/hash'
|
|
341
383
|
describe "XML::AttributeHash" do # TODO: move to HashTest.
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: representable
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.2.
|
|
4
|
+
version: 1.2.4
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2012-
|
|
12
|
+
date: 2012-08-25 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: nokogiri
|
|
@@ -155,6 +155,7 @@ files:
|
|
|
155
155
|
- LICENSE
|
|
156
156
|
- README.rdoc
|
|
157
157
|
- Rakefile
|
|
158
|
+
- gemfiles/Gemfile.mongoid-2.4
|
|
158
159
|
- lib/representable.rb
|
|
159
160
|
- lib/representable/binding.rb
|
|
160
161
|
- lib/representable/bindings/json_bindings.rb
|
|
@@ -179,6 +180,7 @@ files:
|
|
|
179
180
|
- test/polymorphic_test.rb
|
|
180
181
|
- test/representable_test.rb
|
|
181
182
|
- test/test_helper.rb
|
|
183
|
+
- test/test_helper_test.rb
|
|
182
184
|
- test/xml_bindings_test.rb
|
|
183
185
|
- test/xml_test.rb
|
|
184
186
|
homepage: http://representable.apotomo.de
|