active_shipping 0.11.0 → 0.11.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4b36c0ee1b7b2ac743a5b950a23f40f006b5fcc9
4
+ data.tar.gz: 4a89bf43c4fde9d06f3e34aeee258a9c1990171d
5
+ SHA512:
6
+ metadata.gz: 1fe9164056568d8913f2f9230fb8a26cdb9f7ff5237c2ab4b7902fcfc1dd0e60b1615a8ccb999754c1f3349b32152fe8bb6f0503afe024452f36944d455d1517
7
+ data.tar.gz: 5a55bbce296ed30b42a172b4dc70519cefa409828b68d7018a537ad14ddb6cd7d5e21d8f39d494f789454a4f5049acc539f57b656ef4bcd47ae6c5956ec21bf7
@@ -132,6 +132,7 @@ After you've pushed your well-tested changes to your github fork, make a pull re
132
132
  * John Duff
133
133
  * Nigel Ramsay
134
134
  * Philip Arndt
135
+ * Vikram Oberoi
135
136
 
136
137
  ## Legal Mumbo Jumbo
137
138
 
@@ -1,3 +1,4 @@
1
+ require 'active_shipping/shipping/carriers/benchmark_carrier'
1
2
  require 'active_shipping/shipping/carriers/bogus_carrier'
2
3
  require 'active_shipping/shipping/carriers/ups'
3
4
  require 'active_shipping/shipping/carriers/usps'
@@ -13,7 +14,7 @@ module ActiveMerchant
13
14
  module Carriers
14
15
  class <<self
15
16
  def all
16
- [BogusCarrier, UPS, USPS, FedEx, Shipwire, Kunaki, CanadaPost, NewZealandPost, CanadaPostPWS]
17
+ [BenchmarkCarrier, BogusCarrier, UPS, USPS, FedEx, Shipwire, Kunaki, CanadaPost, NewZealandPost, CanadaPostPWS]
17
18
  end
18
19
  end
19
20
  end
@@ -0,0 +1,34 @@
1
+ # The time a 3rd-party shipping provider takes to respond to a request varies greatly.
2
+ # This class simulates these unpredictable delays in shipping rate retrieval so that
3
+ # load-testing tools run into situations that more accurately reflect the real world.
4
+
5
+ module ActiveMerchant
6
+ module Shipping
7
+ class BenchmarkCarrier < Carrier
8
+ cattr_reader :name
9
+ @@name = "Benchmark Carrier"
10
+
11
+ def find_rates(origin, destination, packages, options = {})
12
+ origin = Location.from(origin)
13
+ destination = Location.from(destination)
14
+ packages = Array(packages)
15
+
16
+ delay_time = generate_simulated_lag
17
+
18
+ bogus_estimate = RateEstimate.new(
19
+ origin, destination, @@name,
20
+ "Free Benchmark Shipping", :total_price => 0, :currency => 'USD',
21
+ :packages => packages, :delivery_range => [Time.now.utc.strftime("%Y-%d-%m"), Time.now.utc.strftime("%Y-%d-%m")]
22
+ )
23
+ RateResponse.new(true, "Success (delayed #{delay_time} seconds)", {:rate => 'free'}, :rates => [bogus_estimate], :xml => "<rate>free</rate>")
24
+ end
25
+
26
+ private
27
+
28
+ def generate_simulated_lag(max_delay = 30)
29
+ sleep Random.rand * max_delay
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -127,7 +127,7 @@ module ActiveMerchant
127
127
  request << XmlNode.new('merchantCPCID', @options[:login])
128
128
  request << XmlNode.new('fromPostalCode', origin.postal_code)
129
129
  request << XmlNode.new('turnAroundTime', options[:turn_around_time] ? options[:turn_around_time] : DEFAULT_TURN_AROUND_TIME)
130
- request << XmlNode.new('itemsPrice', dollar_amount(line_items.sum(&:value)))
130
+ request << XmlNode.new('itemsPrice', dollar_amount(line_items.map(&:value).compact.sum))
131
131
 
132
132
  #line items
