serialisable 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3d1e4397bf79459b96b569b558d46de21f445186
4
- data.tar.gz: 6d175852e351b5bd7de719fb2ad63c7390b819d5
3
+ metadata.gz: 398799ae5550e1a9379df90c241567166e12eeb7
4
+ data.tar.gz: d785cbed52c32917be7d480a865f80dffcc1316d
5
5
  SHA512:
6
- metadata.gz: 864ee9628a74de37b91a14615db426b6e9146b653d1846449dbfee1c51ea553d91192490b2522c45b73b2468b025cbbc8b00dffa8bc64c27cf09f2681a96f72f
7
- data.tar.gz: 53d06c080b9c9c1650836e0e42fd310057c586999abb598db6d50c6a877ca314987e501ca508dc32a3564b69b0d7b0c829101db26d2f9438f59d14c5d8a5d3b5
6
+ metadata.gz: 1ff5997b676acdbc6335fc0d1525eaa3196738a0c398dfb5b35adbe2fc3291b57b0a7304ed4bdf9ed0e6f5a1087072df8a7e2e274407949b64a186e07fa3c4a8
7
+ data.tar.gz: 1c1d395a6771858063ff8ab519e1ffabf808a32365bda9933108af81bd0f27b18b41442e3e68077db0654c4854e78f6f448b5c08dae21d8250df984fec94d48c
@@ -1,34 +1,218 @@
1
1
  require 'nokogiri'
2
-
2
+ require_relative 'serialisable/selector'
3
+
4
+ # Serialisable allows you to easily define an object that can deserialise xml
5
+ # into instances of itself. It provides a simple but powerful DSL for defining
6
+ # elements and attributes.
7
+ #
8
+ # require 'serialisable'
9
+ # require 'time'
10
+ #
11
+ # class Play
12
+ # extend Serialisable
13
+ #
14
+ # root 'play'
15
+ # element :artist, 'artist'
16
+ # element :name, 'name'
17
+ # element :played_at, 'playedat', Time
18
+ # end
19
+ #
20
+ # class User
21
+ # extend Serialisable
22
+ #
23
+ # root 'user'
24
+ # attribute :id, 'id', :to_i
25
+ # element :name, 'name'
26
+ # elements :plays, 'plays', Play
27
+ #
28
+ # def inspect
29
+ # "#<User:#{id} #{name}>"
30
+ # end
31
+ # end
32
+ #
33
+ # user = User.deserialise <<XML
34
+ # <?xml version="1.0" encoding="utf-8"?>
35
+ # <user id="12452">
36
+ # <name>John Doe</name>
37
+ # <plays>
38
+ # <play>
39
+ # <artist>Arctic Monkeys</artist>
40
+ # <name>505</name>
41
+ # <playedat>2014-02-03T12:23:55Z</playedat>
42
+ # </play>
43
+ # <play>
44
+ # <artist>Aphex Twin</artist>
45
+ # <name>Windowlicker</name>
46
+ # <playedat>2014-02-03T12:26:13Z</playedat>
47
+ # </play>
48
+ # </plays>
49
+ # </user>
50
+ # XML
51
+ #
52
+ # p user
53
+ # #=> #<User:12452 John Doe>
54
+ # p user.plays.map(&:name)
55
+ # #=> ["505", "Windowlicker"]
56
+ #
57
+ #
58
+ # @example Type as Symbol
59
+ #
60
+ # class Count
61
+ # extend Serialisable
62
+ #
63
+ # root 'count'
64
+ # attribute :value, 'value', :to_i
65
+ # end
66
+ #
67
+ # count = Count.deserialise <<XML
68
+ # <?xml version="1.0" encoding="utf-8"?>
69
+ # <count value="500" />
70
+ # XML
71
+ #
72
+ # p count.value #=> 500
73
+ #
74
+ #
75
+ # @example Type as object responding to +#parse+
76
+ #
77
+ # class IntParser
78
+ # def parse(str); str.to_i; end
79
+ # end
80
+ #
81
+ # class Count
82
+ # extend Serialisable
83
+ #
84
+ # root 'count'
85
+ # attribute :value, 'value', IntParser
86
+ # end
87
+ #
88
+ # count = Count.deserialise <<XML
89
+ # <?xml version="1.0" encoding="utf-8"?>
90
+ # <count value="500" />
91
+ # XML
92
+ #
93
+ # p count.value #=> 500
94
+ #
95
+ #
3
96
  module Serialisable
