happymapper 0.3.1 → 0.3.2
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/Rakefile +1 -7
- data/examples/multi_street_address.rb +1 -1
- data/lib/happymapper.rb +33 -16
- data/lib/happymapper/version.rb +1 -1
- data/spec/fixtures/notes.xml +9 -0
- data/spec/happymapper_spec.rb +67 -303
- data/spec/support/models.rb +290 -0
- metadata +5 -3
data/Rakefile
CHANGED
@@ -25,18 +25,12 @@ task :release => :build do
|
|
25
25
|
sh "git tag v#{HappyMapper::Version}"
|
26
26
|
sh "git push origin master"
|
27
27
|
sh "git push origin v#{HappyMapper::Version}"
|
28
|
-
sh "gem push
|
28
|
+
sh "gem push happymapper-#{HappyMapper::Version}.gem"
|
29
29
|
end
|
30
30
|
|
31
31
|
desc 'Upload website files to rubyforge'
|
32
32
|
task :website do
|
33
33
|
sh %{rsync -av website/ jnunemaker@rubyforge.org:/var/www/gforge-projects/happymapper}
|
34
|
-
Rake::Task['website_docs'].invoke
|
35
|
-
end
|
36
|
-
|
37
|
-
task :website_docs do
|
38
|
-
Rake::Task['rerdoc'].invoke
|
39
|
-
sh %{rsync -av doc/ jnunemaker@rubyforge.org:/var/www/gforge-projects/happymapper/docs}
|
40
34
|
end
|
41
35
|
|
42
36
|
Rake::RDocTask.new do |r|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
dir = File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
2
|
require File.join(dir, 'happymapper')
|
3
3
|
|
4
|
-
file_contents = File.read(dir + '/../spec/fixtures/
|
4
|
+
file_contents = File.read(dir + '/../spec/fixtures/multi_street_address.xml')
|
5
5
|
|
6
6
|
class MultiStreetAddress
|
7
7
|
include HappyMapper
|
data/lib/happymapper.rb
CHANGED
@@ -13,7 +13,7 @@ module HappyMapper
|
|
13
13
|
base.instance_variable_set("@elements", {})
|
14
14
|
base.extend ClassMethods
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
module ClassMethods
|
18
18
|
def attribute(name, type, options={})
|
19
19
|
attribute = Attribute.new(name, type, options)
|
@@ -21,26 +21,39 @@ module HappyMapper
|
|
21
21
|
@attributes[to_s] << attribute
|
22
22
|
attr_accessor attribute.method_name.intern
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
def attributes
|
26
26
|
@attributes[to_s] || []
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
def element(name, type, options={})
|
30
30
|
element = Element.new(name, type, options)
|
31
31
|
@elements[to_s] ||= []
|
32
32
|
@elements[to_s] << element
|
33
33
|
attr_accessor element.method_name.intern
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
|
+
def content(name)
|
37
|
+
@content = name
|
38
|
+
attr_accessor name
|
39
|
+
end
|
40
|
+
|
41
|
+
def after_parse_callbacks
|
42
|
+
@after_parse_callbacks ||= []
|
43
|
+
end
|
44
|
+
|
45
|
+
def after_parse(&block)
|
46
|
+
after_parse_callbacks.push(block)
|
47
|
+
end
|
48
|
+
|
36
49
|
def elements
|
37
50
|
@elements[to_s] || []
|
38
51
|
end
|
39
|
-
|
52
|
+
|
40
53
|
def has_one(name, type, options={})
|
41
54
|
element name, type, {:single => true}.merge(options)
|
42
55
|
end
|
43
|
-
|
56
|
+
|
44
57
|
def has_many(name, type, options={})
|
45
58
|
element name, type, {:single => false}.merge(options)
|
46
59
|
end
|
@@ -56,11 +69,11 @@ module HappyMapper
|
|
56
69
|
def tag(new_tag_name)
|
57
70
|
@tag_name = new_tag_name.to_s
|
58
71
|
end
|
59
|
-
|
72
|
+
|
60
73
|
def tag_name
|
61
74
|
@tag_name ||= to_s.split('::')[-1].downcase
|
62
75
|
end
|
63
|
-
|
76
|
+
|
64
77
|
def parse(xml, options = {})
|
65
78
|
if xml.is_a?(XML::Node)
|
66
79
|
node = xml
|
@@ -80,21 +93,25 @@ module HappyMapper
|
|
80
93
|
xpath = root ? '/' : './/'
|
81
94
|
xpath += "#{DEFAULT_NS}:" if namespace
|
82
95
|
xpath += tag_name
|
83
|
-
|
96
|
+
|
84
97
|
nodes = node.find(xpath, Array(namespace))
|
85
98
|
collection = nodes.collect do |n|
|
86
99
|
obj = new
|
87
|
-
|
88
|
-
attributes.each do |attr|
|
89
|
-
obj.send("#{attr.method_name}=",
|
100
|
+
|
101
|
+
attributes.each do |attr|
|
102
|
+
obj.send("#{attr.method_name}=",
|
90
103
|
attr.from_xml_node(n, namespace))
|
91
104
|
end
|
92
|
-
|
105
|
+
|
93
106
|
elements.each do |elem|
|
94
|
-
obj.send("#{elem.method_name}=",
|
107
|
+
obj.send("#{elem.method_name}=",
|
95
108
|
elem.from_xml_node(n, namespace))
|
96
109
|
end
|
97
|
-
|
110
|
+
|
111
|
+
obj.send("#{@content}=", n.content) if @content
|
112
|
+
|
113
|
+
obj.class.after_parse_callbacks.each { |callback| callback.call(obj) }
|
114
|
+
|
98
115
|
obj
|
99
116
|
end
|
100
117
|
|
@@ -112,4 +129,4 @@ end
|
|
112
129
|
|
113
130
|
require 'happymapper/item'
|
114
131
|
require 'happymapper/attribute'
|
115
|
-
require 'happymapper/element'
|
132
|
+
require 'happymapper/element'
|
data/lib/happymapper/version.rb
CHANGED
data/spec/happymapper_spec.rb
CHANGED
@@ -1,302 +1,35 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
2
|
require 'pp'
|
3
3
|
require 'uri'
|
4
|
-
|
5
|
-
module Analytics
|
6
|
-
class Property
|
7
|
-
include HappyMapper
|
8
|
-
|
9
|
-
tag 'property'
|
10
|
-
namespace 'http://schemas.google.com/analytics/2009'
|
11
|
-
attribute :name, String
|
12
|
-
attribute :value, String
|
13
|
-
end
|
14
|
-
|
15
|
-
class Entry
|
16
|
-
include HappyMapper
|
17
|
-
|
18
|
-
tag 'entry'
|
19
|
-
element :id, String
|
20
|
-
element :updated, DateTime
|
21
|
-
element :title, String
|
22
|
-
element :table_id, String, :namespace => 'http://schemas.google.com/analytics/2009', :tag => 'tableId'
|
23
|
-
has_many :properties, Property
|
24
|
-
end
|
25
|
-
|
26
|
-
class Feed
|
27
|
-
include HappyMapper
|
28
|
-
|
29
|
-
tag 'feed'
|
30
|
-
element :id, String
|
31
|
-
element :updated, DateTime
|
32
|
-
element :title, String
|
33
|
-
has_many :entries, Entry
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
class Feature
|
38
|
-
include HappyMapper
|
39
|
-
element :name, String, :tag => '.|.//text()'
|
40
|
-
end
|
41
|
-
|
42
|
-
class FeatureBullet
|
43
|
-
include HappyMapper
|
44
|
-
|
45
|
-
tag 'features_bullets'
|
46
|
-
has_many :features, Feature
|
47
|
-
element :bug, String
|
48
|
-
end
|
49
|
-
|
50
|
-
class Product
|
51
|
-
include HappyMapper
|
52
|
-
|
53
|
-
element :title, String
|
54
|
-
has_one :feature_bullets, FeatureBullet
|
55
|
-
end
|
56
|
-
|
57
|
-
module FamilySearch
|
58
|
-
class Person
|
59
|
-
include HappyMapper
|
60
|
-
|
61
|
-
attribute :version, String
|
62
|
-
attribute :modified, Time
|
63
|
-
attribute :id, String
|
64
|
-
end
|
65
|
-
|
66
|
-
class Persons
|
67
|
-
include HappyMapper
|
68
|
-
has_many :person, Person
|
69
|
-
end
|
70
|
-
|
71
|
-
class FamilyTree
|
72
|
-
include HappyMapper
|
73
|
-
|
74
|
-
tag 'familytree'
|
75
|
-
attribute :version, String
|
76
|
-
attribute :status_message, String, :tag => 'statusMessage'
|
77
|
-
attribute :status_code, String, :tag => 'statusCode'
|
78
|
-
has_one :persons, Persons
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
module FedEx
|
83
|
-
class Address
|
84
|
-
include HappyMapper
|
85
|
-
|
86
|
-
tag 'Address'
|
87
|
-
namespace 'http://fedex.com/ws/track/v2'
|
88
|
-
element :city, String, :tag => 'City'
|
89
|
-
element :state, String, :tag => 'StateOrProvinceCode'
|
90
|
-
element :zip, String, :tag => 'PostalCode'
|
91
|
-
element :countrycode, String, :tag => 'CountryCode'
|
92
|
-
element :residential, Boolean, :tag => 'Residential'
|
93
|
-
end
|
94
|
-
|
95
|
-
class Event
|
96
|
-
include HappyMapper
|
97
|
-
|
98
|
-
tag 'Events'
|
99
|
-
namespace 'http://fedex.com/ws/track/v2'
|
100
|
-
element :timestamp, String, :tag => 'Timestamp'
|
101
|
-
element :eventtype, String, :tag => 'EventType'
|
102
|
-
element :eventdescription, String, :tag => 'EventDescription'
|
103
|
-
has_one :address, Address
|
104
|
-
end
|
105
|
-
|
106
|
-
class PackageWeight
|
107
|
-
include HappyMapper
|
108
|
-
|
109
|
-
tag 'PackageWeight'
|
110
|
-
namespace 'http://fedex.com/ws/track/v2'
|
111
|
-
element :units, String, :tag => 'Units'
|
112
|
-
element :value, Integer, :tag => 'Value'
|
113
|
-
end
|
114
|
-
|
115
|
-
class TrackDetails
|
116
|
-
include HappyMapper
|
117
|
-
|
118
|
-
tag 'TrackDetails'
|
119
|
-
namespace 'http://fedex.com/ws/track/v2'
|
120
|
-
element :tracking_number, String, :tag => 'TrackingNumber'
|
121
|
-
element :status_code, String, :tag => 'StatusCode'
|
122
|
-
element :status_desc, String, :tag => 'StatusDescription'
|
123
|
-
element :carrier_code, String, :tag => 'CarrierCode'
|
124
|
-
element :service_info, String, :tag => 'ServiceInfo'
|
125
|
-
has_one :weight, PackageWeight, :tag => 'PackageWeight'
|
126
|
-
element :est_delivery, String, :tag => 'EstimatedDeliveryTimestamp'
|
127
|
-
has_many :events, Event
|
128
|
-
end
|
129
|
-
|
130
|
-
class Notification
|
131
|
-
include HappyMapper
|
132
|
-
|
133
|
-
tag 'Notifications'
|
134
|
-
namespace 'http://fedex.com/ws/track/v2'
|
135
|
-
element :severity, String, :tag => 'Severity'
|
136
|
-
element :source, String, :tag => 'Source'
|
137
|
-
element :code, Integer, :tag => 'Code'
|
138
|
-
element :message, String, :tag => 'Message'
|
139
|
-
element :localized_message, String, :tag => 'LocalizedMessage'
|
140
|
-
end
|
141
|
-
|
142
|
-
class TransactionDetail
|
143
|
-
include HappyMapper
|
144
|
-
|
145
|
-
tag 'TransactionDetail'
|
146
|
-
namespace 'http://fedex.com/ws/track/v2'
|
147
|
-
element :cust_tran_id, String, :tag => 'CustomerTransactionId'
|
148
|
-
end
|
149
|
-
|
150
|
-
class TrackReply
|
151
|
-
include HappyMapper
|
152
|
-
|
153
|
-
tag 'TrackReply'
|
154
|
-
namespace 'http://fedex.com/ws/track/v2'
|
155
|
-
element :highest_severity, String, :tag => 'HighestSeverity'
|
156
|
-
element :more_data, Boolean, :tag => 'MoreData'
|
157
|
-
has_many :notifications, Notification, :tag => 'Notifications'
|
158
|
-
has_many :trackdetails, TrackDetails, :tag => 'TrackDetails'
|
159
|
-
has_one :tran_detail, TransactionDetail, :tab => 'TransactionDetail'
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
|
-
class Place
|
164
|
-
include HappyMapper
|
165
|
-
element :name, String
|
166
|
-
end
|
167
|
-
|
168
|
-
class Radar
|
169
|
-
include HappyMapper
|
170
|
-
has_many :places, Place
|
171
|
-
end
|
172
|
-
|
173
|
-
class Post
|
174
|
-
include HappyMapper
|
175
|
-
|
176
|
-
attribute :href, String
|
177
|
-
attribute :hash, String
|
178
|
-
attribute :description, String
|
179
|
-
attribute :tag, String
|
180
|
-
attribute :time, Time
|
181
|
-
attribute :others, Integer
|
182
|
-
attribute :extended, String
|
183
|
-
end
|
184
|
-
|
185
|
-
class User
|
186
|
-
include HappyMapper
|
187
|
-
|
188
|
-
element :id, Integer
|
189
|
-
element :name, String
|
190
|
-
element :screen_name, String
|
191
|
-
element :location, String
|
192
|
-
element :description, String
|
193
|
-
element :profile_image_url, String
|
194
|
-
element :url, String
|
195
|
-
element :protected, Boolean
|
196
|
-
element :followers_count, Integer
|
197
|
-
end
|
198
|
-
|
199
|
-
class Status
|
200
|
-
include HappyMapper
|
201
|
-
|
202
|
-
element :id, Integer
|
203
|
-
element :text, String
|
204
|
-
element :created_at, Time
|
205
|
-
element :source, String
|
206
|
-
element :truncated, Boolean
|
207
|
-
element :in_reply_to_status_id, Integer
|
208
|
-
element :in_reply_to_user_id, Integer
|
209
|
-
element :favorited, Boolean
|
210
|
-
element :non_existent, String, :tag => 'dummy', :namespace => 'fake'
|
211
|
-
has_one :user, User
|
212
|
-
end
|
213
|
-
|
214
|
-
class CurrentWeather
|
215
|
-
include HappyMapper
|
216
|
-
|
217
|
-
tag 'ob'
|
218
|
-
namespace 'http://www.aws.com/aws'
|
219
|
-
element :temperature, Integer, :tag => 'temp'
|
220
|
-
element :feels_like, Integer, :tag => 'feels-like'
|
221
|
-
element :current_condition, String, :tag => 'current-condition', :attributes => {:icon => String}
|
222
|
-
end
|
223
|
-
|
224
|
-
class Address
|
225
|
-
include HappyMapper
|
226
|
-
|
227
|
-
tag 'address'
|
228
|
-
element :street, String
|
229
|
-
element :postcode, String
|
230
|
-
element :housenumber, String
|
231
|
-
element :city, String
|
232
|
-
element :country, String
|
233
|
-
end
|
234
|
-
|
235
|
-
# for type coercion
|
236
|
-
class ProductGroup < String; end
|
237
|
-
|
238
|
-
module PITA
|
239
|
-
class Item
|
240
|
-
include HappyMapper
|
241
|
-
|
242
|
-
tag 'Item' # if you put class in module you need tag
|
243
|
-
element :asin, String, :tag => 'ASIN'
|
244
|
-
element :detail_page_url, URI, :tag => 'DetailPageURL', :parser => :parse
|
245
|
-
element :manufacturer, String, :tag => 'Manufacturer', :deep => true
|
246
|
-
element :point, String, :tag => 'point', :namespace => 'http://www.georss.org/georss'
|
247
|
-
element :product_group, ProductGroup, :tag => 'ProductGroup', :deep => true, :parser => :new, :raw => true
|
248
|
-
end
|
249
|
-
|
250
|
-
class Items
|
251
|
-
include HappyMapper
|
252
|
-
|
253
|
-
tag 'Items' # if you put class in module you need tag
|
254
|
-
element :total_results, Integer, :tag => 'TotalResults'
|
255
|
-
element :total_pages, Integer, :tag => 'TotalPages'
|
256
|
-
has_many :items, Item
|
257
|
-
end
|
258
|
-
end
|
259
|
-
|
260
|
-
module GitHub
|
261
|
-
class Commit
|
262
|
-
include HappyMapper
|
263
|
-
|
264
|
-
tag "commit"
|
265
|
-
element :url, String
|
266
|
-
element :tree, String
|
267
|
-
element :message, String
|
268
|
-
element :id, String
|
269
|
-
element :'committed-date', Date
|
270
|
-
end
|
271
|
-
end
|
4
|
+
require 'support/models'
|
272
5
|
|
273
6
|
describe HappyMapper do
|
274
|
-
|
7
|
+
|
275
8
|
describe "being included into another class" do
|
276
9
|
before do
|
277
10
|
@klass = Class.new do
|
278
11
|
include HappyMapper
|
279
|
-
|
12
|
+
|
280
13
|
def self.to_s
|
281
14
|
'Foo'
|
282
15
|
end
|
283
16
|
end
|
284
17
|
end
|
285
|
-
|
18
|
+
|
286
19
|
it "should set attributes to an array" do
|
287
20
|
@klass.attributes.should == []
|
288
21
|
end
|
289
|
-
|
22
|
+
|
290
23
|
it "should set @elements to a hash" do
|
291
24
|
@klass.elements.should == []
|
292
25
|
end
|
293
|
-
|
26
|
+
|
294
27
|
it "should allow adding an attribute" do
|
295
28
|
lambda {
|
296
29
|
@klass.attribute :name, String
|
297
30
|
}.should change(@klass, :attributes)
|
298
31
|
end
|
299
|
-
|
32
|
+
|
300
33
|
it "should allow adding an attribute containing a dash" do
|
301
34
|
lambda {
|
302
35
|
@klass.attribute :'bar-baz', String
|
@@ -307,7 +40,7 @@ describe HappyMapper do
|
|
307
40
|
@klass.attribute :name, String
|
308
41
|
@klass.attributes.size.should == 1
|
309
42
|
end
|
310
|
-
|
43
|
+
|
311
44
|
it "should allow adding an element" do
|
312
45
|
lambda {
|
313
46
|
@klass.element :name, String
|
@@ -320,12 +53,12 @@ describe HappyMapper do
|
|
320
53
|
}.should change(@klass, :elements)
|
321
54
|
|
322
55
|
end
|
323
|
-
|
56
|
+
|
324
57
|
it "should be able to get all elements in array" do
|
325
58
|
@klass.element(:name, String)
|
326
59
|
@klass.elements.size.should == 1
|
327
60
|
end
|
328
|
-
|
61
|
+
|
329
62
|
it "should allow has one association" do
|
330
63
|
@klass.has_one(:user, User)
|
331
64
|
element = @klass.elements.first
|
@@ -333,7 +66,7 @@ describe HappyMapper do
|
|
333
66
|
element.type.should == User
|
334
67
|
element.options[:single] = true
|
335
68
|
end
|
336
|
-
|
69
|
+
|
337
70
|
it "should allow has many association" do
|
338
71
|
@klass.has_many(:users, User)
|
339
72
|
element = @klass.elements.first
|
@@ -342,20 +75,28 @@ describe HappyMapper do
|
|
342
75
|
element.options[:single] = false
|
343
76
|
end
|
344
77
|
|
78
|
+
it "has after_parse callbacks" do
|
79
|
+
call1 = lambda { |doc| puts doc.inspect }
|
80
|
+
call2 = lambda { |doc| puts doc.inspect }
|
81
|
+
@klass.after_parse(&call1)
|
82
|
+
@klass.after_parse(&call2)
|
83
|
+
@klass.after_parse_callbacks.should == [call1, call2]
|
84
|
+
end
|
85
|
+
|
345
86
|
it "should default tag name to lowercase class" do
|
346
87
|
@klass.tag_name.should == 'foo'
|
347
88
|
end
|
348
|
-
|
89
|
+
|
349
90
|
it "should default tag name of class in modules to the last constant lowercase" do
|
350
91
|
module Bar; class Baz; include HappyMapper; end; end
|
351
92
|
Bar::Baz.tag_name.should == 'baz'
|
352
93
|
end
|
353
|
-
|
94
|
+
|
354
95
|
it "should allow setting tag name" do
|
355
96
|
@klass.tag('FooBar')
|
356
97
|
@klass.tag_name.should == 'FooBar'
|
357
98
|
end
|
358
|
-
|
99
|
+
|
359
100
|
it "should allow setting a namespace" do
|
360
101
|
@klass.namespace(namespace = "foo")
|
361
102
|
@klass.namespace.should == namespace
|
@@ -365,21 +106,29 @@ describe HappyMapper do
|
|
365
106
|
@klass.should respond_to(:parse)
|
366
107
|
end
|
367
108
|
end
|
368
|
-
|
109
|
+
|
369
110
|
describe "#attributes" do
|
370
111
|
it "should only return attributes for the current class" do
|
371
112
|
Post.attributes.size.should == 7
|
372
113
|
Status.attributes.size.should == 0
|
373
114
|
end
|
374
115
|
end
|
375
|
-
|
116
|
+
|
376
117
|
describe "#elements" do
|
377
118
|
it "should only return elements for the current class" do
|
378
119
|
Post.elements.size.should == 0
|
379
120
|
Status.elements.size.should == 10
|
380
121
|
end
|
381
122
|
end
|
382
|
-
|
123
|
+
|
124
|
+
describe "running after_parse callbacks" do
|
125
|
+
it "works" do
|
126
|
+
user = Status.parse(fixture_file('statuses.xml')).first.user
|
127
|
+
user.after_parse_called.should be_true
|
128
|
+
user.after_parse2_called.should be_true
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
383
132
|
it "should parse xml attributes into ruby objects" do
|
384
133
|
posts = Post.parse(fixture_file('posts.xml'))
|
385
134
|
posts.size.should == 20
|
@@ -392,7 +141,7 @@ describe HappyMapper do
|
|
392
141
|
first.others.should == 56
|
393
142
|
first.extended.should == 'ROXML is a Ruby library designed to make it easier for Ruby developers to work with XML. Using simple annotations, it enables Ruby classes to be custom-mapped to XML. ROXML takes care of the marshalling and unmarshalling of mapped attributes so that developers can focus on building first-class Ruby classes.'
|
394
143
|
end
|
395
|
-
|
144
|
+
|
396
145
|
it "should parse xml elements to ruby objcts" do
|
397
146
|
statuses = Status.parse(fixture_file('statuses.xml'))
|
398
147
|
statuses.size.should == 20
|
@@ -414,7 +163,7 @@ describe HappyMapper do
|
|
414
163
|
first.user.protected.should be_false
|
415
164
|
first.user.followers_count.should == 486
|
416
165
|
end
|
417
|
-
|
166
|
+
|
418
167
|
it "should parse xml containing the desired element as root node" do
|
419
168
|
address = Address.parse(fixture_file('address.xml'), :single => true)
|
420
169
|
address.street.should == 'Milchstrasse'
|
@@ -462,7 +211,7 @@ describe HappyMapper do
|
|
462
211
|
third.places[0].name.should == 'Work'
|
463
212
|
third.places[1].name.should == 'Home'
|
464
213
|
end
|
465
|
-
|
214
|
+
|
466
215
|
it "should parse xml that has elements with dashes" do
|
467
216
|
commit = GitHub::Commit.parse(fixture_file('commit.xml'))
|
468
217
|
commit.message.should == "move commands.rb and helpers.rb into commands/ dir"
|
@@ -471,7 +220,7 @@ describe HappyMapper do
|
|
471
220
|
commit.committed_date.should == Date.parse("2008-03-02T16:45:41-08:00")
|
472
221
|
commit.tree.should == "28a1a1ca3e663d35ba8bf07d3f1781af71359b76"
|
473
222
|
end
|
474
|
-
|
223
|
+
|
475
224
|
it "should parse xml with no namespace" do
|
476
225
|
product = Product.parse(fixture_file('product_no_namespace.xml'), :single => true)
|
477
226
|
product.title.should == "A Title"
|
@@ -480,7 +229,7 @@ describe HappyMapper do
|
|
480
229
|
product.feature_bullets.features[0].name.should == 'This is feature text 1'
|
481
230
|
product.feature_bullets.features[1].name.should == 'This is feature text 2'
|
482
231
|
end
|
483
|
-
|
232
|
+
|
484
233
|
it "should parse xml with default namespace" do
|
485
234
|
product = Product.parse(fixture_file('product_default_namespace.xml'), :single => true)
|
486
235
|
product.title.should == "A Title"
|
@@ -489,7 +238,7 @@ describe HappyMapper do
|
|
489
238
|
product.feature_bullets.features[0].name.should == 'This is feature text 1'
|
490
239
|
product.feature_bullets.features[1].name.should == 'This is feature text 2'
|
491
240
|
end
|
492
|
-
|
241
|
+
|
493
242
|
it "should parse xml with single namespace" do
|
494
243
|
product = Product.parse(fixture_file('product_single_namespace.xml'), :single => true)
|
495
244
|
product.title.should == "A Title"
|
@@ -498,7 +247,7 @@ describe HappyMapper do
|
|
498
247
|
product.feature_bullets.features[0].name.should == 'This is feature text 1'
|
499
248
|
product.feature_bullets.features[1].name.should == 'This is feature text 2'
|
500
249
|
end
|
501
|
-
|
250
|
+
|
502
251
|
it "should parse xml with multiple namespaces" do
|
503
252
|
track = FedEx::TrackReply.parse(fixture_file('multiple_namespaces.xml'))
|
504
253
|
track.highest_severity.should == 'SUCCESS'
|
@@ -540,34 +289,49 @@ describe HappyMapper do
|
|
540
289
|
last_event.address.zip.should == '327506398'
|
541
290
|
track.tran_detail.cust_tran_id.should == '20090102-111321'
|
542
291
|
end
|
543
|
-
|
292
|
+
|
293
|
+
it "should be able to parse from a node's content " do
|
294
|
+
notes = Backpack::Note.parse(fixture_file('notes.xml'))
|
295
|
+
notes.size.should == 2
|
296
|
+
|
297
|
+
note = notes[0]
|
298
|
+
note.id.should == 1132
|
299
|
+
note.title.should == 'My world!'
|
300
|
+
note.body.should include("It's a pretty place")
|
301
|
+
|
302
|
+
note = notes[1]
|
303
|
+
note.id.should == 1133
|
304
|
+
note.title.should == 'Your world!'
|
305
|
+
note.body.should include("Also pretty")
|
306
|
+
end
|
307
|
+
|
544
308
|
it "should be able to parse google analytics api xml" do
|
545
309
|
data = Analytics::Feed.parse(fixture_file('analytics.xml'))
|
546
310
|
data.id.should == 'http://www.google.com/analytics/feeds/accounts/nunemaker@gmail.com'
|
547
311
|
data.entries.size.should == 4
|
548
|
-
|
312
|
+
|
549
313
|
entry = data.entries[0]
|
550
314
|
entry.title.should == 'addictedtonew.com'
|
551
315
|
entry.properties.size.should == 4
|
552
|
-
|
316
|
+
|
553
317
|
property = entry.properties[0]
|
554
318
|
property.name.should == 'ga:accountId'
|
555
319
|
property.value.should == '85301'
|
556
320
|
end
|
557
|
-
|
321
|
+
|
558
322
|
it "should allow instantiating with a string" do
|
559
323
|
module StringFoo
|
560
324
|
class Bar
|
561
325
|
include HappyMapper
|
562
326
|
has_many :things, 'StringFoo::Thing'
|
563
327
|
end
|
564
|
-
|
328
|
+
|
565
329
|
class Thing
|
566
330
|
include HappyMapper
|
567
331
|
end
|
568
332
|
end
|
569
333
|
end
|
570
|
-
|
334
|
+
|
571
335
|
xit "should parse family search xml" do
|
572
336
|
tree = FamilySearch::FamilyTree.parse(fixture_file('family_tree.xml'))
|
573
337
|
tree.version.should == '1.0.20071213.942'
|
@@ -578,7 +342,7 @@ describe HappyMapper do
|
|
578
342
|
# tree.people.first.modified.should == Time.utc(2008, 1, 3, 16, 41, 31) # 2008-01-03T09:41:31-07:00
|
579
343
|
# tree.people.first.id.should == 'KWQS-BBQ'
|
580
344
|
end
|
581
|
-
|
345
|
+
|
582
346
|
describe 'nested elements with namespaces' do
|
583
347
|
module Namespaces
|
584
348
|
class Info
|
@@ -586,7 +350,7 @@ describe HappyMapper do
|
|
586
350
|
namespace 'http://schemas.google.com/analytics/2009'
|
587
351
|
element :category, String
|
588
352
|
end
|
589
|
-
|
353
|
+
|
590
354
|
class Alert
|
591
355
|
include HappyMapper
|
592
356
|
namespace 'http://schemas.google.com/analytics/2009'
|
@@ -602,7 +366,7 @@ describe HappyMapper do
|
|
602
366
|
has_one :alert, Alert
|
603
367
|
end
|
604
368
|
end
|
605
|
-
|
369
|
+
|
606
370
|
def mapping
|
607
371
|
@mapping ||= Namespaces::Distribution.parse(fixture_file('nested_namespaces.xml'))
|
608
372
|
end
|
@@ -610,11 +374,11 @@ describe HappyMapper do
|
|
610
374
|
it "should parse elements with inline namespace" do
|
611
375
|
lambda { mapping }.should_not raise_error
|
612
376
|
end
|
613
|
-
|
377
|
+
|
614
378
|
it "should map elements with inline namespace" do
|
615
379
|
mapping.alert.identifier.should == 'CDC-2006-183'
|
616
380
|
end
|
617
|
-
|
381
|
+
|
618
382
|
it "should map sub elements of with nested namespace" do
|
619
383
|
mapping.alert.info.category.should == 'Health'
|
620
384
|
end
|
@@ -623,5 +387,5 @@ describe HappyMapper do
|
|
623
387
|
mapping.alert.severity.should == 'Severe'
|
624
388
|
end
|
625
389
|
end
|
626
|
-
|
390
|
+
|
627
391
|
end
|
@@ -0,0 +1,290 @@
|
|
1
|
+
module Analytics
|
2
|
+
class Property
|
3
|
+
include HappyMapper
|
4
|
+
|
5
|
+
tag 'property'
|
6
|
+
namespace 'http://schemas.google.com/analytics/2009'
|
7
|
+
attribute :name, String
|
8
|
+
attribute :value, String
|
9
|
+
end
|
10
|
+
|
11
|
+
class Entry
|
12
|
+
include HappyMapper
|
13
|
+
|
14
|
+
tag 'entry'
|
15
|
+
element :id, String
|
16
|
+
element :updated, DateTime
|
17
|
+
element :title, String
|
18
|
+
element :table_id, String, :namespace => 'http://schemas.google.com/analytics/2009', :tag => 'tableId'
|
19
|
+
has_many :properties, Property
|
20
|
+
end
|
21
|
+
|
22
|
+
class Feed
|
23
|
+
include HappyMapper
|
24
|
+
|
25
|
+
tag 'feed'
|
26
|
+
element :id, String
|
27
|
+
element :updated, DateTime
|
28
|
+
element :title, String
|
29
|
+
has_many :entries, Entry
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Feature
|
34
|
+
include HappyMapper
|
35
|
+
element :name, String, :tag => '.|.//text()'
|
36
|
+
end
|
37
|
+
|
38
|
+
class FeatureBullet
|
39
|
+
include HappyMapper
|
40
|
+
|
41
|
+
tag 'features_bullets'
|
42
|
+
has_many :features, Feature
|
43
|
+
element :bug, String
|
44
|
+
end
|
45
|
+
|
46
|
+
class Product
|
47
|
+
include HappyMapper
|
48
|
+
|
49
|
+
element :title, String
|
50
|
+
has_one :feature_bullets, FeatureBullet
|
51
|
+
end
|
52
|
+
|
53
|
+
module FamilySearch
|
54
|
+
class Person
|
55
|
+
include HappyMapper
|
56
|
+
|
57
|
+
attribute :version, String
|
58
|
+
attribute :modified, Time
|
59
|
+
attribute :id, String
|
60
|
+
end
|
61
|
+
|
62
|
+
class Persons
|
63
|
+
include HappyMapper
|
64
|
+
has_many :person, Person
|
65
|
+
end
|
66
|
+
|
67
|
+
class FamilyTree
|
68
|
+
include HappyMapper
|
69
|
+
|
70
|
+
tag 'familytree'
|
71
|
+
attribute :version, String
|
72
|
+
attribute :status_message, String, :tag => 'statusMessage'
|
73
|
+
attribute :status_code, String, :tag => 'statusCode'
|
74
|
+
has_one :persons, Persons
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
module FedEx
|
79
|
+
class Address
|
80
|
+
include HappyMapper
|
81
|
+
|
82
|
+
tag 'Address'
|
83
|
+
namespace 'http://fedex.com/ws/track/v2'
|
84
|
+
element :city, String, :tag => 'City'
|
85
|
+
element :state, String, :tag => 'StateOrProvinceCode'
|
86
|
+
element :zip, String, :tag => 'PostalCode'
|
87
|
+
element :countrycode, String, :tag => 'CountryCode'
|
88
|
+
element :residential, Boolean, :tag => 'Residential'
|
89
|
+
end
|
90
|
+
|
91
|
+
class Event
|
92
|
+
include HappyMapper
|
93
|
+
|
94
|
+
tag 'Events'
|
95
|
+
namespace 'http://fedex.com/ws/track/v2'
|
96
|
+
element :timestamp, String, :tag => 'Timestamp'
|
97
|
+
element :eventtype, String, :tag => 'EventType'
|
98
|
+
element :eventdescription, String, :tag => 'EventDescription'
|
99
|
+
has_one :address, Address
|
100
|
+
end
|
101
|
+
|
102
|
+
class PackageWeight
|
103
|
+
include HappyMapper
|
104
|
+
|
105
|
+
tag 'PackageWeight'
|
106
|
+
namespace 'http://fedex.com/ws/track/v2'
|
107
|
+
element :units, String, :tag => 'Units'
|
108
|
+
element :value, Integer, :tag => 'Value'
|
109
|
+
end
|
110
|
+
|
111
|
+
class TrackDetails
|
112
|
+
include HappyMapper
|
113
|
+
|
114
|
+
tag 'TrackDetails'
|
115
|
+
namespace 'http://fedex.com/ws/track/v2'
|
116
|
+
element :tracking_number, String, :tag => 'TrackingNumber'
|
117
|
+
element :status_code, String, :tag => 'StatusCode'
|
118
|
+
element :status_desc, String, :tag => 'StatusDescription'
|
119
|
+
element :carrier_code, String, :tag => 'CarrierCode'
|
120
|
+
element :service_info, String, :tag => 'ServiceInfo'
|
121
|
+
has_one :weight, PackageWeight, :tag => 'PackageWeight'
|
122
|
+
element :est_delivery, String, :tag => 'EstimatedDeliveryTimestamp'
|
123
|
+
has_many :events, Event
|
124
|
+
end
|
125
|
+
|
126
|
+
class Notification
|
127
|
+
include HappyMapper
|
128
|
+
|
129
|
+
tag 'Notifications'
|
130
|
+
namespace 'http://fedex.com/ws/track/v2'
|
131
|
+
element :severity, String, :tag => 'Severity'
|
132
|
+
element :source, String, :tag => 'Source'
|
133
|
+
element :code, Integer, :tag => 'Code'
|
134
|
+
element :message, String, :tag => 'Message'
|
135
|
+
element :localized_message, String, :tag => 'LocalizedMessage'
|
136
|
+
end
|
137
|
+
|
138
|
+
class TransactionDetail
|
139
|
+
include HappyMapper
|
140
|
+
|
141
|
+
tag 'TransactionDetail'
|
142
|
+
namespace 'http://fedex.com/ws/track/v2'
|
143
|
+
element :cust_tran_id, String, :tag => 'CustomerTransactionId'
|
144
|
+
end
|
145
|
+
|
146
|
+
class TrackReply
|
147
|
+
include HappyMapper
|
148
|
+
|
149
|
+
tag 'TrackReply'
|
150
|
+
namespace 'http://fedex.com/ws/track/v2'
|
151
|
+
element :highest_severity, String, :tag => 'HighestSeverity'
|
152
|
+
element :more_data, Boolean, :tag => 'MoreData'
|
153
|
+
has_many :notifications, Notification, :tag => 'Notifications'
|
154
|
+
has_many :trackdetails, TrackDetails, :tag => 'TrackDetails'
|
155
|
+
has_one :tran_detail, TransactionDetail, :tab => 'TransactionDetail'
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
class Place
|
160
|
+
include HappyMapper
|
161
|
+
element :name, String
|
162
|
+
end
|
163
|
+
|
164
|
+
class Radar
|
165
|
+
include HappyMapper
|
166
|
+
has_many :places, Place
|
167
|
+
end
|
168
|
+
|
169
|
+
class Post
|
170
|
+
include HappyMapper
|
171
|
+
|
172
|
+
attribute :href, String
|
173
|
+
attribute :hash, String
|
174
|
+
attribute :description, String
|
175
|
+
attribute :tag, String
|
176
|
+
attribute :time, Time
|
177
|
+
attribute :others, Integer
|
178
|
+
attribute :extended, String
|
179
|
+
end
|
180
|
+
|
181
|
+
class User
|
182
|
+
include HappyMapper
|
183
|
+
|
184
|
+
element :id, Integer
|
185
|
+
element :name, String
|
186
|
+
element :screen_name, String
|
187
|
+
element :location, String
|
188
|
+
element :description, String
|
189
|
+
element :profile_image_url, String
|
190
|
+
element :url, String
|
191
|
+
element :protected, Boolean
|
192
|
+
element :followers_count, Integer
|
193
|
+
|
194
|
+
attr_accessor :after_parse_called
|
195
|
+
attr_accessor :after_parse2_called
|
196
|
+
|
197
|
+
after_parse do |doc|
|
198
|
+
doc.after_parse_called = true
|
199
|
+
end
|
200
|
+
|
201
|
+
after_parse do |doc|
|
202
|
+
doc.after_parse2_called = true
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
class Status
|
207
|
+
include HappyMapper
|
208
|
+
|
209
|
+
element :id, Integer
|
210
|
+
element :text, String
|
211
|
+
element :created_at, Time
|
212
|
+
element :source, String
|
213
|
+
element :truncated, Boolean
|
214
|
+
element :in_reply_to_status_id, Integer
|
215
|
+
element :in_reply_to_user_id, Integer
|
216
|
+
element :favorited, Boolean
|
217
|
+
element :non_existent, String, :tag => 'dummy', :namespace => 'fake'
|
218
|
+
has_one :user, User
|
219
|
+
end
|
220
|
+
|
221
|
+
class CurrentWeather
|
222
|
+
include HappyMapper
|
223
|
+
|
224
|
+
tag 'ob'
|
225
|
+
namespace 'http://www.aws.com/aws'
|
226
|
+
element :temperature, Integer, :tag => 'temp'
|
227
|
+
element :feels_like, Integer, :tag => 'feels-like'
|
228
|
+
element :current_condition, String, :tag => 'current-condition', :attributes => {:icon => String}
|
229
|
+
end
|
230
|
+
|
231
|
+
class Address
|
232
|
+
include HappyMapper
|
233
|
+
|
234
|
+
tag 'address'
|
235
|
+
element :street, String
|
236
|
+
element :postcode, String
|
237
|
+
element :housenumber, String
|
238
|
+
element :city, String
|
239
|
+
element :country, String
|
240
|
+
end
|
241
|
+
|
242
|
+
# for type coercion
|
243
|
+
class ProductGroup < String; end
|
244
|
+
|
245
|
+
module PITA
|
246
|
+
class Item
|
247
|
+
include HappyMapper
|
248
|
+
|
249
|
+
tag 'Item' # if you put class in module you need tag
|
250
|
+
element :asin, String, :tag => 'ASIN'
|
251
|
+
element :detail_page_url, URI, :tag => 'DetailPageURL', :parser => :parse
|
252
|
+
element :manufacturer, String, :tag => 'Manufacturer', :deep => true
|
253
|
+
element :point, String, :tag => 'point', :namespace => 'http://www.georss.org/georss'
|
254
|
+
element :product_group, ProductGroup, :tag => 'ProductGroup', :deep => true, :parser => :new, :raw => true
|
255
|
+
end
|
256
|
+
|
257
|
+
class Items
|
258
|
+
include HappyMapper
|
259
|
+
|
260
|
+
tag 'Items' # if you put class in module you need tag
|
261
|
+
element :total_results, Integer, :tag => 'TotalResults'
|
262
|
+
element :total_pages, Integer, :tag => 'TotalPages'
|
263
|
+
has_many :items, Item
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
module GitHub
|
268
|
+
class Commit
|
269
|
+
include HappyMapper
|
270
|
+
|
271
|
+
tag "commit"
|
272
|
+
element :url, String
|
273
|
+
element :tree, String
|
274
|
+
element :message, String
|
275
|
+
element :id, String
|
276
|
+
element :'committed-date', Date
|
277
|
+
end
|
278
|
+
end
|
279
|
+
|
280
|
+
module Backpack
|
281
|
+
class Note
|
282
|
+
include HappyMapper
|
283
|
+
|
284
|
+
attribute :id, Integer
|
285
|
+
attribute :title, String
|
286
|
+
attribute :created_at, Date
|
287
|
+
|
288
|
+
content :body
|
289
|
+
end
|
290
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 3
|
8
|
-
-
|
9
|
-
version: 0.3.
|
8
|
+
- 2
|
9
|
+
version: 0.3.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- John Nunemaker
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-07-04 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -74,6 +74,7 @@ files:
|
|
74
74
|
- spec/fixtures/multi_street_address.xml
|
75
75
|
- spec/fixtures/multiple_namespaces.xml
|
76
76
|
- spec/fixtures/nested_namespaces.xml
|
77
|
+
- spec/fixtures/notes.xml
|
77
78
|
- spec/fixtures/pita.xml
|
78
79
|
- spec/fixtures/posts.xml
|
79
80
|
- spec/fixtures/product_default_namespace.xml
|
@@ -87,6 +88,7 @@ files:
|
|
87
88
|
- spec/happymapper_spec.rb
|
88
89
|
- spec/spec.opts
|
89
90
|
- spec/spec_helper.rb
|
91
|
+
- spec/support/models.rb
|
90
92
|
- License
|
91
93
|
- Rakefile
|
92
94
|
- README.rdoc
|