happymapper-swanandp 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/License +20 -0
  2. data/README.rdoc +55 -0
  3. data/Rakefile +35 -0
  4. data/examples/amazon.rb +34 -0
  5. data/examples/current_weather.rb +21 -0
  6. data/examples/dashed_elements.rb +20 -0
  7. data/examples/multi_street_address.rb +30 -0
  8. data/examples/post.rb +19 -0
  9. data/examples/twitter.rb +37 -0
  10. data/lib/happymapper.rb +321 -0
  11. data/lib/happymapper/attribute.rb +3 -0
  12. data/lib/happymapper/element.rb +3 -0
  13. data/lib/happymapper/item.rb +179 -0
  14. data/lib/happymapper/version.rb +3 -0
  15. data/spec/fixtures/address.xml +8 -0
  16. data/spec/fixtures/analytics.xml +61 -0
  17. data/spec/fixtures/commit.xml +52 -0
  18. data/spec/fixtures/current_weather.xml +89 -0
  19. data/spec/fixtures/family_tree.xml +7 -0
  20. data/spec/fixtures/multi_street_address.xml +9 -0
  21. data/spec/fixtures/multiple_namespaces.xml +170 -0
  22. data/spec/fixtures/nested_namespaces.xml +17 -0
  23. data/spec/fixtures/notes.xml +9 -0
  24. data/spec/fixtures/pita.xml +133 -0
  25. data/spec/fixtures/posts.xml +23 -0
  26. data/spec/fixtures/product_default_namespace.xml +10 -0
  27. data/spec/fixtures/product_no_namespace.xml +10 -0
  28. data/spec/fixtures/product_single_namespace.xml +10 -0
  29. data/spec/fixtures/radar.xml +21 -0
  30. data/spec/fixtures/raw.xml +9 -0
  31. data/spec/fixtures/statuses.xml +422 -0
  32. data/spec/happymapper_attribute_spec.rb +17 -0
  33. data/spec/happymapper_element_spec.rb +17 -0
  34. data/spec/happymapper_item_spec.rb +115 -0
  35. data/spec/happymapper_spec.rb +404 -0
  36. data/spec/happymapper_to_xml_namespaces_spec.rb +149 -0
  37. data/spec/happymapper_to_xml_spec.rb +138 -0
  38. data/spec/spec.opts +1 -0
  39. data/spec/spec_helper.rb +9 -0
  40. data/spec/support/models.rb +323 -0
  41. metadata +121 -0