97
+ def self.extended(obj)
98
+ obj.instance_variable_set(:@__selectors, [])
99
+ end
100
+
101
+ # Define the element that makes up the root for the class.
102
+ #
103
+ # @param selector [String] Name of xml element to mark as the root.
4
104
  def root(selector)
5
105
  @__root = selector
6
- @__element = {}
7
- @__elements = {}
8
- @__attribute = {}
9
106
  end
10
107
 
11
- def attribute(name, selector, type=String)
12
- @__attribute[name] = [selector, type]
108
+ # Define an attribute selector. This will match an attribute in the defined
109
+ # root element that has the name given by +selector+.
110
+ #
111
+ # @param name [Symbol] Name of the method to be defined on the class that
112
+ # returns the value matched.
113
+ # @param selector [String] Name of xml attribute to match against.
114
+ # @param type [Symbol, #parse] If a symbol is given the matched string will
115
+ # have the method named by it called on it. If an object responding to
116
+ # #parse is given then the string value will be passed to that method.
117
+ def attribute(name, selector, type = nil)
118
+ @__selectors << Selector::Attribute.new(name, selector, type)
13
119
  end
14
120
 
15
- def element(name, selector, type=String)
16
- @__element[name] = [selector, type]
121
+ # Define an element selector. This will match a node in the defined root
122
+ # element that has the name given by +selector+.
123
+ #
124
+ # @overload element(name, serialisable)
125
+ # Use this when the node being matched contains nested xml.
126
+ #
127
+ # @param name [Symbol] Name of the method to be defined on the class that
128
+ # returns the value matched.
129
+ # @param serialisable [Serialisable]
130
+ #
131
+ # @overload element(name, root, serialisable)
132
+ # Use this when the node being matched contains nested xml and the root
133
+ # needs to be set.
134
+ #
135
+ # @param name [Symbol] Name of the method to be defined on the class that
136
+ # returns the value matched.
137
+ # @param root [String] Name of the root of the nested element, this
138
+ # overrides any root set on the +serialisable+ passed.
139
+ # @param serialisable [Serialisable] Serialisable object that represents
140
+ # the nested element.
141
+ #
142
+ # @overload element(name, selector, type=nil)
143
+ # Use this when the node only contains text.
144
+ #
145
+ # @param name [Symbol] Name of the method to be defined on the class that
146
+ # returns the value matched.
147
+ # @param selector [String] Name of xml attribute to match against.
148
+ # @param type [Symbol, #parse] If a symbol is given the matched string will
149
+ # have the method named by it called on it. If an object responding to
150
+ # #parse is given then the string value will be passed to that method.
151
+ #
152
+ def element(name, selector, type = nil)
153
+ if selector.respond_to?(:__deserialise, true)
154
+ @__selectors << Selector::Nested.new(name, selector)
155
+
156
+ elsif type.respond_to?(:__deserialise, true)
157
+ cloned_type = type.clone
158
+ cloned_type.instance_variable_set(:@__root, selector)
159
+ @__selectors << Selector::Nested.new(name, cloned_type)
160
+
161
+ else
162
+ @__selectors << Selector::Node.new(name, selector, type)
163
+ end
17
164
  end
18
165
 
19
- def elements(name, *args)
20
- case args.size
21
- when 1
22
- klass = args.first
23
- @__elements[name] = [nil, klass]
24
- when 2
25
- selector, type = args
26
- @__elements[name] = [selector, type]
166
+ # Define an elements selector. This will match all nodes in the defined root
167
+ # element that has the name given by +selector+. The method created by this
168
+ # will return an array of matching values.
169
+ #
170
+ # @overload elements(name, serialisable)
171
+ # Use this when the nodes being matched contains nested xml.
172
+ #
173
+ # @param name [Symbol] Name of the method to be defined on the class that
174
+ # returns the value matched.
175
+ # @param serialisable [Serialisable]
176
+ #
177
+ # @overload elements(name, root, serialisable)
178
+ # Use this when the nodes being matched contains nested xml and the root
179
+ # needs to be set.
180
+ #
181
+ # @param name [Symbol] Name of the method to be defined on the class that
182
+ # returns the value matched.
183
+ # @param root [String] Name of the root of the nested element, this
184
+ # overrides any root set on the +serialisable+ passed.
185
+ # @param serialisable [Serialisable] Serialisable object that represents
186
+ # the nested element.
187
+ #
188
+ # @overload elements(name, selector, type=nil)
189
+ # Use this when the nodes only contain text.
190
+ #
191
+ # @param name [Symbol] Name of the method to be defined on the class that
192
+ # returns the value matched.
193
+ # @param selector [String] Name of xml attribute to match against.
194
+ # @param type [Symbol, #parse] If a symbol is given the matched string will
195
+ # have the method named by it called on it. If an object responding to
196
+ # #parse is given then the string value will be passed to that method.
197
+ #
198
+ def elements(name, selector, type = nil)
199
+ if selector.respond_to?(:__deserialise_all, true)
200
+ @__selectors << Selector::NestedMultiple.new(name, selector, type)
201
+
202
+ elsif type.respond_to?(:__deserialise_all, true)
203
+ cloned_type = type.clone
204
+ cloned_type.instance_variable_set(:@__root, selector)
205
+ @__selectors << Selector::NestedMultiple.new(name, cloned_type)
206
+
27
207
  else