133
133
  request << build_line_items(line_items)
@@ -211,12 +211,18 @@ module ActiveMerchant
211
211
  end
212
212
 
213
213
  def response_success?(xml)
214
+ return false unless xml.get_text('eparcel/error').nil?
215
+
214
216
  value = xml.get_text('eparcel/ratesAndServicesResponse/statusCode').to_s
215
217
  value == '1' || value == '2'
216
218
  end
217
219
 
218
220
  def response_message(xml)
219
- xml.get_text('eparcel/ratesAndServicesResponse/statusMessage').to_s
221
+ if response_success?(xml)
222
+ xml.get_text('eparcel/ratesAndServicesResponse/statusMessage').to_s
223
+ else
224
+ xml.get_text('eparcel/error/statusMessage').to_s
225
+ end
220
226
  end
221
227
 
222
228
  # <!-- List of items in the shopping -->
@@ -52,12 +52,13 @@ module ActiveMerchant
52
52
 
53
53
  MAX_WEIGHT = 30 # kg
54
54
 
55
- attr_accessor :language, :endpoint, :logger, :platform_id
55
+ attr_accessor :language, :endpoint, :logger, :platform_id, :customer_number
56
56
 
57
57
  def initialize(options = {})
58
58
  @language = LANGUAGE[options[:language]] || LANGUAGE['en']
59
59
  @endpoint = options[:endpoint] || ENDPOINT
60
60
  @platform_id = options[:platform_id]
61
+ @customer_number = options[:customer_number]
61
62
  super(options)
62
63
  end
63
64
 
@@ -618,7 +619,7 @@ module ActiveMerchant
618
619
  end
619
620
 
620
621
  def customer_number_node(options)
621
- XmlNode.new("customer-number", options[:customer_number])
622
+ XmlNode.new("customer-number", options[:customer_number] || customer_number)
622
623
  end
623
624
 
624
625
  def contract_id_node(options)
@@ -22,6 +22,9 @@ module ActiveMerchant
22
22
  "fedex_ground" => "FDXG",
23
23
  "fedex_express" => "FDXE"
24
24
  }
25
+
26
+ DELIVERY_ADDRESS_NODE_NAMES = %w(DestinationAddress ActualDeliveryAddress)
27
+ SHIPPER_ADDRESS_NODE_NAMES = %w(ShipperAddress)
25
28
 
26
29
  ServiceTypes = {
27
30
  "PRIORITY_OVERNIGHT" => "FedEx Priority Overnight",
@@ -47,7 +50,9 @@ module ActiveMerchant
47
50
  "GROUND_HOME_DELIVERY" => "FedEx Ground Home Delivery",
48
51
  "FEDEX_GROUND" => "FedEx Ground",
49
52
  "INTERNATIONAL_GROUND" => "FedEx International Ground",
50
- "SMART_POST" => "FedEx SmartPost"
53
+ "SMART_POST" => "FedEx SmartPost",
54
+ "FEDEX_FREIGHT_PRIORITY" => "FedEx Freight Priority",
55
+ "FEDEX_FREIGHT_ECONOMY" => "FedEx Freight Economy"
51
56
  }
52
57
 