@@ -0,0 +1,149 @@
1
+ require 'spec_helper'
2
+
3
+ module ToXMLWithNamespaces
4
+
5
+ #
6
+ # Similar example as the to_xml but this time with namespacing
7
+ #
8
+ class Address
9
+ include HappyMapper
10
+
11
+ register_namespace 'address', 'http://www.company.com/address'
12
+ register_namespace 'country', 'http://www.company.com/country'
13
+
14
+ tag 'Address'
15
+ namespace 'address'
16
+
17
+ element :country, 'Country', :tag => 'country', :namespace => 'country'
18
+
19
+
20
+ attribute :location, String
21
+
22
+ element :street, String
23
+ element :postcode, String
24
+ element :city, String
25
+
26
+ element :housenumber, String
27
+
28
+ #
29
+ # to_xml will default to the attr_accessor method and not the attribute,
30
+ # allowing for that to be overwritten
31
+ #
32
+ def housenumber
33
+ "[#{@housenumber}]"
34
+ end
35
+
36
+ #
37
+ # Write a empty element even if this is not specified
38
+ #
39
+ element :description, String, :state_when_nil => true
40
+
41
+ #
42
+ # Perform the on_save operation when saving
43
+ #
44
+ has_one :date_created, Time, :on_save => lambda {|time| DateTime.parse(time).strftime("%T %D") if time }
45
+
46
+ #
47
+ # Write multiple elements and call on_save when saving
48
+ #
49
+ has_many :dates_updated, Time, :on_save => lambda {|times|
50
+ times.compact.map {|time| DateTime.parse(time).strftime("%T %D") } if times }
51
+
52
+ #
53
+ # Class composition
54
+ #
55
+
56
+ def initialize(parameters)
57
+ parameters.each_pair do |property,value|
58
+ send("#{property}=",value) if respond_to?("#{property}=")
59
+ end
60
+ end
61
+
62
+ end
63
+
64
+ #
65
+ # Country is composed above the in Address class. Here is a demonstration
66
+ # of how to_xml will handle class composition as well as utilizing the tag
67
+ # value.
68
+ #
69
+ class Country
70
+ include HappyMapper
71
+
72
+ register_namespace 'countryName', 'http://www.company.com/countryName'
73
+
74
+ attribute :code, String, :tag => 'countryCode'
75
+ has_one :name, String, :tag => 'countryName', :namespace => 'countryName'
76
+
77
+ def initialize(parameters)
78
+ parameters.each_pair do |property,value|
79
+ send("#{property}=",value) if respond_to?("#{property}=")
80
+ end
81
+ end
82
+
83
+ end
84
+
85
+ describe "#to_xml" do
86
+
87
+ context "Address" do
88
+
89
+ before(:all) do
90
+ address = Address.new('street' => 'Mockingbird Lane',
91
+ 'location' => 'Home',
92
+ 'housenumber' => '1313',
93
+ 'postcode' => '98103',
94
+ 'city' => 'Seattle',
95
+ 'country' => Country.new(:name => 'USA', :code => 'us'),
96
+ 'date_created' => '2011-01-01 15:00:00')
97
+
98
+ address.dates_updated = ["2011-01-01 16:01:00","2011-01-02 11:30:01"]
99
+
100
+ @address_xml = XML::Parser.string(address.to_xml).parse.root
101
+ end
102
+
103
+ { 'street' => 'Mockingbird Lane',
104
+ 'postcode' => '98103',
105
+ 'city' => 'Seattle' }.each_pair do |property,value|
106
+
107
+ it "should have the element '#{property}' with the value '#{value}'" do
108
+ @address_xml.find("address:#{property}").first.child.to_s.should == value
109
+ end
110
+
111
+ end
112
+
113
+ it "should use the result of #housenumber method (not the @housenumber)" do
114
+ @address_xml.find("address:housenumber").first.child.to_s.should == "[1313]"
115
+ end
116
+
117
+ it "should have the attribute 'location' with the value 'Home'" do
118
+ @address_xml.find('@location').first.child.to_s.should == "Home"
119
+ end
120
+
121
+ it "should add an empty description element" do
122
+ @address_xml.find('address:description').first.child.to_s.should == ""
123
+ end
124
+
125
+ it "should call #on_save when saving the time to convert the time" do
126
+ @address_xml.find('address:date_created').first.child.to_s.should == "15:00:00 01/01/11"
127
+ end
128
+
129
+ it "should handle multiple elements for 'has_many'" do
130
+ dates_updated = @address_xml.find('address:dates_updated')
131
+ dates_updated.length.should == 2
132
+ dates_updated.first.child.to_s.should == "16:01:00 01/01/11"
133
+ dates_updated.last.child.to_s.should == "11:30:01 01/02/11"
134
+ end
135
+
136
+ it "should write the country code" do
137
+ @address_xml.find('country:country/@country:countryCode').first.child.to_s.should == "us"
138
+ end
139
+
140
+ it "should write the country name" do
141
+ @address_xml.find('country:country/countryName:countryName').first.child.to_s.should == "USA"
142
+ end
143
+
144
+ end
145
+
146
+
147
+ end
148
+
149
+ end
@@ -0,0 +1,138 @@
1
+ require 'spec_helper'
2
+
3
+ module ToXML
4
+
5
+ class Address
6
+ include HappyMapper
7
+
8
+ tag 'address'
9
+
10
+ attribute :location, String
11
+
12
+ element :street, String
13
+ element :postcode, String
14
+ element :city, String
15
+
16
+ element :housenumber, String
17
+
18
+ #
19
+ # to_xml will default to the attr_accessor method and not the attribute,
20
+ # allowing for that to be overwritten
21
+ #
22
+ def housenumber
23
+ "[#{@housenumber}]"
24
+ end
25
+
26
+ #
27
+ # Write a empty element even if this is not specified
28
+ #
29
+ element :description, String, :state_when_nil => true
30
+
31
+ #
32
+ # Perform the on_save operation when saving
33
+ #
34
+ has_one :date_created, Time, :on_save => lambda {|time| DateTime.parse(time).strftime("%T %D") if time }
35
+
36
+ #
37
+ # Write multiple elements and call on_save when saving
38
+ #
39
+ has_many :dates_updated, Time, :on_save => lambda {|times|
40
+ times.compact.map {|time| DateTime.parse(time).strftime("%T %D") } if times }
41
+
42
+ #
43
+ # Class composition
44
+ #
45
+ element :country, 'Country', :tag => 'country'
46
+
47
+ def initialize(parameters)
48
+ parameters.each_pair do |property,value|
49
+ send("#{property}=",value) if respond_to?("#{property}=")
50
+ end
51
+ end
52
+
53
+ end
54
+
55
+ #
56
+ # Country is composed above the in Address class. Here is a demonstration
57
+ # of how to_xml will handle class composition as well as utilizing the tag
58
+ # value.
59
+ #
60
+ class Country
61
+ include HappyMapper
62
+
63
+ attribute :code, String, :tag => 'countryCode'
64
+ has_one :name, String, :tag => 'countryName'
65
+
66
+ def initialize(parameters)
67
+ parameters.each_pair do |property,value|
68
+ send("#{property}=",value) if respond_to?("#{property}=")
69
+ end
70
+ end
71
+
72
+ end
73
+
74
+ describe "#to_xml" do
75
+
76
+ context "Address" do
77
+
78
+ before(:all) do
79
+ address = Address.new('street' => 'Mockingbird Lane',
80
+ 'location' => 'Home',
81
+ 'housenumber' => '1313',
82
+ 'postcode' => '98103',
83
+ 'city' => 'Seattle',
84
+ 'country' => Country.new(:name => 'USA', :code => 'us'),
85
+ 'date_created' => '2011-01-01 15:00:00')
86
+
87
+ address.dates_updated = ["2011-01-01 16:01:00","2011-01-02 11:30:01"]
88
+
89
+ @address_xml = XML::Parser.string(address.to_xml).parse.root
90
+ end
91
+
92
+ { 'street' => 'Mockingbird Lane',
93
+ 'postcode' => '98103',
94
+ 'city' => 'Seattle' }.each_pair do |property,value|
95
+
96
+ it "should have the element '#{property}' with the value '#{value}'" do
97
+ @address_xml.find("#{property}").first.child.to_s.should == value
98
+ end
99
+
100
+ end
101
+
102
+ it "should use the result of #housenumber method (not the @housenumber)" do
103
+ @address_xml.find("housenumber").first.child.to_s.should == "[1313]"
104
+ end
105
+
106
+ it "should have the attribute 'location' with the value 'Home'" do
107
+ @address_xml.find('@location').first.child.to_s.should == "Home"
108
+ end
109
+
110
+ it "should add an empty description element" do
111
+ @address_xml.find('description').first.child.to_s.should == ""
112
+ end
113
+
114
+ it "should call #on_save when saving the time to convert the time" do
115
+ @address_xml.find('date_created').first.child.to_s.should == "15:00:00 01/01/11"
116
+ end
117
+
118
+ it "should handle multiple elements for 'has_many'" do
119
+ dates_updated = @address_xml.find('dates_updated')
120
+ dates_updated.length.should == 2
121
+ dates_updated.first.child.to_s.should == "16:01:00 01/01/11"
122
+ dates_updated.last.child.to_s.should == "11:30:01 01/02/11"
123
+ end
124
+
125
+ it "should write the country code" do
126
+ @address_xml.find('country/@countryCode').first.child.to_s.should == "us"
127
+ end
128
+
129
+ it "should write the country name" do
130
+ @address_xml.find('country/countryName').first.child.to_s.should == "USA"
131
+ end
132
+
133
+ end
134
+
135
+
136
+ end
137
+
138
+ end
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'spec'
5
+ require File.expand_path('../../lib/happymapper', __FILE__)
6
+
7
+ def fixture_file(filename)
8
+ File.read(File.dirname(__FILE__) + "/fixtures/#{filename}")
9
+ end
@@ -0,0 +1,323 @@
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
+ class MultiStreetAddress
243
+ include HappyMapper
244
+
245
+ tag 'address'
246
+ # allow primitive type to be collection
247
+ has_many :street_address, String, :tag => "streetaddress"
248
+ element :city, String
249
+ element :state_or_providence, String, :tag => "stateOfProvidence"
250
+ element :zip, String
251
+ element :country, String
252
+ end
253
+
254
+ # for type coercion
255
+ class ProductGroup < String; end
256
+
257
+ module PITA
258
+ class Item
259
+ include HappyMapper
260
+
261
+ tag 'Item' # if you put class in module you need tag
262
+ element :asin, String, :tag => 'ASIN'
263
+ element :detail_page_url, URI, :tag => 'DetailPageURL', :parser => :parse
264
+ element :manufacturer, String, :tag => 'Manufacturer', :deep => true
265
+ element :point, String, :tag => 'point', :namespace => 'http://www.georss.org/georss'
266
+ element :product_group, ProductGroup, :tag => 'ProductGroup', :deep => true, :parser => :new, :raw => true
267
+ end
268
+
269
+ class Items
270
+ include HappyMapper
271
+
272
+ tag 'Items' # if you put class in module you need tag
273
+ element :total_results, Integer, :tag => 'TotalResults'
274
+ element :total_pages, Integer, :tag => 'TotalPages'
275
+ has_many :items, Item
276
+ end
277
+ end
278
+
279
+ module GitHub
280
+ class Commit
281
+ include HappyMapper
282
+
283
+ tag "commit"
284
+ element :url, String
285
+ element :tree, String
286
+ element :message, String
287
+ element :id, String
288
+ element :'committed-date', Date
289
+ end
290
+ end
291
+
292
+ module Backpack
293
+ class Note
294
+ include HappyMapper
295
+
296
+ attribute :id, Integer
297
+ attribute :title, String
298
+ attribute :created_at, Date
299
+
300
+ content :body
301
+ end
302
+ end
303
+
304
+ module RawXml
305
+ class CustomStuff
306
+ include HappyMapper
307
+ raw_content :body
308
+ tag :custom
309
+ end
310
+
311
+ class Address
312
+ include HappyMapper
313
+
314
+ tag 'address'
315
+ element :street, String
316
+ element :postcode, String
317
+ element :housenumber, String
318
+ element :city, String
319
+ element :country, String
320
+ has_one :custom_stuff, RawXml::CustomStuff
321
+ end
322
+
323
+ end