28
- raise ArgumentError
208
+ @__selectors << Selector::Nodes.new(name, selector, type)
29
209
  end
30
210
  end
31
211
 
212
+ # Deserialises the given +xml+ into an instance of the class.
213
+ #
214
+ # @param xml [String]
215
+ # @return An instance of the class that the method was called on.
32
216
  def deserialise(xml)
33
217
  __deserialise Nokogiri::XML(xml)
34
218
  end
@@ -37,99 +221,21 @@ module Serialisable
37
221
 
38
222
  def __deserialise_all(doc)
39
223
  doc = doc.children.find_all {|node| node.name == @__root }
40
-
41
- attrs_list = doc.map do |node|
42
- attrs = SerialisableHelpers.get_multiples(node, @__elements)
43
- attrs += SerialisableHelpers.get_singles(node, @__element)
44
- attrs += SerialisableHelpers.get_attributes(node, @__attribute)
45
-
46
- attrs
47
- end
48
-
49
- objs = []
50
- attrs_list.each do |attrs|
51
- attrs = Hash[attrs]
52
-
53
- attrs.each do |key, value|
54
- define_method key do
55
- instance_variable_get(:@__serialisable_attrs)[key]
56
- end
57
- end
58
-
59
- obj = new
60
- obj.instance_variable_set(:@__serialisable_attrs, attrs)
61
- objs << obj
62
- end
63
-
64
- objs
224
+ doc.map {|node| __select(node) }
65
225
  end
66
226
 
67
227
  def __deserialise(doc)
68
- doc = doc.children.find {|node| node.name == @__root }
69
-
70
- attrs = SerialisableHelpers.get_multiples(doc, @__elements)
71
- attrs += SerialisableHelpers.get_singles(doc, @__element)
72
- attrs += SerialisableHelpers.get_attributes(doc, @__attribute)
73
-
74
- attrs = Hash[attrs]
75
-
76
- attrs.each do |key, value|
77
- define_method key do
78
- instance_variable_get(:@__serialisable_attrs)[key]
79
- end
80
- end
81
-
82
- obj = new
83
- obj.instance_variable_set(:@__serialisable_attrs, attrs)
84
- obj
228
+ node = doc.children.find {|node| node.name == @__root }
229
+ __select(node)
85
230
  end
86
- end
87
-
88
- module SerialisableHelpers
89
- extend self
90
231
 
91
- def get_multiples(root, hash)
92
- hash.map do |name, (selector, type)|
93
- if type.respond_to?(:__deserialise_all, true)
94
- [name, type.send(:__deserialise_all, root)]
95
- else
96
- values = root.children.find_all {|node| node.name == selector }
97
- .map {|node| node.children.to_s }
98
- .map {|value| parse_type(value, type) }
99
-
100
- [name, values]
101
- end
102
- end
103
- end
104
-
105
- def get_singles(root, hash)
106
- hash.map do |name, (selector, type)|
107
- if selector.respond_to?(:__deserialise, true)
108
- [name, selector.send(:__deserialise, root)]
109
- else
110
- value = root.children.find {|node| node.name == selector }.children.to_s
111
- value = parse_type(value, type)
112
-
113
- [name, value]
114
- end
115
- end
116
- end
117
-
118
- def get_attributes(root, hash)
119
- hash.map do |name, (selector, type)|
120
- value = root.attributes[selector].value
121
- value = parse_type(value, type)
122
-
123
- [name, value]
124
- end
125
- end
126
-
127
- # Parses the value read from xml if the type given responds to the method
128
- # #parse, otherwise returns the string value.
129
- #
130
- # @param value [String]
131
- # @param type [#parse]
132
- def parse_type(value, type)
133
- type.respond_to?(:parse) ? type.parse(value) : value
232
+ def __select(node)
233
+ new.tap {|obj|
234
+ @__selectors.each {|selector|
235
+ obj.singleton_class.send(:define_method, selector.name) {
236
+ selector.match(node)
237
+ }
238
+ }
239
+ }
134
240
  end