53
58
  PackageTypes = {
@@ -175,9 +180,14 @@ module ActiveMerchant
175
180
 
176
181
  root_node << XmlNode.new('RequestedShipment') do |rs|
177
182
  rs << XmlNode.new('ShipTimestamp', ship_timestamp(options[:turn_around_time]))
178
- rs << XmlNode.new('DropoffType', options[:dropoff_type] || 'REGULAR_PICKUP')
179
- #rs << XmlNode.new('ServiceType', 'SMART_POST') # use this to test responses for specific services.
180
- rs << XmlNode.new('PackagingType', options[:packaging_type] || 'YOUR_PACKAGING')
183
+
184
+ freight = has_freight?(options)
185
+
186
+ if !freight
187
+ # fedex api wants this up here otherwise request returns an error
188
+ rs << XmlNode.new('DropoffType', options[:dropoff_type] || 'REGULAR_PICKUP')
189
+ rs << XmlNode.new('PackagingType', options[:packaging_type] || 'YOUR_PACKAGING')
190
+ end
181
191
 
182
192
  rs << build_location_node('Shipper', (options[:shipper] || origin))
183
193
  rs << build_location_node('Recipient', destination)
@@ -185,35 +195,89 @@ module ActiveMerchant
185
195
  rs << build_location_node('Origin', origin)
186
196
  end
187
197
 
188
- rs << XmlNode.new('SmartPostDetail') do |spd|
189
- spd << XmlNode.new('Indicia', options[:smart_post_indicia] || 'PARCEL_SELECT')
190
- spd << XmlNode.new('HubId', options[:smart_post_hub_id] || 5902) # default to LA
191
- end
198
+ if freight
199
+ # build xml for freight rate requests
200
+ freight_options = options[:freight]
201
+ rs << build_shipping_charges_payment_node(freight_options)
202
+ rs << build_freight_shipment_detail_node(freight_options, packages, imperial)
203
+ rs << build_rate_request_types_node
204
+ else
205
+ # build xml for non-freight rate requests
206
+ rs << XmlNode.new('SmartPostDetail') do |spd|
207
+ spd << XmlNode.new('Indicia', options[:smart_post_indicia] || 'PARCEL_SELECT')
208
+ spd << XmlNode.new('HubId', options[:smart_post_hub_id] || 5902) # default to LA
209
+ end
192
210
 
193
- rs << XmlNode.new('RateRequestTypes', 'ACCOUNT')
211
+ rs << build_rate_request_types_node
194
212
 
195
- rs << XmlNode.new('PackageCount', packages.size)
196
- packages.each do |pkg|
197
- rs << XmlNode.new('RequestedPackageLineItems') do |rps|
198
- rps << XmlNode.new('GroupPackageCount', 1)
199
- rps << XmlNode.new('Weight') do |tw|
200
- tw << XmlNode.new('Units', imperial ? 'LB' : 'KG')
201
- tw << XmlNode.new('Value', [((imperial ? pkg.lbs : pkg.kgs).to_f*1000).round/1000.0, 0.1].max)
202
- end
203
- rps << XmlNode.new('Dimensions') do |dimensions|
204
- [:length,:width,:height].each do |axis|
205
- value = ((imperial ? pkg.inches(axis) : pkg.cm(axis)).to_f*1000).round/1000.0 # 3 decimals
206
- dimensions << XmlNode.new(axis.to_s.capitalize, value.ceil)
207
- end
208
- dimensions << XmlNode.new('Units', imperial ? 'IN' : 'CM')
213
+ rs << XmlNode.new('PackageCount', packages.size)
214
+ packages.each do |pkg|
215
+ rs << XmlNode.new('RequestedPackageLineItems') do |rps|
216
+ rps << XmlNode.new('GroupPackageCount', 1)
217
+ rps << build_package_weight_node(pkg, imperial)
218
+ rps << build_package_dimensions_node(pkg, imperial)
209
219
  end
210
220
  end
211
221
  end
212
-
213
222
  end
214
223
  end
215
224
  xml_request.to_s
216
225
  end
226
+
227
+ def build_shipping_charges_payment_node(freight_options)
228
+ XmlNode.new('ShippingChargesPayment') do |shipping_charges_payment|
229
+ shipping_charges_payment << XmlNode.new('PaymentType', freight_options[:payment_type])
230
+ shipping_charges_payment << XmlNode.new('Payor') do |payor|
231
+ payor << XmlNode.new('ResponsibleParty') do |responsible_party|
232
+ # TODO: case of different freight account numbers?
233
+ responsible_party << XmlNode.new('AccountNumber', freight_options[:account])
234
+ end
235
+ end
236
+ end
237
+ end
238
+
239
+ def build_freight_shipment_detail_node(freight_options, packages, imperial)
240
+ XmlNode.new('FreightShipmentDetail') do |freight_shipment_detail|
241
+ # TODO: case of different freight account numbers?
242
+ freight_shipment_detail << XmlNode.new('FedExFreightAccountNumber', freight_options[:account])
243
+ freight_shipment_detail << build_location_node('FedExFreightBillingContactAndAddress', freight_options[:billing_location])
244
+ freight_shipment_detail << XmlNode.new('Role', freight_options[:role])
245
+
246
+ packages.each do |pkg|
247
+ freight_shipment_detail << XmlNode.new('LineItems') do |line_items|
248
+ line_items << XmlNode.new('FreightClass', freight_options[:freight_class])
249
+ line_items << XmlNode.new('Packaging', freight_options[:packaging])
250
+ line_items << build_package_weight_node(pkg, imperial)
251
+ line_items << build_package_dimensions_node(pkg, imperial)
252
+ end
253
+ end
254
+ end
255
+ end
256
+
257
+ def has_freight?(options)
258
+ options[:freight] && options[:freight].present?
259
+ end
260
+
261
+ def build_package_weight_node(pkg, imperial)
262
+ XmlNode.new('Weight') do |tw|
263
+ tw << XmlNode.new('Units', imperial ? 'LB' : 'KG')
264
+ tw << XmlNode.new('Value', [((imperial ? pkg.lbs : pkg.kgs).to_f*1000).round/1000.0, 0.1].max)
265
+ end
266
+ end
267
+
268
+ def build_package_dimensions_node(pkg, imperial)
269
+ XmlNode.new('Dimensions') do |dimensions|
270
+ [:length,:width,:height].each do |axis|
271
+ value = ((imperial ? pkg.inches(axis) : pkg.cm(axis)).to_f*1000).round/1000.0 # 3 decimals
272
+ dimensions << XmlNode.new(axis.to_s.capitalize, value.ceil)
273
+ end
274
+ dimensions << XmlNode.new('Units', imperial ? 'IN' : 'CM')
275
+ end
276
+ end
277
+
278
+ def build_rate_request_types_node(type = 'ACCOUNT')
279
+ XmlNode.new('RateRequestTypes', type)
280
+ end
217
281
 
218
282
  def build_tracking_request(tracking_number, options={})
219
283
  xml_request = XmlNode.new('TrackRequest', 'xmlns' => 'http://fedex.com/ws/track/v3') do |root_node|
@@ -262,6 +326,10 @@ module ActiveMerchant
262
326
  def build_location_node(name, location)
263
327
  location_node = XmlNode.new(name) do |xml_node|
264
328
  xml_node << XmlNode.new('Address') do |address_node|
329
+ address_node << XmlNode.new('StreetLines', location.address1) if location.address1
330
+ address_node << XmlNode.new('StreetLines', location.address2) if location.address2
331
+ address_node << XmlNode.new('City', location.city) if location.city
332
+ address_node << XmlNode.new('StateOrProvinceCode', location.state) if location.state
265
333
  address_node << XmlNode.new('PostalCode', location.postal_code)
266
334
  address_node << XmlNode.new("CountryCode", location.country_code(:alpha2))
267
335
 
@@ -346,7 +414,9 @@ module ActiveMerchant
346
414
  message = response_message(xml)
347
415
 
348
416
  if success
349
- tracking_number, origin, destination, status, status_code, status_description, delivery_signature = nil
417
+ tracking_number, shipper_address, origin, destination, status = nil
418
+ status_code, status_description, ship_time = nil
419
+ scheduled_delivery_time, actual_delivery_time, delivery_signature = nil
350
420
  shipment_events = []
351
421
 
352
422
  tracking_details = root_node.elements['TrackDetails']
@@ -370,7 +440,12 @@ module ActiveMerchant
370
440
  )
