serialisable 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +45 -0
- data/Rakefile +9 -0
- data/lib/serialisable.rb +136 -0
- data/lib/serialisable/version.rb +3 -0
- data/spec/serialisable_spec.rb +312 -0
- data/spec/spec_helper.rb +6 -0
- metadata +94 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6fd4b076b8bdcf3bb038edb81861f995b5c64e03
|
4
|
+
data.tar.gz: eff45ba4141fb2eeff36635e4ffa21de831b1dd8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d3c9d0c2e3e2d7f8973da83a85143e3a8a2e2ffa16770c4e19c074fbd2672e1543b7e1ff95dd3d02ef0b61c13fc00a4e0f034cd587db148705ea146ad946a163
|
7
|
+
data.tar.gz: 86677bd6af34fe7e3f5859a6266e55e67cd0d5dfd87b12b2dfde0b8dccfad10ea83896bcb69a1b8b66c62b310d3380fa13d72b57286dbb78cbc43a978fa2c1f2
|
data/README.md
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# Serialisable
|
2
|
+
|
3
|
+
Simple xml to object deserialisation for Ruby, built on top of Nokogiri (at the
|
4
|
+
moment).
|
5
|
+
|
6
|
+
This is still in the hacky stage, so you probably shouldn't use it...
|
7
|
+
|
8
|
+
``` xml
|
9
|
+
<?xml version="1.0" encoding="utf-8"?>
|
10
|
+
<plays>
|
11
|
+
<play>
|
12
|
+
<track>505</track>
|
13
|
+
<artist>Arctic Monkeys</artist>
|
14
|
+
<time>2013-10-12T15:34:50Z</time>
|
15
|
+
</play>
|
16
|
+
<play>
|
17
|
+
<track>Windowlicker</track>
|
18
|
+
<artist>Aphex Twin</artist>
|
19
|
+
<time>2013-10-12T15:37:43Z</time>
|
20
|
+
</play>
|
21
|
+
</plays>
|
22
|
+
```
|
23
|
+
|
24
|
+
``` ruby
|
25
|
+
require 'serialisable'
|
26
|
+
require 'time'
|
27
|
+
|
28
|
+
class Play
|
29
|
+
extend Serialisable
|
30
|
+
|
31
|
+
root 'play'
|
32
|
+
element :track, 'track'
|
33
|
+
element :artist, 'artist'
|
34
|
+
element :time, 'time', Time # an object responding to #parse
|
35
|
+
end
|
36
|
+
|
37
|
+
class Plays
|
38
|
+
extend Serialisable
|
39
|
+
|
40
|
+
root 'plays'
|
41
|
+
elements :plays, Play # a Serialisable object
|
42
|
+
end
|
43
|
+
|
44
|
+
plays = Plays.deserialise(File.read('plays.xml')).plays
|
45
|
+
```
|
data/Rakefile
ADDED
data/lib/serialisable.rb
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require_relative 'serialisable/selector'
|
3
|
+
|
4
|
+
module Serialisable
|
5
|
+
def root(selector)
|
6
|
+
@__root = selector
|
7
|
+
@__element = {}
|
8
|
+
@__elements = {}
|
9
|
+
@__attribute = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def attribute(name, selector, type=String)
|
13
|
+
@__attribute[name] = [selector, type]
|
14
|
+
end
|
15
|
+
|
16
|
+
def element(name, selector, type=String)
|
17
|
+
@__element[name] = [selector, type]
|
18
|
+
end
|
19
|
+
|
20
|
+
def elements(name, *args)
|
21
|
+
case args.size
|
22
|
+
when 1
|
23
|
+
klass = args.first
|
24
|
+
@__elements[name] = [nil, klass]
|
25
|
+
when 2
|
26
|
+
selector, type = args
|
27
|
+
@__elements[name] = [selector, type]
|
28
|
+
else
|
29
|
+
raise ArgumentError
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def deserialise(xml)
|
34
|
+
__deserialise Nokogiri::XML(xml)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def __deserialise_all(doc)
|
40
|
+
doc = doc.children.find_all {|node| node.name == @__root }
|
41
|
+
|
42
|
+
attrs_list = doc.map do |node|
|
43
|
+
attrs = SerialisableHelpers.get_multiples(node, @__elements)
|
44
|
+
attrs += SerialisableHelpers.get_singles(node, @__element)
|
45
|
+
attrs += SerialisableHelpers.get_attributes(node, @__attribute)
|
46
|
+
|
47
|
+
attrs
|
48
|
+
end
|
49
|
+
|
50
|
+
objs = []
|
51
|
+
attrs_list.each do |attrs|
|
52
|
+
attrs = Hash[attrs]
|
53
|
+
|
54
|
+
attrs.each do |key, value|
|
55
|
+
define_method key do
|
56
|
+
instance_variable_get(:@__serialisable_attrs)[key]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
obj = new
|
61
|
+
obj.instance_variable_set(:@__serialisable_attrs, attrs)
|
62
|
+
objs << obj
|
63
|
+
end
|
64
|
+
|
65
|
+
objs
|
66
|
+
end
|
67
|
+
|
68
|
+
def __deserialise(doc)
|
69
|
+
doc = doc.children.find {|node| node.name == @__root }
|
70
|
+
|
71
|
+
attrs = SerialisableHelpers.get_multiples(doc, @__elements)
|
72
|
+
attrs += SerialisableHelpers.get_singles(doc, @__element)
|
73
|
+
attrs += SerialisableHelpers.get_attributes(doc, @__attribute)
|
74
|
+
|
75
|
+
attrs = Hash[attrs]
|
76
|
+
|
77
|
+
attrs.each do |key, value|
|
78
|
+
define_method key do
|
79
|
+
instance_variable_get(:@__serialisable_attrs)[key]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
obj = new
|
84
|
+
obj.instance_variable_set(:@__serialisable_attrs, attrs)
|
85
|
+
obj
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
module SerialisableHelpers
|
90
|
+
extend self
|
91
|
+
|
92
|
+
def get_multiples(root, hash)
|
93
|
+
hash.map do |name, (selector, type)|
|
94
|
+
if type.respond_to?(:__deserialise_all, true)
|
95
|
+
[name, type.send(:__deserialise_all, root)]
|
96
|
+
else
|
97
|
+
values = root.children.find_all {|node| node.name == selector }
|
98
|
+
.map {|node| node.children.to_s }
|
99
|
+
.map {|value| parse_type(value, type) }
|
100
|
+
|
101
|
+
[name, values]
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def get_singles(root, hash)
|
107
|
+
hash.map do |name, (selector, type)|
|
108
|
+
if selector.respond_to?(:__deserialise, true)
|
109
|
+
[name, selector.send(:__deserialise, root)]
|
110
|
+
else
|
111
|
+
value = root.children.find {|node| node.name == selector }.children.to_s
|
112
|
+
value = parse_type(value, type)
|
113
|
+
|
114
|
+
[name, value]
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def get_attributes(root, hash)
|
120
|
+
hash.map do |name, (selector, type)|
|
121
|
+
value = root.attributes[selector].value
|
122
|
+
value = parse_type(value, type)
|
123
|
+
|
124
|
+
[name, value]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Parses the value read from xml if the type given responds to the method
|
129
|
+
# #parse, otherwise returns the string value.
|
130
|
+
#
|
131
|
+
# @param value [String]
|
132
|
+
# @param type [#parse]
|
133
|
+
def parse_type(value, type)
|
134
|
+
type.respond_to?(:parse) ? type.parse(value) : value
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,312 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
describe Serialisable do
|
4
|
+
|
5
|
+
describe '#element' do
|
6
|
+
describe 'with a single element' do
|
7
|
+
|
8
|
+
subject {
|
9
|
+
Class.new {
|
10
|
+
extend Serialisable
|
11
|
+
|
12
|
+
root 'root'
|
13
|
+
element :node, 'node'
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
17
|
+
let(:xml) {
|
18
|
+
'<?xml version="1.0" encoding="utf-8"?><root><node>value</node></root>'
|
19
|
+
}
|
20
|
+
|
21
|
+
it 'takes xml and returns an object' do
|
22
|
+
subject.deserialise(xml).node.must_equal 'value'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'with an single element with a type to parse' do
|
27
|
+
subject {
|
28
|
+
require 'time'
|
29
|
+
|
30
|
+
Class.new {
|
31
|
+
extend Serialisable
|
32
|
+
|
33
|
+
root 'root'
|
34
|
+
element :time, 'time', Time
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
let(:xml) {
|
39
|
+
'<?xml version="1.0" encoding="utf-8"?><root><time>2013-07-04T13:23:34Z</time></root>'
|
40
|
+
}
|
41
|
+
|
42
|
+
it 'takes xml and returns an object with the type parsed' do
|
43
|
+
subject.deserialise(xml).time.must_equal Time.utc(2013, 7, 4, 13, 23, 34)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'with a nested serialisable' do
|
48
|
+
subject {
|
49
|
+
Class.new {
|
50
|
+
extend Serialisable
|
51
|
+
|
52
|
+
root 'songs'
|
53
|
+
element :song, Class.new {
|
54
|
+
extend Serialisable
|
55
|
+
|
56
|
+
root 'song'
|
57
|
+
element :artist, 'artist'
|
58
|
+
element :name, 'name'
|
59
|
+
}
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
let(:xml) {
|
64
|
+
<<EOS
|
65
|
+
<?xml version="1.0" encoding="utf-8"?>
|
66
|
+
<songs>
|
67
|
+
<song>
|
68
|
+
<artist>Arctic Monkeys</artist>
|
69
|
+
<name>505</name>
|
70
|
+
</song>
|
71
|
+
</songs>
|
72
|
+
EOS
|
73
|
+
}
|
74
|
+
|
75
|
+
it 'deserialises the nested object correctly' do
|
76
|
+
result = subject.deserialise(xml)
|
77
|
+
|
78
|
+
result.song.artist.must_equal 'Arctic Monkeys'
|
79
|
+
result.song.name.must_equal '505'
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe '#elements' do
|
85
|
+
describe 'with a single list of elements' do
|
86
|
+
subject {
|
87
|
+
require 'time'
|
88
|
+
|
89
|
+
Class.new {
|
90
|
+
extend Serialisable
|
91
|
+
|
92
|
+
root 'root'
|
93
|
+
elements :times, 'time', Time
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
let (:xml) {
|
98
|
+
'<?xml version="1.0" encoding="utf-8"?><root><time>2013-05-06T00:00:00Z</time><time>2013-06-07T00:00:00Z</time></root>'
|
99
|
+
}
|
100
|
+
|
101
|
+
it 'takes xml and returns an object with a list of results' do
|
102
|
+
times = subject.deserialise(xml).times
|
103
|
+
times.must_equal [Time.utc(2013, 5, 6), Time.utc(2013, 6, 7)]
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe 'with a list of nested objects' do
|
108
|
+
subject {
|
109
|
+
Class.new {
|
110
|
+
extend Serialisable
|
111
|
+
|
112
|
+
root 'songs'
|
113
|
+
elements :songs, Class.new {
|
114
|
+
extend Serialisable
|
115
|
+
|
116
|
+
root 'song'
|
117
|
+
element :artist, 'artist'
|
118
|
+
element :name, 'name'
|
119
|
+
}
|
120
|
+
}
|
121
|
+
}
|
122
|
+
|
123
|
+
let(:xml) {
|
124
|
+
<<EOS
|
125
|
+
<?xml version="1.0" encoding="utf-8"?>
|
126
|
+
<songs>
|
127
|
+
<song>
|
128
|
+
<artist>Arctic Monkeys</artist>
|
129
|
+
<name>505</name>
|
130
|
+
</song>
|
131
|
+
<song>
|
132
|
+
<artist>Aphex Twin</artist>
|
133
|
+
<name>Windowlicker</name>
|
134
|
+
</song>
|
135
|
+
</songs>
|
136
|
+
EOS
|
137
|
+
}
|
138
|
+
|
139
|
+
it 'takes xml and returns an object with a list of nested objects' do
|
140
|
+
result = subject.deserialise(xml)
|
141
|
+
|
142
|
+
result.songs.length.must_equal 2
|
143
|
+
|
144
|
+
result.songs[0].artist.must_equal 'Arctic Monkeys'
|
145
|
+
result.songs[0].name.must_equal '505'
|
146
|
+
|
147
|
+
result.songs[1].artist.must_equal 'Aphex Twin'
|
148
|
+
result.songs[1].name.must_equal 'Windowlicker'
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'raises an exception if not given less than two arguments' do
|
153
|
+
lambda {
|
154
|
+
Class.new {
|
155
|
+
extend Serialisable
|
156
|
+
|
157
|
+
elements :name
|
158
|
+
}
|
159
|
+
}.must_raise ArgumentError
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'raises an exception if given more than three arguments' do
|
163
|
+
lambda {
|
164
|
+
Class.new {
|
165
|
+
extend Serialisable
|
166
|
+
|
167
|
+
elements :name, 'one', 'two', 'three'
|
168
|
+
}
|
169
|
+
}.must_raise ArgumentError
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe '#attribute' do
|
174
|
+
describe 'with a single attribute' do
|
175
|
+
subject {
|
176
|
+
Class.new {
|
177
|
+
extend Serialisable
|
178
|
+
|
179
|
+
root 'item'
|
180
|
+
attribute :id, 'id'
|
181
|
+
}
|
182
|
+
}
|
183
|
+
|
184
|
+
let(:xml) {
|
185
|
+
'<?xml version="1.0" encoding="utf-8"?><item id="1234" />'
|
186
|
+
}
|
187
|
+
|
188
|
+
it 'takes xml and returns an object with the attribute deserialised' do
|
189
|
+
subject.deserialise(xml).id.must_equal '1234'
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe 'with an attribute with a type' do
|
194
|
+
subject {
|
195
|
+
require 'time'
|
196
|
+
Class.new {
|
197
|
+
extend Serialisable
|
198
|
+
|
199
|
+
root 'item'
|
200
|
+
attribute :at, 'at', Time
|
201
|
+
}
|
202
|
+
}
|
203
|
+
|
204
|
+
let(:xml) {
|
205
|
+
'<?xml version="1.0" encoding="utf-8"?><item at="2013-10-10T15:30:34Z" />'
|
206
|
+
}
|
207
|
+
|
208
|
+
it 'takes xml and returns an object with the attribute parsed' do
|
209
|
+
subject.deserialise(xml).at.must_equal Time.utc(2013, 10, 10, 15, 30, 34)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
describe 'with an attribute on a nested object' do
|
214
|
+
subject {
|
215
|
+
Class.new {
|
216
|
+
extend Serialisable
|
217
|
+
|
218
|
+
root 'items'
|
219
|
+
element :item, Class.new {
|
220
|
+
extend Serialisable
|
221
|
+
|
222
|
+
root 'item'
|
223
|
+
attribute :id, 'id'
|
224
|
+
}
|
225
|
+
}
|
226
|
+
}
|
227
|
+
|
228
|
+
let(:xml) {
|
229
|
+
'<?xml version="1.0" encoding="utf-8"?><items><item id="1234" /></items>'
|
230
|
+
}
|
231
|
+
|
232
|
+
it 'takes xml and returns an object with the attribute deserialised' do
|
233
|
+
subject.deserialise(xml).item.id.must_equal '1234'
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
describe 'with an attribute on a list of nested object' do
|
238
|
+
subject {
|
239
|
+
Class.new {
|
240
|
+
extend Serialisable
|
241
|
+
|
242
|
+
root 'items'
|
243
|
+
elements :items, Class.new {
|
244
|
+
extend Serialisable
|
245
|
+
|
246
|
+
root 'item'
|
247
|
+
attribute :id, 'id'
|
248
|
+
}
|
249
|
+
}
|
250
|
+
}
|
251
|
+
|
252
|
+
let(:xml) {
|
253
|
+
'<?xml version="1.0" encoding="utf-8"?><items><item id="1234" /><item id="5678" /></items>'
|
254
|
+
}
|
255
|
+
|
256
|
+
it 'takes xml and returns an object with the attribute deserialised' do
|
257
|
+
items = subject.deserialise(xml).items
|
258
|
+
|
259
|
+
items[0].id.must_equal '1234'
|
260
|
+
items[1].id.must_equal '5678'
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
describe 'all together' do
|
266
|
+
let(:xml) {
|
267
|
+
<<EOS
|
268
|
+
<?xml version="1.0" encoding="utf-8"?>
|
269
|
+
<plays>
|
270
|
+
<play>
|
271
|
+
<track>505</track>
|
272
|
+
<artist>Arctic Monkeys</artist>
|
273
|
+
<time>2013-10-12T15:34:50Z</time>
|
274
|
+
</play>
|
275
|
+
<play>
|
276
|
+
<track>Windowlicker</track>
|
277
|
+
<artist>Aphex Twin</artist>
|
278
|
+
<time>2013-10-12T15:37:43Z</time>
|
279
|
+
</play>
|
280
|
+
</plays>
|
281
|
+
EOS
|
282
|
+
}
|
283
|
+
|
284
|
+
subject {
|
285
|
+
Class.new {
|
286
|
+
extend Serialisable
|
287
|
+
|
288
|
+
root 'plays'
|
289
|
+
elements :plays, Class.new {
|
290
|
+
extend Serialisable
|
291
|
+
|
292
|
+
root 'play'
|
293
|
+
element :track, 'track'
|
294
|
+
element :artist, 'artist'
|
295
|
+
element :time, 'time', Time
|
296
|
+
}
|
297
|
+
}
|
298
|
+
}
|
299
|
+
|
300
|
+
it 'works!' do
|
301
|
+
plays = subject.deserialise(xml).plays
|
302
|
+
|
303
|
+
plays[0].track.must_equal '505'
|
304
|
+
plays[0].artist.must_equal 'Arctic Monkeys'
|
305
|
+
plays[0].time.must_equal Time.utc(2013, 10, 12, 15, 34, 50)
|
306
|
+
|
307
|
+
plays[1].track.must_equal 'Windowlicker'
|
308
|
+
plays[1].artist.must_equal 'Aphex Twin'
|
309
|
+
plays[1].time.must_equal Time.utc(2013, 10, 12, 15, 37, 43)
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: serialisable
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Joshua Hawxwell
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: nokogiri
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: minitest
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '5.2'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '5.2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: mocha
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.0'
|
55
|
+
description: |2
|
56
|
+
Serialisable provides a simple DSL for turning xml into ruby objects.
|
57
|
+
email: m@hawx.me
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- README.md
|
63
|
+
- Rakefile
|
64
|
+
- lib/serialisable/version.rb
|
65
|
+
- lib/serialisable.rb
|
66
|
+
- spec/spec_helper.rb
|
67
|
+
- spec/serialisable_spec.rb
|
68
|
+
homepage: http://github.com/hawx/serialisable
|
69
|
+
licenses:
|
70
|
+
- MIT
|
71
|
+
metadata: {}
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
requirements: []
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 2.0.14
|
89
|
+
signing_key:
|
90
|
+
specification_version: 4
|
91
|
+
summary: Serialisable allows easy xml deserialisation
|
92
|
+
test_files:
|
93
|
+
- spec/spec_helper.rb
|
94
|
+
- spec/serialisable_spec.rb
|