135
241
  end
@@ -0,0 +1,57 @@
1
+ module Serialisable
2
+
3
+ # @abstract Must implement #match
4
+ class Selector
5
+ attr_reader :name
6
+
7
+ def initialize(name, selector, type = nil)
8
+ @name = name
9
+ @selector = selector
10
+ @type = type
11
+ end
12
+
13
+ def parse(value)
14
+ if @type.respond_to?(:parse)
15
+ @type.parse(value)
16
+ elsif @type.is_a?(Symbol)
17
+ value.send(@type)
18
+ else
19
+ value
20
+ end
21
+ end
22
+
23
+ class Attribute < Selector
24
+ def match(root)
25
+ parse root.attributes[@selector].value
26
+ end
27
+ end
28
+
29
+ class Node < Selector
30
+ def match(root)
31
+ parse root.children
32
+ .find {|node| node.name == @selector }
33
+ .children.to_s
34
+ end
35
+ end
36
+
37
+ class Nodes < Selector
38
+ def match(root)
39
+ root.children
40
+ .find_all {|node| node.name == @selector }
41
+ .map {|node| parse node.children.to_s }
42
+ end
43
+ end
44
+
45
+ class Nested < Selector
46
+ def match(root)
47
+ @selector.send(:__deserialise, root)
48
+ end
49
+ end
50
+
51
+ class NestedMultiple < Selector
52
+ def match(root)
53
+ @selector.send(:__deserialise_all, root)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -1,3 +1,3 @@
1
1
  module Serialisable
2
- VERSION = '0.0.1'
2
+ VERSION = '0.1.0'
3
3
  end