371
441
  end
372
442
 
373
- destination = extract_destination(tracking_details)
443
+ destination = extract_address(tracking_details, DELIVERY_ADDRESS_NODE_NAMES)
444
+ shipper_address = extract_address(tracking_details, SHIPPER_ADDRESS_NODE_NAMES)
445
+
446
+ ship_time = extract_timestamp(tracking_details, 'ShipTimestamp')
447
+ actual_delivery_time = extract_timestamp(tracking_details, 'ActualDeliveryTimestamp')
448
+ scheduled_delivery_time = extract_timestamp(tracking_details, 'EstimatedDeliveryTimestamp')
374
449
 
375
450
  tracking_details.elements.each('Events') do |event|
376
451
  address = event.elements['Address']
@@ -400,8 +475,12 @@ module ActiveMerchant
400
475
  :status => status,
401
476
  :status_code => status_code,
402
477
  :status_description => status_description,
478
+ :ship_time => ship_time,
479
+ :scheduled_delivery_date => scheduled_delivery_time,
480
+ :actual_delivery_date => actual_delivery_time,
403
481
  :delivery_signature => delivery_signature,
404
482
  :shipment_events => shipment_events,
483
+ :shipper_address => shipper_address.unknown? ? nil : shipper_address,
405
484
  :origin => origin,
