woahdae-consumer 0.8.1
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/History.txt +4 -0
- data/LICENSE +20 -0
- data/Manifest.txt +73 -0
- data/PostInstall.txt +8 -0
- data/README.rdoc +53 -0
- data/Rakefile +30 -0
- data/app_generators/consumer/USAGE +14 -0
- data/app_generators/consumer/consumer_generator.rb +89 -0
- data/app_generators/consumer/templates/LICENSE +20 -0
- data/app_generators/consumer/templates/README.rdoc +3 -0
- data/app_generators/consumer/templates/Rakefile +57 -0
- data/app_generators/consumer/templates/TODO +4 -0
- data/app_generators/consumer/templates/config/config.yml +2 -0
- data/app_generators/consumer/templates/config/config.yml.sample +1 -0
- data/app_generators/consumer/templates/lib/base.rb +6 -0
- data/app_generators/consumer/templates/rails/init.rb +1 -0
- data/app_generators/consumer/templates/script/destroy +14 -0
- data/app_generators/consumer/templates/script/generate +14 -0
- data/app_generators/consumer/templates/spec/spec_helper.rb +11 -0
- data/bin/consumer +17 -0
- data/config/website.yml.sample +2 -0
- data/consumer.gemspec +48 -0
- data/consumer_generators/request/USAGE +25 -0
- data/consumer_generators/request/request_generator.rb +94 -0
- data/consumer_generators/request/templates/lib/request.rb +55 -0
- data/consumer_generators/request/templates/lib/response.rb +12 -0
- data/consumer_generators/request/templates/spec/request_spec.rb +27 -0
- data/consumer_generators/request/templates/spec/response_spec.rb +10 -0
- data/consumer_generators/request/templates/spec/xml/response.xml +0 -0
- data/examples/active_record/README.txt +1 -0
- data/examples/active_record/ar_spec.rb +33 -0
- data/examples/active_record/database.sqlite +0 -0
- data/examples/active_record/environment.rb +15 -0
- data/examples/active_record/migration.rb +21 -0
- data/examples/active_record/models/book.rb +13 -0
- data/examples/active_record/models/contributor.rb +12 -0
- data/examples/active_record/xml/book.xml +6 -0
- data/examples/active_record/xml/book_with_contributors.xml +11 -0
- data/examples/active_record/xml/contributor.xml +3 -0
- data/examples/active_record/xml/contributor_with_books.xml +19 -0
- data/examples/shipping/environment.rb +3 -0
- data/examples/shipping/rate.rb +15 -0
- data/examples/shipping/shipping.yml.sample +8 -0
- data/examples/shipping/shipping_spec.rb +27 -0
- data/examples/shipping/ups_rate_request.rb +182 -0
- data/examples/shipping/ups_rate_response.xml +340 -0
- data/lib/consumer/helper.rb +111 -0
- data/lib/consumer/mapping.rb +184 -0
- data/lib/consumer/request.rb +280 -0
- data/lib/consumer.rb +28 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +71 -0
- data/spec/helper_spec.rb +136 -0
- data/spec/mapping_spec.rb +94 -0
- data/spec/request_spec.rb +75 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/xml/rate_response.xml +14 -0
- data/spec/xml/rate_response_error.xml +35 -0
- data/tasks/rspec.rake +21 -0
- data/test/test_consumer_generator.rb +68 -0
- data/test/test_generator_helper.rb +29 -0
- data/website/index.html +11 -0
- data/website/index.txt +81 -0
- data/website/javascripts/rounded_corners_lite.inc.js +285 -0
- data/website/stylesheets/screen.css +159 -0
- data/website/template.html.erb +50 -0
- metadata +180 -0
@@ -0,0 +1,340 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<RatingServiceSelectionResponse>
|
3
|
+
<Response>
|
4
|
+
<TransactionReference>
|
5
|
+
<CustomerContext>RatingandService</CustomerContext>
|
6
|
+
<XpciVersion>1.0001</XpciVersion>
|
7
|
+
</TransactionReference>
|
8
|
+
<ResponseStatusCode>1</ResponseStatusCode>
|
9
|
+
<ResponseStatusDescription>Success</ResponseStatusDescription>
|
10
|
+
</Response>
|
11
|
+
<RatedShipment>
|
12
|
+
<Service>
|
13
|
+
<Code>03</Code>
|
14
|
+
</Service>
|
15
|
+
<RatedShipmentWarning>Yourinvoicemayvaryfromthedisplayedreferencerates</RatedShipmentWarning>
|
16
|
+
<BillingWeight>
|
17
|
+
<UnitOfMeasurement>
|
18
|
+
<Code>LBS</Code>
|
19
|
+
</UnitOfMeasurement>
|
20
|
+
<Weight>5.0</Weight>
|
21
|
+
</BillingWeight>
|
22
|
+
<TransportationCharges>
|
23
|
+
<CurrencyCode>USD</CurrencyCode>
|
24
|
+
<MonetaryValue>5.03</MonetaryValue>
|
25
|
+
</TransportationCharges>
|
26
|
+
<ServiceOptionsCharges>
|
27
|
+
<CurrencyCode>USD</CurrencyCode>
|
28
|
+
<MonetaryValue>0.00</MonetaryValue>
|
29
|
+
</ServiceOptionsCharges>
|
30
|
+
<TotalCharges>
|
31
|
+
<CurrencyCode>USD</CurrencyCode>
|
32
|
+
<MonetaryValue>5.03</MonetaryValue>
|
33
|
+
</TotalCharges>
|
34
|
+
<GuaranteedDaysToDelivery/>
|
35
|
+
<ScheduledDeliveryTime/>
|
36
|
+
<RatedPackage>
|
37
|
+
<TransportationCharges>
|
38
|
+
<CurrencyCode>USD</CurrencyCode>
|
39
|
+
<MonetaryValue>5.03</MonetaryValue>
|
40
|
+
</TransportationCharges>
|
41
|
+
<ServiceOptionsCharges>
|
42
|
+
<CurrencyCode>USD</CurrencyCode>
|
43
|
+
<MonetaryValue>0.00</MonetaryValue>
|
44
|
+
</ServiceOptionsCharges>
|
45
|
+
<TotalCharges>
|
46
|
+
<CurrencyCode>USD</CurrencyCode>
|
47
|
+
<MonetaryValue>5.03</MonetaryValue>
|
48
|
+
</TotalCharges>
|
49
|
+
<Weight>5.0</Weight>
|
50
|
+
<BillingWeight>
|
51
|
+
<UnitOfMeasurement>
|
52
|
+
<Code>LBS</Code>
|
53
|
+
</UnitOfMeasurement>
|
54
|
+
<Weight>5.0</Weight>
|
55
|
+
</BillingWeight>
|
56
|
+
</RatedPackage>
|
57
|
+
</RatedShipment>
|
58
|
+
<RatedShipment>
|
59
|
+
<Service>
|
60
|
+
<Code>12</Code>
|
61
|
+
</Service>
|
62
|
+
<RatedShipmentWarning>Yourinvoicemayvaryfromthedisplayedreferencerates</RatedShipmentWarning>
|
63
|
+
<BillingWeight>
|
64
|
+
<UnitOfMeasurement>
|
65
|
+
<Code>LBS</Code>
|
66
|
+
</UnitOfMeasurement>
|
67
|
+
<Weight>5.0</Weight>
|
68
|
+
</BillingWeight>
|
69
|
+
<TransportationCharges>
|
70
|
+
<CurrencyCode>USD</CurrencyCode>
|
71
|
+
<MonetaryValue>9.12</MonetaryValue>
|
72
|
+
</TransportationCharges>
|
73
|
+
<ServiceOptionsCharges>
|
74
|
+
<CurrencyCode>USD</CurrencyCode>
|
75
|
+
<MonetaryValue>0.00</MonetaryValue>
|
76
|
+
</ServiceOptionsCharges>
|
77
|
+
<TotalCharges>
|
78
|
+
<CurrencyCode>USD</CurrencyCode>
|
79
|
+
<MonetaryValue>9.12</MonetaryValue>
|
80
|
+
</TotalCharges>
|
81
|
+
<GuaranteedDaysToDelivery>3</GuaranteedDaysToDelivery>
|
82
|
+
<ScheduledDeliveryTime/>
|
83
|
+
<RatedPackage>
|
84
|
+
<TransportationCharges>
|
85
|
+
<CurrencyCode>USD</CurrencyCode>
|
86
|
+
<MonetaryValue>9.12</MonetaryValue>
|
87
|
+
</TransportationCharges>
|
88
|
+
<ServiceOptionsCharges>
|
89
|
+
<CurrencyCode>USD</CurrencyCode>
|
90
|
+
<MonetaryValue>0.00</MonetaryValue>
|
91
|
+
</ServiceOptionsCharges>
|
92
|
+
<TotalCharges>
|
93
|
+
<CurrencyCode>USD</CurrencyCode>
|
94
|
+
<MonetaryValue>9.12</MonetaryValue>
|
95
|
+
</TotalCharges>
|
96
|
+
<Weight>5.0</Weight>
|
97
|
+
<BillingWeight>
|
98
|
+
<UnitOfMeasurement>
|
99
|
+
<Code>LBS</Code>
|
100
|
+
</UnitOfMeasurement>
|
101
|
+
<Weight>5.0</Weight>
|
102
|
+
</BillingWeight>
|
103
|
+
</RatedPackage>
|
104
|
+
</RatedShipment>
|
105
|
+
<RatedShipment>
|
106
|
+
<Service>
|
107
|
+
<Code>59</Code>
|
108
|
+
</Service>
|
109
|
+
<RatedShipmentWarning>Yourinvoicemayvaryfromthedisplayedreferencerates</RatedShipmentWarning>
|
110
|
+
<BillingWeight>
|
111
|
+
<UnitOfMeasurement>
|
112
|
+
<Code>LBS</Code>
|
113
|
+
</UnitOfMeasurement>
|
114
|
+
<Weight>5.0</Weight>
|
115
|
+
</BillingWeight>
|
116
|
+
<TransportationCharges>
|
117
|
+
<CurrencyCode>USD</CurrencyCode>
|
118
|
+
<MonetaryValue>14.91</MonetaryValue>
|
119
|
+
</TransportationCharges>
|
120
|
+
<ServiceOptionsCharges>
|
121
|
+
<CurrencyCode>USD</CurrencyCode>
|
122
|
+
<MonetaryValue>0.00</MonetaryValue>
|
123
|
+
</ServiceOptionsCharges>
|
124
|
+
<TotalCharges>
|
125
|
+
<CurrencyCode>USD</CurrencyCode>
|
126
|
+
<MonetaryValue>14.91</MonetaryValue>
|
127
|
+
</TotalCharges>
|
128
|
+
<GuaranteedDaysToDelivery>2</GuaranteedDaysToDelivery>
|
129
|
+
<ScheduledDeliveryTime>10:30A.M.</ScheduledDeliveryTime>
|
130
|
+
<RatedPackage>
|
131
|
+
<TransportationCharges>
|
132
|
+
<CurrencyCode>USD</CurrencyCode>
|
133
|
+
<MonetaryValue>14.91</MonetaryValue>
|
134
|
+
</TransportationCharges>
|
135
|
+
<ServiceOptionsCharges>
|
136
|
+
<CurrencyCode>USD</CurrencyCode>
|
137
|
+
<MonetaryValue>0.00</MonetaryValue>
|
138
|
+
</ServiceOptionsCharges>
|
139
|
+
<TotalCharges>
|
140
|
+
<CurrencyCode>USD</CurrencyCode>
|
141
|
+
<MonetaryValue>14.91</MonetaryValue>
|
142
|
+
</TotalCharges>
|
143
|
+
<Weight>5.0</Weight>
|
144
|
+
<BillingWeight>
|
145
|
+
<UnitOfMeasurement>
|
146
|
+
<Code>LBS</Code>
|
147
|
+
</UnitOfMeasurement>
|
148
|
+
<Weight>5.0</Weight>
|
149
|
+
</BillingWeight>
|
150
|
+
</RatedPackage>
|
151
|
+
</RatedShipment>
|
152
|
+
<RatedShipment>
|
153
|
+
<Service>
|
154
|
+
<Code>02</Code>
|
155
|
+
</Service>
|
156
|
+
<RatedShipmentWarning>Yourinvoicemayvaryfromthedisplayedreferencerates</RatedShipmentWarning>
|
157
|
+
<BillingWeight>
|
158
|
+
<UnitOfMeasurement>
|
159
|
+
<Code>LBS</Code>
|
160
|
+
</UnitOfMeasurement>
|
161
|
+
<Weight>5.0</Weight>
|
162
|
+
</BillingWeight>
|
163
|
+
<TransportationCharges>
|
164
|
+
<CurrencyCode>USD</CurrencyCode>
|
165
|
+
<MonetaryValue>12.79</MonetaryValue>
|
166
|
+
</TransportationCharges>
|
167
|
+
<ServiceOptionsCharges>
|
168
|
+
<CurrencyCode>USD</CurrencyCode>
|
169
|
+
<MonetaryValue>0.00</MonetaryValue>
|
170
|
+
</ServiceOptionsCharges>
|
171
|
+
<TotalCharges>
|
172
|
+
<CurrencyCode>USD</CurrencyCode>
|
173
|
+
<MonetaryValue>12.79</MonetaryValue>
|
174
|
+
</TotalCharges>
|
175
|
+
<GuaranteedDaysToDelivery>2</GuaranteedDaysToDelivery>
|
176
|
+
<ScheduledDeliveryTime/>
|
177
|
+
<RatedPackage>
|
178
|
+
<TransportationCharges>
|
179
|
+
<CurrencyCode>USD</CurrencyCode>
|
180
|
+
<MonetaryValue>12.79</MonetaryValue>
|
181
|
+
</TransportationCharges>
|
182
|
+
<ServiceOptionsCharges>
|
183
|
+
<CurrencyCode>USD</CurrencyCode>
|
184
|
+
<MonetaryValue>0.00</MonetaryValue>
|
185
|
+
</ServiceOptionsCharges>
|
186
|
+
<TotalCharges>
|
187
|
+
<CurrencyCode>USD</CurrencyCode>
|
188
|
+
<MonetaryValue>12.79</MonetaryValue>
|
189
|
+
</TotalCharges>
|
190
|
+
<Weight>5.0</Weight>
|
191
|
+
<BillingWeight>
|
192
|
+
<UnitOfMeasurement>
|
193
|
+
<Code>LBS</Code>
|
194
|
+
</UnitOfMeasurement>
|
195
|
+
<Weight>5.0</Weight>
|
196
|
+
</BillingWeight>
|
197
|
+
</RatedPackage>
|
198
|
+
</RatedShipment>
|
199
|
+
<RatedShipment>
|
200
|
+
<Service>
|
201
|
+
<Code>13</Code>
|
202
|
+
</Service>
|
203
|
+
<RatedShipmentWarning>Yourinvoicemayvaryfromthedisplayedreferencerates</RatedShipmentWarning>
|
204
|
+
<BillingWeight>
|
205
|
+
<UnitOfMeasurement>
|
206
|
+
<Code>LBS</Code>
|
207
|
+
</UnitOfMeasurement>
|
208
|
+
<Weight>5.0</Weight>
|
209
|
+
</BillingWeight>
|
210
|
+
<TransportationCharges>
|
211
|
+
<CurrencyCode>USD</CurrencyCode>
|
212
|
+
<MonetaryValue>23.71</MonetaryValue>
|
213
|
+
</TransportationCharges>
|
214
|
+
<ServiceOptionsCharges>
|
215
|
+
<CurrencyCode>USD</CurrencyCode>
|
216
|
+
<MonetaryValue>0.00</MonetaryValue>
|
217
|
+
</ServiceOptionsCharges>
|
218
|
+
<TotalCharges>
|
219
|
+
<CurrencyCode>USD</CurrencyCode>
|
220
|
+
<MonetaryValue>23.71</MonetaryValue>
|
221
|
+
</TotalCharges>
|
222
|
+
<GuaranteedDaysToDelivery>1</GuaranteedDaysToDelivery>
|
223
|
+
<ScheduledDeliveryTime>3:00P.M.</ScheduledDeliveryTime>
|
224
|
+
<RatedPackage>
|
225
|
+
<TransportationCharges>
|
226
|
+
<CurrencyCode>USD</CurrencyCode>
|
227
|
+
<MonetaryValue>23.71</MonetaryValue>
|
228
|
+
</TransportationCharges>
|
229
|
+
<ServiceOptionsCharges>
|
230
|
+
<CurrencyCode>USD</CurrencyCode>
|
231
|
+
<MonetaryValue>0.00</MonetaryValue>
|
232
|
+
</ServiceOptionsCharges>
|
233
|
+
<TotalCharges>
|
234
|
+
<CurrencyCode>USD</CurrencyCode>
|
235
|
+
<MonetaryValue>23.71</MonetaryValue>
|
236
|
+
</TotalCharges>
|
237
|
+
<Weight>5.0</Weight>
|
238
|
+
<BillingWeight>
|
239
|
+
<UnitOfMeasurement>
|
240
|
+
<Code>LBS</Code>
|
241
|
+
</UnitOfMeasurement>
|
242
|
+
<Weight>5.0</Weight>
|
243
|
+
</BillingWeight>
|
244
|
+
</RatedPackage>
|
245
|
+
</RatedShipment>
|
246
|
+
<RatedShipment>
|
247
|
+
<Service>
|
248
|
+
<Code>14</Code>
|
249
|
+
</Service>
|
250
|
+
<RatedShipmentWarning>Yourinvoicemayvaryfromthedisplayedreferencerates</RatedShipmentWarning>
|
251
|
+
<BillingWeight>
|
252
|
+
<UnitOfMeasurement>
|
253
|
+
<Code>LBS</Code>
|
254
|
+
</UnitOfMeasurement>
|
255
|
+
<Weight>5.0</Weight>
|
256
|
+
</BillingWeight>
|
257
|
+
<TransportationCharges>
|
258
|
+
<CurrencyCode>USD</CurrencyCode>
|
259
|
+
<MonetaryValue>64.25</MonetaryValue>
|
260
|
+
</TransportationCharges>
|
261
|
+
<ServiceOptionsCharges>
|
262
|
+
<CurrencyCode>USD</CurrencyCode>
|
263
|
+
<MonetaryValue>0.00</MonetaryValue>
|
264
|
+
</ServiceOptionsCharges>
|
265
|
+
<TotalCharges>
|
266
|
+
<CurrencyCode>USD</CurrencyCode>
|
267
|
+
<MonetaryValue>64.25</MonetaryValue>
|
268
|
+
</TotalCharges>
|
269
|
+
<GuaranteedDaysToDelivery>1</GuaranteedDaysToDelivery>
|
270
|
+
<ScheduledDeliveryTime>8:00A.M.</ScheduledDeliveryTime>
|
271
|
+
<RatedPackage>
|
272
|
+
<TransportationCharges>
|
273
|
+
<CurrencyCode>USD</CurrencyCode>
|
274
|
+
<MonetaryValue>64.25</MonetaryValue>
|
275
|
+
</TransportationCharges>
|
276
|
+
<ServiceOptionsCharges>
|
277
|
+
<CurrencyCode>USD</CurrencyCode>
|
278
|
+
<MonetaryValue>0.00</MonetaryValue>
|
279
|
+
</ServiceOptionsCharges>
|
280
|
+
<TotalCharges>
|
281
|
+
<CurrencyCode>USD</CurrencyCode>
|
282
|
+
<MonetaryValue>64.25</MonetaryValue>
|
283
|
+
</TotalCharges>
|
284
|
+
<Weight>5.0</Weight>
|
285
|
+
<BillingWeight>
|
286
|
+
<UnitOfMeasurement>
|
287
|
+
<Code>LBS</Code>
|
288
|
+
</UnitOfMeasurement>
|
289
|
+
<Weight>5.0</Weight>
|
290
|
+
</BillingWeight>
|
291
|
+
</RatedPackage>
|
292
|
+
</RatedShipment>
|
293
|
+
<RatedShipment>
|
294
|
+
<Service>
|
295
|
+
<Code>01</Code>
|
296
|
+
</Service>
|
297
|
+
<RatedShipmentWarning>Yourinvoicemayvaryfromthedisplayedreferencerates</RatedShipmentWarning>
|
298
|
+
<BillingWeight>
|
299
|
+
<UnitOfMeasurement>
|
300
|
+
<Code>LBS</Code>
|
301
|
+
</UnitOfMeasurement>
|
302
|
+
<Weight>5.0</Weight>
|
303
|
+
</BillingWeight>
|
304
|
+
<TransportationCharges>
|
305
|
+
<CurrencyCode>USD</CurrencyCode>
|
306
|
+
<MonetaryValue>27.63</MonetaryValue>
|
307
|
+
</TransportationCharges>
|
308
|
+
<ServiceOptionsCharges>
|
309
|
+
<CurrencyCode>USD</CurrencyCode>
|
310
|
+
<MonetaryValue>0.00</MonetaryValue>
|
311
|
+
</ServiceOptionsCharges>
|
312
|
+
<TotalCharges>
|
313
|
+
<CurrencyCode>USD</CurrencyCode>
|
314
|
+
<MonetaryValue>27.63</MonetaryValue>
|
315
|
+
</TotalCharges>
|
316
|
+
<GuaranteedDaysToDelivery>1</GuaranteedDaysToDelivery>
|
317
|
+
<ScheduledDeliveryTime>10:30A.M.</ScheduledDeliveryTime>
|
318
|
+
<RatedPackage>
|
319
|
+
<TransportationCharges>
|
320
|
+
<CurrencyCode>USD</CurrencyCode>
|
321
|
+
<MonetaryValue>27.63</MonetaryValue>
|
322
|
+
</TransportationCharges>
|
323
|
+
<ServiceOptionsCharges>
|
324
|
+
<CurrencyCode>USD</CurrencyCode>
|
325
|
+
<MonetaryValue>0.00</MonetaryValue>
|
326
|
+
</ServiceOptionsCharges>
|
327
|
+
<TotalCharges>
|
328
|
+
<CurrencyCode>USD</CurrencyCode>
|
329
|
+
<MonetaryValue>27.63</MonetaryValue>
|
330
|
+
</TotalCharges>
|
331
|
+
<Weight>5.0</Weight>
|
332
|
+
<BillingWeight>
|
333
|
+
<UnitOfMeasurement>
|
334
|
+
<Code>LBS</Code>
|
335
|
+
</UnitOfMeasurement>
|
336
|
+
<Weight>5.0</Weight>
|
337
|
+
</BillingWeight>
|
338
|
+
</RatedPackage>
|
339
|
+
</RatedShipment>
|
340
|
+
</RatingServiceSelectionResponse>
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module Consumer::Helper
|
2
|
+
# if you pass in a newline-less glob of xml it'll return an indented copy
|
3
|
+
# for improved readability.
|
4
|
+
def self.tidy(xml)
|
5
|
+
xml = xml.clone # avoid modifying @response_xml due to pass by reference
|
6
|
+
|
7
|
+
# remove all formatting to start from a common base
|
8
|
+
xml.gsub!(/\>[\t\n\r ]*\</, "><")
|
9
|
+
# replace empty tag pairs with <tag/>
|
10
|
+
xml.gsub!(/\<(\w*?)\>\<\/\1\>/, "<\\1/>")
|
11
|
+
# add in newlines after >, and sometimse before <
|
12
|
+
xml.gsub!(/\>\</,">\n<")
|
13
|
+
|
14
|
+
declaration = /\<\?xml/
|
15
|
+
start_tag = /\<[^\/]+?\>[\n\t\r ]+/
|
16
|
+
end_tag = /^[\t ]*\<\//
|
17
|
+
|
18
|
+
## add appropriate spacing before each newline.
|
19
|
+
tab = 0
|
20
|
+
siblings = false
|
21
|
+
first_tag = true
|
22
|
+
return xml.collect do |line|
|
23
|
+
next line if line =~ declaration
|
24
|
+
|
25
|
+
# calculate the indentation.
|
26
|
+
# In general we want to add spacing if it's a start tag or leaf node, and
|
27
|
+
# remove spacing if it's an end tag. The only times we don't want to add
|
28
|
+
# spacing is if it's the very first node or the previous node was a sibling
|
29
|
+
# instead of a parent.
|
30
|
+
if line =~ end_tag
|
31
|
+
tab -= 1
|
32
|
+
else
|
33
|
+
tab += 1 unless first_tag || siblings
|
34
|
+
end
|
35
|
+
|
36
|
+
# if the line is a start tag, the next lines will no longer be siblings
|
37
|
+
siblings = line =~ start_tag ? false : true
|
38
|
+
first_tag = false
|
39
|
+
|
40
|
+
# return line with appropriate amount of preceding spaces #
|
41
|
+
line = " " * (tab > 0 ? tab : 0) + line
|
42
|
+
end.join << "\n"
|
43
|
+
end
|
44
|
+
|
45
|
+
# returns a copy of the xml without empty nodes. Also removes internal
|
46
|
+
# (non-leaf) nodes that only contain empty leaves. Nodes containing only
|
47
|
+
# whitespace characters (space, newline, tab, and return) are considered empty.
|
48
|
+
def self.compact_xml(xml)
|
49
|
+
old_xml = xml
|
50
|
+
loop do
|
51
|
+
new_xml = old_xml.gsub(/\<(\w*?)\>[ \t\r\n]*\<\/\1\>\n?/, "")
|
52
|
+
if old_xml == new_xml # nothing was changed
|
53
|
+
return new_xml
|
54
|
+
else # something changed, so we'll go through it again
|
55
|
+
old_xml = new_xml
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# returns a hash of defaults if +self.yaml_defaults+ is defined and the file
|
61
|
+
# defined there exists, empty hash otherwise.
|
62
|
+
#
|
63
|
+
# Also takes a namespace, i.e. a sub-hash, and when given a namespace it also
|
64
|
+
# enables a global namespace called 'all'. Thus if you had the yaml:
|
65
|
+
#
|
66
|
+
# <pre>
|
67
|
+
# all:
|
68
|
+
# my_name: Buster
|
69
|
+
# greetings:
|
70
|
+
# hello: world
|
71
|
+
# other:
|
72
|
+
# irrelevant: data
|
73
|
+
# </pre>
|
74
|
+
#
|
75
|
+
# a namespace of 'greetings' would return the hash:
|
76
|
+
#
|
77
|
+
# <code>
|
78
|
+
# {"my_name" => "Buster", "hello" => "world"}
|
79
|
+
# </code>
|
80
|
+
#
|
81
|
+
# You don't have to use the global namespace, but if you do, it will be included
|
82
|
+
# everywhere.
|
83
|
+
def self.hash_from_yaml(base_path, file, namespace = nil)
|
84
|
+
begin
|
85
|
+
hash = (base_path && file) ? YAML.load(File.read(File.join(base_path, file))) : {}
|
86
|
+
rescue => e
|
87
|
+
raise ArgumentError, "YAML load error: #{e.message}"
|
88
|
+
end
|
89
|
+
|
90
|
+
return {} if !hash
|
91
|
+
|
92
|
+
if namespace
|
93
|
+
global = hash["all"] || {}
|
94
|
+
namespaced_hash = hash[namespace] || {}
|
95
|
+
hash = global.merge(namespaced_hash)
|
96
|
+
end
|
97
|
+
|
98
|
+
return hash
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.http_from_url(url)
|
102
|
+
uri = URI.parse url
|
103
|
+
http = Net::HTTP.new uri.host, uri.port
|
104
|
+
if uri.port == 443
|
105
|
+
http.use_ssl = true
|
106
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
107
|
+
end
|
108
|
+
return http, uri
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
@@ -0,0 +1,184 @@
|
|
1
|
+
module Consumer::Mapping
|
2
|
+
def self.included(base)
|
3
|
+
base.extend ClassMethods
|
4
|
+
end
|
5
|
+
|
6
|
+
### our lone instance method ###
|
7
|
+
|
8
|
+
##
|
9
|
+
# Same as doing:
|
10
|
+
#
|
11
|
+
# <code>self.association(s) = Association.from_xml(xml)</code>
|
12
|
+
# === Behaviors
|
13
|
+
# * sets the association to a call to Klass.from_xml
|
14
|
+
# === Parameters
|
15
|
+
# [+xml+] String of xml
|
16
|
+
# [+association+] The association name (i.e. self.something)
|
17
|
+
# [+klass+] The association class (i.e. Something.from_xml).
|
18
|
+
# Defaults to singular, capitalized +association+.
|
19
|
+
# === Returns
|
20
|
+
# Nothing in particular
|
21
|
+
def association_from_xml(xml, association, klass = nil)
|
22
|
+
klass ||= association.to_s.capitalize.singularize.constantize
|
23
|
+
|
24
|
+
association_instance = klass.from_xml(xml)
|
25
|
+
return if association_instance.nil?
|
26
|
+
|
27
|
+
self.send(association.to_s + "=", association_instance)
|
28
|
+
end
|
29
|
+
|
30
|
+
module ClassMethods
|
31
|
+
# Creates a new mapping hash in self.maps
|
32
|
+
# === Parameters
|
33
|
+
# The parameters here are used to add a new mapping hash to self.maps, which
|
34
|
+
# in turn is used by from_xml_via_map to instantiate new objects
|
35
|
+
# [+first_or_all+] If +:all+, from_xml_via_map will return an array instead
|
36
|
+
# of a single instance (i.e. sets map[:all] to true)
|
37
|
+
# [+base_path+] A fully qualified xpath, such as //SomethingResponse/bah.
|
38
|
+
# Also, uniquely identifies the map for a particular xml
|
39
|
+
# response in the case of multiple maps.
|
40
|
+
# [+registry+] A hash of :attribute => 'xpath' pairs. Xpaths are
|
41
|
+
# relative to +base_path+, but fully qualified xpaths are
|
42
|
+
# also valid.
|
43
|
+
#
|
44
|
+
# For example, if the base path was //Response/Bah and the
|
45
|
+
# registry was {:foo => "FooElm"}, then from_xml_via_map
|
46
|
+
# will set instance.foo to the value at
|
47
|
+
# //Response/Bah/FooElm in the xml. However, if you set
|
48
|
+
# {:foo => "//Response/Woot/Ack"}, then it will pull the
|
49
|
+
# value from //Response/Woot/Ack (not
|
50
|
+
# //Response/Bah/Response/Woot/Ack).
|
51
|
+
# [+options+] Valid options are:
|
52
|
+
# * +:include+ - sets map[:associations], which is an
|
53
|
+
# array of parameters to association_from_xml
|
54
|
+
# [+block+] In from_xml_via_map this gets called with the new
|
55
|
+
# instance as the last step of instantiation.
|
56
|
+
# === Returns
|
57
|
+
# The newly created map
|
58
|
+
# === Raises
|
59
|
+
# * RuntimeError if the base path is already defined in another mapping
|
60
|
+
# in the class
|
61
|
+
def map(first_or_all, base_path, registry, options = {}, &block)
|
62
|
+
if self.maps.find {|m| m[:base_path] == base_path}
|
63
|
+
raise "Base path exists: #{base_path}"
|
64
|
+
end
|
65
|
+
|
66
|
+
map = {
|
67
|
+
:all => first_or_all == :all ? true : false,
|
68
|
+
:base_path => base_path,
|
69
|
+
:registry => registry,
|
70
|
+
:associations => [*options[:include]].compact,
|
71
|
+
:block => block
|
72
|
+
}
|
73
|
+
self.maps << map
|
74
|
+
|
75
|
+
return map
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns @maps or []
|
79
|
+
def maps
|
80
|
+
@maps ||= []
|
81
|
+
end
|
82
|
+
|
83
|
+
# Pulls attributes from the xml using xpaths defined in the mapping whose
|
84
|
+
# base path matches the xml, and instantiates a new object with those attrs.
|
85
|
+
# === Behaviors
|
86
|
+
# * If multiple elements match the base path and map[:all] is true, it will
|
87
|
+
# return an array of objects.
|
88
|
+
# * Calls from_xml on elements in map[:associations] (see
|
89
|
+
# association_from_xml)
|
90
|
+
# * Calls map[:block] with the new instance (and optionally the libxml node)
|
91
|
+
# just before adding it to the return array for custom post-processing
|
92
|
+
# === Returns
|
93
|
+
# * An array of instances or a new instance depending on whether map[:all]
|
94
|
+
# is true or false, respectively
|
95
|
+
def from_xml_via_map(xml)
|
96
|
+
nodes, map = find_nodes_and_map(xml)
|
97
|
+
return nil if map.nil?
|
98
|
+
instances = []
|
99
|
+
|
100
|
+
nodes.each do |node|
|
101
|
+
attrs = attrs_from_node_and_registry(node, map[:registry])
|
102
|
+
instance = self.from_hash(attrs)
|
103
|
+
|
104
|
+
map[:associations].each do |association|
|
105
|
+
# TODO: spec
|
106
|
+
instance.association_from_xml(xml, association)
|
107
|
+
end
|
108
|
+
|
109
|
+
b = map[:block]
|
110
|
+
if b
|
111
|
+
case b.arity # number of parameters
|
112
|
+
when 1
|
113
|
+
b.call(instance)
|
114
|
+
when 2
|
115
|
+
b.call(instance, node)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
return instance unless map[:all]
|
120
|
+
instances << instance
|
121
|
+
end
|
122
|
+
|
123
|
+
return instances
|
124
|
+
end
|
125
|
+
|
126
|
+
# you can override this to what you want. Defaults to
|
127
|
+
# an alias for from_xml_via_map.
|
128
|
+
def from_xml(xml)
|
129
|
+
@xml = xml
|
130
|
+
self.before_from_xml if defined?(before_from_xml)
|
131
|
+
from_xml_via_map(@xml)
|
132
|
+
end
|
133
|
+
|
134
|
+
# initializes a new instance of self and uses the attribute setters to
|
135
|
+
# populate attributes from the hash. Objects inheriting from ActiveRecord
|
136
|
+
# do this automatically in initialize, but the world doesn't (always) revolve
|
137
|
+
# around AR
|
138
|
+
def from_hash(attrs)
|
139
|
+
object = self.new
|
140
|
+
|
141
|
+
attrs.each do |attribute, value|
|
142
|
+
object.send("#{attribute}=", value)
|
143
|
+
end
|
144
|
+
|
145
|
+
object
|
146
|
+
end
|
147
|
+
|
148
|
+
private
|
149
|
+
|
150
|
+
# find the first map whose base path matches the xml,
|
151
|
+
# and return the nodes found at that base path along with the map
|
152
|
+
# === Parameters
|
153
|
+
# [+xml+] - String of xml
|
154
|
+
# === Returns
|
155
|
+
# two-member array of the form [[LibXML::XML::XPath::Object], Consumer::Mapping::Map]
|
156
|
+
# === Raises
|
157
|
+
# nothing
|
158
|
+
def find_nodes_and_map(xml)
|
159
|
+
self.maps.each do |map|
|
160
|
+
doc = LibXML::XML::Parser.string(xml).parse
|
161
|
+
nodes = doc.find(map[:base_path])
|
162
|
+
return nodes, map if !nodes.empty?
|
163
|
+
end
|
164
|
+
return [], nil
|
165
|
+
puts "No map found in #{self.class} for xml #{xml[0..100]}..." if $DEBUG
|
166
|
+
end
|
167
|
+
|
168
|
+
# returns a hash of attribute => value pairs given an xpath node and a
|
169
|
+
# map registry
|
170
|
+
# (LibXML::XML::XPath::Object and Consumer::Mapping::Map#registry, respectively)
|
171
|
+
def attrs_from_node_and_registry(node, registry)
|
172
|
+
attrs = {}
|
173
|
+
|
174
|
+
registry.each do |attribute, path|
|
175
|
+
leaf = node.find(path).first
|
176
|
+
attrs[attribute] = leaf.content if leaf.respond_to?(:content)
|
177
|
+
attrs[attribute] = leaf.value if leaf.respond_to?(:value)
|
178
|
+
end
|
179
|
+
|
180
|
+
attrs
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
end
|