@@ -0,0 +1,166 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe Serialisable::Selector do
4
+ describe '#name' do
5
+ let(:selector_name) { "some name" }
6
+ subject { Serialisable::Selector.new(selector_name, nil) }
7
+
8
+ it 'returns the name' do
9
+ subject.name.must_equal selector_name
10
+ end
11
+ end
12
+
13
+ describe Serialisable::Selector::Attribute do
14
+ describe '#match' do
15
+ describe 'when type not given' do
16
+ subject { Serialisable::Selector::Attribute.new(nil, 'hey') }
17
+
18
+ let(:xml) { '<el hey="1" what="5"/>' }
19
+ let(:doc) { Nokogiri::XML(xml) }
20
+
21
+ it 'returns the matching attribute' do
22
+ subject.match(doc.children.first).must_equal "1"
23
+ end
24
+ end
25
+
26
+ describe 'when symbol given as type' do
27
+ subject { Serialisable::Selector::Attribute.new(nil, 'hey', :to_i) }
28
+
29
+ let(:xml) { '<el hey="1" what="5"/>' }
30
+ let(:doc) { Nokogiri::XML(xml) }
31
+
32
+ it 'returns the matching attribute' do
33
+ subject.match(doc.children.first).must_equal 1
34
+ end
35
+ end
36
+
37
+ describe 'when object responding to #parse given as type' do
38
+ let(:type) { Class.new { def parse(v); v.to_i; end }.new }
39
+ subject { Serialisable::Selector::Attribute.new(nil, 'hey', type) }
40
+
41
+ let(:xml) { '<el hey="1" what="5"/>' }
42
+ let(:doc) { Nokogiri::XML(xml) }
43
+
44
+ it 'returns the matching attribute' do
45
+ subject.match(doc.children.first).must_equal 1
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ describe Serialisable::Selector::Node do
52
+ describe '#match' do
53
+ describe 'when type not given' do
54
+ subject { Serialisable::Selector::Node.new(nil, 'hey') }
55
+
56
+ let(:xml) { '<el><hey>5</hey><what>6</what></el>' }
57
+ let(:doc) { Nokogiri::XML(xml) }
58
+
59
+ it 'returns the matching node' do
60
+ subject.match(doc.children.first).must_equal "5"
61
+ end
62
+ end
63
+
64
+ describe 'when symbol given as type' do
65
+ subject { Serialisable::Selector::Node.new(nil, 'hey', :to_i) }
66
+
67
+ let(:xml) { '<el><hey>5</hey><what>6</what></el>' }
68
+ let(:doc) { Nokogiri::XML(xml) }
69
+
70
+ it 'returns the matching node' do
71
+ subject.match(doc.children.first).must_equal 5
72
+ end
73
+ end
74
+
75
+ describe 'when object responding to #parse given as type' do
76
+ let(:type) { Class.new { def parse(v); v.to_i; end }.new }
77
+ subject { Serialisable::Selector::Node.new(nil, 'hey', type) }
78
+
79
+ let(:xml) { '<el><hey>5</hey><what>6</what></el>' }
80
+ let(:doc) { Nokogiri::XML(xml) }
81
+
82
+ it 'returns the matching node' do
83
+ subject.match(doc.children.first).must_equal 5
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ describe Serialisable::Selector::Nodes do
90
+ describe '#match' do
91
+ describe 'when no type given' do
92
+ subject { Serialisable::Selector::Nodes.new(nil, 'hey') }
93
+
94
+ let(:xml) { '<el><hey>5</hey><hey>6</hey><what>7</what></el>' }
95
+ let(:doc) { Nokogiri::XML(xml) }
96
+
97
+ it 'returns the matching nodes' do
98
+ subject.match(doc.children.first).must_equal ['5', '6']
99
+ end
100
+ end
101
+
102
+ describe 'when symbol given as type' do
103
+ subject { Serialisable::Selector::Nodes.new(nil, 'hey', :to_i) }
104
+
105
+ let(:xml) { '<el><hey>5</hey><hey>6</hey><what>7</what></el>' }
106
+ let(:doc) { Nokogiri::XML(xml) }
107
+
108
+ it 'returns the matching nodes' do
109
+ subject.match(doc.children.first).must_equal [5, 6]
110
+ end
111
+ end
112
+
113
+ describe 'when object responding to #parse given as type' do
114
+ let(:type) { Class.new { def parse(v); v.to_i; end }.new }
115
+ subject { Serialisable::Selector::Nodes.new(nil, 'hey', type) }
116
+
117
+ let(:xml) { '<el><hey>5</hey><hey>6</hey><what>7</what></el>' }
118
+ let(:doc) { Nokogiri::XML(xml) }
119
+
120
+ it 'returns the matching nodes' do
121
+ subject.match(doc.children.first).must_equal [5, 6]
122
+ end
123
+ end
124
+ end
125
+ end
126
+
127
+ describe Serialisable::Selector::Nested do
128
+ describe '#match' do
129
+ let(:root) { mock }
130
+ let(:nested) { mock }
131
+ let(:parsed) { mock }
132
+ subject { Serialisable::Selector::Nested.new(nil, nested, nil) }
133
+
134
+ before {
135
+ nested
136
+ .expects(:send)
137
+ .with(:__deserialise, root)
138
+ .returns(parsed)
139
+ }
140
+
141
+ it 'calls the private #__deserialise method' do
142
+ subject.match(root).must_equal parsed
143
+ end
144
+ end
145
+ end
146
+
147
+ describe Serialisable::Selector::NestedMultiple do
148
+ describe '#match' do
149
+ let(:root) { mock }
150
+ let(:nested) { mock }
151
+ let(:parsed) { mock }
152
+ subject { Serialisable::Selector::NestedMultiple.new(nil, nested, nil) }
153
+
154
+ before {
155
+ nested
156
+ .expects(:send)
157
+ .with(:__deserialise_all, root)
158
+ .returns(parsed)
159
+ }
160
+
161
+ it 'calls the private #__deserialise_all method' do
162
+ subject.match(root).must_equal parsed
163
+ end
164
+ end
165
+ end
166
+ end
@@ -79,6 +79,44 @@ EOS
79
79
  result.song.name.must_equal '505'
80
80
  end
81
81
  end