406
485
  :destination => destination,
407
486
  :tracking_number => tracking_number
@@ -452,8 +531,12 @@ module ActiveMerchant
452
531
  results
453
532
  end
454
533
 
455
- def extract_destination(document)
456
- node = document.elements['DestinationAddress'] || document.elements['ActualDeliveryAddress']
534
+ def extract_address(document, possible_node_names)
535
+ node = nil
536
+ possible_node_names.each do |name|
537
+ node ||= document.elements[name]
538
+ break if node
539
+ end
457
540
 
458
541
  args = if node
459
542
  {
@@ -472,6 +555,12 @@ module ActiveMerchant
472
555
  Location.new(args)
473
556
  end
474
557
 
558
+ def extract_timestamp(document, node_name)
559
+ if timestamp_node = document.elements[node_name]
560
+ Time.parse(timestamp_node.to_s).utc
561
+ end
562
+ end
563
+
475
564
  def build_document(xml)
476
565
  REXML::Document.new(xml)
477
566
  rescue REXML::ParseException => e
@@ -325,7 +325,7 @@ module ActiveMerchant
325
325
  message = response_message(xml)
326
326
 
327
327
  if success
328
- tracking_number, origin, destination, status_code, status_description = nil
328
+ tracking_number, origin, destination, status_code, status_description, delivery_signature = nil
329
329
  delivered, exception = false
330
330
  exception_event = nil
331
331
  shipment_events = []
@@ -392,6 +392,7 @@ module ActiveMerchant
392
392
 
393
393
  # Has the shipment been delivered?
394
394
  if status == :delivered
395
+ delivery_signature = activities.first.get_text('ActivityLocation/SignedForByName').to_s
395
396
  if !destination
396
397
  destination = shipment_events[-1].location
397
398
  end
@@ -407,6 +408,7 @@ module ActiveMerchant
407
408
  :status => status,
408
409
  :status_code => status_code,
409
410
  :status_description => status_description,
411
+ :delivery_signature => delivery_signature,
410
412
  :scheduled_delivery_date => scheduled_delivery_date,
411
413
  :shipment_events => shipment_events,
412
414
  :delivered => delivered,
@@ -474,6 +474,7 @@ module ActiveMerchant
474
474
  end
475
475
 
476
476
  def parse_tracking_response(response, options)
477
+ actual_delivery_date, status = nil
477
478
  xml = REXML::Document.new(response)
478
479
  root_node = xml.elements['TrackResponse']
479
480
 
@@ -509,7 +510,13 @@ module ActiveMerchant
509
510
  shipment_events << ShipmentEvent.new(description, zoneless_time, location)
510
511
  end
511
512
  end
513
+
512
514
  shipment_events = shipment_events.sort_by(&:time)
515
+
516
+ if last_shipment = shipment_events.last
517
+ status = last_shipment.status
518
+ actual_delivery_date = last_shipment.time if last_shipment.delivered?
519
+ end
513
520
  end
514
521
 
515
522
  TrackingResponse.new(success, message, Hash.from_xml(response),
@@ -518,7 +525,9 @@ module ActiveMerchant
518
525
  :request => last_request,
519
526
  :shipment_events => shipment_events,
520
527
  :destination => destination,
521
- :tracking_number => tracking_number
528
+ :tracking_number => tracking_number,
529
+ :status => status,
530
+ :actual_delivery_date => actual_delivery_date
522
531
  )
523
532
  end
524
533
 
@@ -84,6 +84,7 @@ module ActiveMerchant #:nodoc:
84
84
  def residential?; @address_type == 'residential' end
85
85
  def commercial?; @address_type == 'commercial' end
86
86
  def po_box?; @address_type == 'po_box' end
87
+ def unknown?; country_code == 'ZZ' end
87
88
 
88
89
  def address_type=(value)
89
90
  return unless value.present?
@@ -7,8 +7,15 @@ module ActiveMerchant #:nodoc:
7
7
  def initialize(name, time, location, message=nil)
8
8
  @name, @time, @location, @message = name, time, location, message
9
9
  end
10
-
10
+
11
+ def delivered?
12
+ status == :delivered
13
+ end
14
+
15
+ def status
16
+ @status ||= name.downcase.gsub("\s", "_").to_sym
17
+ end
11
18
  end
12
19
 
13
20
  end
14
- end
21
+ end
@@ -7,11 +7,13 @@ module ActiveMerchant #:nodoc:
7
7
  attr_reader :status # symbol
8
8
  attr_reader :status_code # string
9
9
  attr_reader :status_description #string
10
+ attr_reader :ship_time # time
10
11
  attr_reader :scheduled_delivery_date # time
12
+ attr_reader :actual_delivery_date # time
11
13
  attr_reader :delivery_signature #string
12
14
  attr_reader :tracking_number # string
13
15
  attr_reader :shipment_events # array of ShipmentEvents in chronological order
14
- attr_reader :origin, :destination
16
+ attr_reader :shipper_address, :origin, :destination # Location objects
15
17
 
16
18
  def initialize(success, message, params = {}, options = {})
17
19
  @carrier = options[:carrier].parameterize.to_sym
@@ -19,11 +21,15 @@ module ActiveMerchant #:nodoc:
19
21
  @status = options[:status]
20
22
  @status_code = options[:status_code]
21
23
  @status_description = options[:status_description]
24
+ @ship_time = options[:ship_time]
22
25
  @scheduled_delivery_date = options[:scheduled_delivery_date]
26
+ @actual_delivery_date = options[:actual_delivery_date]
23
27
  @delivery_signature = options[:delivery_signature]
24
28
  @tracking_number = options[:tracking_number]
25
29
  @shipment_events = Array(options[:shipment_events])
26
- @origin, @destination = options[:origin], options[:destination]
30
+ @shipper_address = options[:shipper_address]
31
+ @origin = options[:origin]
32
+ @destination = options[:destination]
27
33
  super
28
34
  end
29
35
 
@@ -42,7 +48,8 @@ module ActiveMerchant #:nodoc:
42
48
  alias_method(:exception_event, :latest_event)
43
49
  alias_method(:delivered?, :is_delivered?)
44
50
  alias_method(:exception?, :has_exception?)
45
-
51
+ alias_method(:scheduled_delivery_time, :scheduled_delivery_date)
52
+ alias_method(:actual_delivery_time, :actual_delivery_date)
46
53
  end
47
54
 
48
55
  end
@@ -1,3 +1,3 @@
1
1
  module ActiveShipping
2
- VERSION = "0.11.0"
2
+ VERSION = "0.11.1"
3
3
  end
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_shipping
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0
5
- prerelease:
4
+ version: 0.11.1
6
5
  platform: ruby
7
6
  authors:
8
7
  - James MacAulay
@@ -12,92 +11,81 @@ authors:
12
11
  autorequire:
13
12
  bindir: bin
14
13
  cert_chain: []
15
- date: 2013-09-15 00:00:00.000000000 Z
14
+ date: 2013-12-31 00:00:00.000000000 Z
16
15
  dependencies:
17
16
  - !ruby/object:Gem::Dependency
18
17
  name: activesupport
19
18
  requirement: !ruby/object:Gem::Requirement
20
- none: false
21
19
  requirements:
22
- - - ! '>='
20
+ - - '>='
23
21
  - !ruby/object:Gem::Version
24
22
  version: 2.3.5
25
23
  type: :runtime
26
24
  prerelease: false
27
25
  version_requirements: !ruby/object:Gem::Requirement
28
- none: false
29
26
  requirements:
30
- - - ! '>='
27
+ - - '>='
31
28
  - !ruby/object:Gem::Version
32
29
  version: 2.3.5
33
30
  - !ruby/object:Gem::Dependency
34
31
  name: i18n
35
32
  requirement: !ruby/object:Gem::Requirement
36
- none: false
37
33
  requirements:
38
- - - ! '>='
34
+ - - '>='
39
35
  - !ruby/object:Gem::Version
40
36
  version: '0'
41
37
  type: :runtime
42
38
  prerelease: false
43
39
  version_requirements: !ruby/object:Gem::Requirement
44
- none: false
45
40
  requirements:
46
- - - ! '>='
41
+ - - '>='
47
42
  - !ruby/object:Gem::Version
48
43
  version: '0'
49
44
  - !ruby/object:Gem::Dependency
50
45
  name: active_utils
51
46
  requirement: !ruby/object:Gem::Requirement
52
- none: false
53
47
  requirements:
54
- - - ! '>='
48
+ - - '>='
55
49
  - !ruby/object:Gem::Version
56
50
  version: 1.0.1
57
51
  type: :runtime
58
52
  prerelease: false
59
53
  version_requirements: !ruby/object:Gem::Requirement
60
- none: false
61
54
  requirements:
62
- - - ! '>='
55
+ - - '>='
63
56
  - !ruby/object:Gem::Version
64
57
  version: 1.0.1
65
58
  - !ruby/object:Gem::Dependency
66
59
  name: builder
67
60
  requirement: !ruby/object:Gem::Requirement
68
- none: false
69
61
  requirements:
70
- - - ! '>='
62
+ - - '>='
71
63
  - !ruby/object:Gem::Version
72
64
  version: '0'
73
65
  type: :runtime
74
66
  prerelease: false
75
67
  version_requirements: !ruby/object:Gem::Requirement
76
- none: false
77
68
  requirements:
78
- - - ! '>='
69
+ - - '>='
79
70
  - !ruby/object:Gem::Version
80
71
  version: '0'
81
72
  - !ruby/object:Gem::Dependency
82
73
  name: json
83
74
  requirement: !ruby/object:Gem::Requirement
84
- none: false
85
75
  requirements:
86
- - - ! '>='
76
+ - - '>='
87
77
  - !ruby/object:Gem::Version
88
78
  version: 1.5.1
89
79
  type: :runtime
90
80
  prerelease: false
91
81
  version_requirements: !ruby/object:Gem::Requirement
92
- none: false
93
82
  requirements:
94
- - - ! '>='
83
+ - - '>='
95
84
  - !ruby/object:Gem::Version
96
85
  version: 1.5.1
97
86
  - !ruby/object:Gem::Dependency
98
87
  name: minitest
99
88
  requirement: !ruby/object:Gem::Requirement
100
- none: false
101
89
  requirements:
102
90
  - - ~>
103
91
  - !ruby/object:Gem::Version
@@ -105,7 +93,6 @@ dependencies:
105
93
  type: :development
106
94
  prerelease: false
107
95
  version_requirements: !ruby/object:Gem::Requirement
108
- none: false
109
96
  requirements:
110
97
  - - ~>
111
98
  - !ruby/object:Gem::Version
@@ -113,23 +100,20 @@ dependencies:
113
100
  - !ruby/object:Gem::Dependency
114
101
  name: rake
115
102
  requirement: !ruby/object:Gem::Requirement
116
- none: false
117
103
  requirements:
118
- - - ! '>='
104
+ - - '>='
119
105
  - !ruby/object:Gem::Version
120
106
  version: '0'
121
107
  type: :development
122
108
  prerelease: false
123
109
  version_requirements: !ruby/object:Gem::Requirement
124
- none: false
125
110
  requirements:
126
- - - ! '>='
111
+ - - '>='
127
112
  - !ruby/object:Gem::Version
128
113
  version: '0'
129
114
  - !ruby/object:Gem::Dependency
130
115
  name: mocha
131
116
  requirement: !ruby/object:Gem::Requirement
132
- none: false
133
117
  requirements:
134
118
  - - ~>
135
119
  - !ruby/object:Gem::Version
@@ -137,7 +121,6 @@ dependencies:
137
121
  type: :development
138
122
  prerelease: false
139
123
  version_requirements: !ruby/object:Gem::Requirement
140
- none: false
141
124
  requirements:
142
125
  - - ~>
143
126
  - !ruby/object:Gem::Version
@@ -145,33 +128,29 @@ dependencies:
145
128
  - !ruby/object:Gem::Dependency
146
129
  name: timecop
147
130
  requirement: !ruby/object:Gem::Requirement
148
- none: false
149
131
  requirements:
150
- - - ! '>='
132
+ - - '>='
151
133
  - !ruby/object:Gem::Version
152
134
  version: '0'
153
135
  type: :development
154
136
  prerelease: false
155
137
  version_requirements: !ruby/object:Gem::Requirement
156
- none: false
157
138
  requirements:
158
- - - ! '>='
139
+ - - '>='
159
140
  - !ruby/object:Gem::Version
160
141
  version: '0'
161
142
  - !ruby/object:Gem::Dependency
162
143
  name: nokogiri
163
144
  requirement: !ruby/object:Gem::Requirement
164
- none: false
165
145
  requirements:
166
- - - ! '>='
146
+ - - '>='
167
147
  - !ruby/object:Gem::Version
168
148
  version: '0'
169
149
  type: :development
170
150
  prerelease: false
171
151
  version_requirements: !ruby/object:Gem::Requirement
172
- none: false
173
152
  requirements:
174
- - - ! '>='
153
+ - - '>='
175
154
  - !ruby/object:Gem::Version
176
155
  version: '0'
177
156
  description: Get rates and tracking info from various shipping carriers.
@@ -183,6 +162,7 @@ extra_rdoc_files: []
183
162
  files:
184
163
  - lib/active_shipping/shipping/base.rb
185
164
  - lib/active_shipping/shipping/carrier.rb
165
+ - lib/active_shipping/shipping/carriers/benchmark_carrier.rb
186
166
  - lib/active_shipping/shipping/carriers/bogus_carrier.rb
187
167
  - lib/active_shipping/shipping/carriers/canada_post.rb
188
168
  - lib/active_shipping/shipping/carriers/canada_post_pws.rb
@@ -232,29 +212,25 @@ files:
232
212
  - CHANGELOG
233
213
  homepage: http://github.com/shopify/active_shipping
234
214
  licenses: []
215
+ metadata: {}
235
216
  post_install_message:
236
217
  rdoc_options: []
237
218
  require_paths:
238
219
  - lib
239
220
  required_ruby_version: !ruby/object:Gem::Requirement
240
- none: false
241
221
  requirements:
242
- - - ! '>='
222
+ - - '>='
243
223
  - !ruby/object:Gem::Version
244
224
  version: '0'
245
- segments:
246
- - 0
247
- hash: -2134793660123218894
248
225
  required_rubygems_version: !ruby/object:Gem::Requirement
249
- none: false
250
226
  requirements:
251
- - - ! '>='
227
+ - - '>='
252
228
  - !ruby/object:Gem::Version
253
229
  version: 1.3.6
254
230
  requirements: []
255
231
  rubyforge_project: active_shipping
256
- rubygems_version: 1.8.23
232
+ rubygems_version: 2.0.3
257
233
  signing_key:
258
- specification_version: 3
234
+ specification_version: 4
259
235
  summary: Shipping API extension for Active Merchant
260
236
  test_files: []