82
+
83
+ describe 'with a nested serialisable given a root' do
84
+ subject {
85
+ track = Class.new {
86
+ extend Serialisable
87
+
88
+ root 'track'
89
+ element :artist, 'artist'
90
+ element :name, 'name'
91
+ }
92
+
93
+ Class.new {
94
+ extend Serialisable
95
+
96
+ root 'songs'
97
+ element :song, 'song', track
98
+ }
99
+ }
100
+
101
+ let(:xml) {
102
+ <<EOS
103
+ <?xml version="1.0" encoding="utf-8"?>
104
+ <songs>
105
+ <song>
106
+ <artist>Arctic Monkeys</artist>
107
+ <name>505</name>
108
+ </song>
109
+ </songs>
110
+ EOS
111
+ }
112
+
113
+ it 'deserialises the nested object correctly' do
114
+ result = subject.deserialise(xml)
115
+
116
+ result.song.artist.must_equal 'Arctic Monkeys'
117
+ result.song.name.must_equal '505'
118
+ end
119
+ end
82
120
  end
83
121
 
84
122
  describe '#elements' do
@@ -149,24 +187,51 @@ EOS
149
187
  end
150
188
  end
151
189
 
152
- it 'raises an exception if not given less than two arguments' do
153
- lambda {
154
- Class.new {
190
+ describe 'with a list of nested objects given a root' do
191
+ subject {
192
+ track = Class.new {
155
193
  extend Serialisable
156
194
 
157
- elements :name
195
+ root 'track'
196
+ element :artist, 'artist'
197
+ element :name, 'name'
158
198
  }
159
- }.must_raise ArgumentError
160
- end
161
199
 
162
- it 'raises an exception if given more than three arguments' do
163
- lambda {
164
200
  Class.new {
165
201
  extend Serialisable
166
202
 
167
- elements :name, 'one', 'two', 'three'
203
+ root 'songs'
204
+ elements :songs, 'song', track
168
205
  }
169
- }.must_raise ArgumentError
206
+ }
207
+
208
+ let(:xml) {
209
+ <<EOS
210
+ <?xml version="1.0" encoding="utf-8"?>
211
+ <songs>
212
+ <song>
213
+ <artist>Arctic Monkeys</artist>
214
+ <name>505</name>
215
+ </song>
216
+ <song>
217
+ <artist>Aphex Twin</artist>
218
+ <name>Windowlicker</name>
219
+ </song>
220
+ </songs>
221
+ EOS
222
+ }
223
+
224
+ it 'takes xml and returns an object with a list of nested objects' do
225
+ result = subject.deserialise(xml)
226
+
227
+ result.songs.length.must_equal 2
228
+
229
+ result.songs[0].artist.must_equal 'Arctic Monkeys'
230
+ result.songs[0].name.must_equal '505'
231
+
232
+ result.songs[1].artist.must_equal 'Aphex Twin'
233
+ result.songs[1].name.must_equal 'Windowlicker'
234
+ end
170
235
  end
171
236
  end
172
237
 
@@ -1,4 +1,6 @@
1
1
  require 'minitest/autorun'
2
2
  require 'minitest/pride'
3
3
 
4
+ require 'mocha/setup'
5
+
4
6
  require_relative '../lib/serialisable'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: serialisable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joshua Hawxwell
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-08 00:00:00.000000000 Z
11
+ date: 2014-02-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -16,42 +16,42 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 1.6.1
19
+ version: '1.6'
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
- version: 1.6.1
26
+ version: '1.6'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: minitest
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 5.2.0
33
+ version: '5.2'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 5.2.0
40
+ version: '5.2'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: mocha
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: 1.0.0
47
+ version: '1.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
- version: 1.0.0
54
+ version: '1.0'
55
55
  description: |2
56
56
  Serialisable provides a simple DSL for turning xml into ruby objects.
57
57
  email: m@hawx.me
@@ -61,9 +61,11 @@ extra_rdoc_files: []
61
61
  files:
62
62
  - README.md
63
63
  - Rakefile
64
+ - lib/serialisable/selector.rb
64
65
  - lib/serialisable/version.rb
65
66
  - lib/serialisable.rb
66
67
  - spec/spec_helper.rb
68
+ - spec/serialisable/selector_spec.rb
67
69
  - spec/serialisable_spec.rb
68
70
  homepage: http://github.com/hawx/serialisable
69
71
  licenses:
@@ -91,4 +93,6 @@ specification_version: 4
91
93
  summary: Serialisable allows easy xml deserialisation
92
94
  test_files:
93
95
  - spec/spec_helper.rb
96
+ - spec/serialisable/selector_spec.rb
94
97
  - spec/serialisable_spec.rb
98
+ has_rdoc: