trackerific 0.7.1 → 0.7.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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +6 -0
  3. data/Gemfile.lock +43 -1
  4. data/README.rdoc +58 -60
  5. data/lib/trackerific.rb +17 -20
  6. data/lib/trackerific/builders/base/soap.rb +21 -0
  7. data/lib/trackerific/builders/base/xml.rb +38 -0
  8. data/lib/trackerific/builders/fedex.rb +46 -0
  9. data/lib/trackerific/builders/ups.rb +32 -0
  10. data/lib/trackerific/builders/usps.rb +19 -0
  11. data/lib/trackerific/environment.rb +11 -0
  12. data/lib/trackerific/error.rb +3 -1
  13. data/lib/trackerific/parsers/base.rb +35 -0
  14. data/lib/trackerific/parsers/fedex.rb +59 -0
  15. data/lib/trackerific/parsers/ups.rb +66 -0
  16. data/lib/trackerific/parsers/usps.rb +51 -0
  17. data/lib/trackerific/services/base.rb +23 -10
  18. data/lib/trackerific/services/concerns/soap.rb +45 -0
  19. data/lib/trackerific/services/concerns/xml.rb +44 -0
  20. data/lib/trackerific/services/fedex.rb +9 -79
  21. data/lib/trackerific/services/mock_service.rb +4 -12
  22. data/lib/trackerific/services/ups.rb +11 -95
  23. data/lib/trackerific/services/usps.rb +21 -181
  24. data/lib/trackerific/soap/wsdl.rb +17 -0
  25. data/lib/trackerific/version.rb +1 -1
  26. data/spec/fixtures/fedex/error.xml +1 -10
  27. data/spec/fixtures/fedex/success.xml +1 -74
  28. data/spec/fixtures/ups/malformed.xml +10 -0
  29. data/spec/fixtures/ups/request.xml +1 -0
  30. data/spec/fixtures/usps/malformed.xml +2 -0
  31. data/spec/fixtures/usps/request.xml +1 -0
  32. data/spec/lib/trackerific/builders/base/soap_spec.rb +29 -0
  33. data/spec/lib/trackerific/builders/base/xml_spec.rb +35 -0
  34. data/spec/lib/trackerific/builders/fedex_spec.rb +70 -0
  35. data/spec/lib/trackerific/builders/ups_spec.rb +11 -0
  36. data/spec/lib/trackerific/builders/usps_spec.rb +11 -0
  37. data/spec/lib/trackerific/environment_spec.rb +45 -0
  38. data/spec/lib/trackerific/parsers/base_spec.rb +62 -0
  39. data/spec/lib/trackerific/parsers/ups_spec.rb +71 -0
  40. data/spec/lib/trackerific/parsers/usps_spec.rb +77 -0
  41. data/spec/lib/trackerific/services/base_spec.rb +56 -0
  42. data/spec/lib/trackerific/services/concerns/soap_spec.rb +71 -0
  43. data/spec/lib/trackerific/services/concerns/xml_spec.rb +65 -0
  44. data/spec/lib/trackerific/services/fedex_spec.rb +43 -45
  45. data/spec/lib/trackerific/services/ups_spec.rb +23 -2
  46. data/spec/lib/trackerific/services/usps_spec.rb +44 -34
  47. data/spec/lib/trackerific/services_spec.rb +7 -0
  48. data/spec/lib/trackerific/soap/wsdl_spec.rb +29 -0
  49. data/spec/lib/trackerific/version_spec.rb +1 -1
  50. data/spec/lib/trackerific_spec.rb +2 -11
  51. data/spec/spec_helper.rb +17 -1
  52. data/spec/support/reload.rb +6 -0
  53. data/spec/support/trackerific.rb +7 -0
  54. data/trackerific.gemspec +2 -0
  55. data/vendor/wsdl/fedex/TrackService_v8.wsdl +2284 -0
  56. metadata +81 -7
  57. data/lib/trackerific/configuration.rb +0 -7
  58. data/spec/fixtures/usps/city_state_lookup.xml +0 -8
  59. data/spec/lib/trackerific/configuration_spec.rb +0 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c6ebc05677cc3553211222baad840e0a77f75e0d
4
- data.tar.gz: e2f65f8425c2e70a7a6b56c71946b1174337dc5d
3
+ metadata.gz: 1310f1dbf143518a58178390a664b23b697cadba
4
+ data.tar.gz: 709ab9cdaa8df43975eff61b797b98586fab4e34
5
5
  SHA512:
6
- metadata.gz: a789ef97d405deac2bfdfa850cd7a39719a7f6ac64f1e16297098f1e48ed18385bedda51154acdc7a44e3ac6ca4093a3acf543d8d426a062861142d14748cae2
7
- data.tar.gz: 532c75fddf2c6b8e4c34abe4822edf52ac41b1e70952cc0cfda368d7ad5869ff32e416a83a2a2ae8a6b31abb9abf09cb342012c6ea3ef73c3e73c6f3c8837485
6
+ metadata.gz: b398a2bfaab2602d8cb0624d48f7936750abb13bdfb36828a27cd4ec1f4b0a5a0763996de30edf2aa38a4270fecb31e5158a77a2d242542a3c3be6d1094b0158
7
+ data.tar.gz: dfe45ddfe2c76098a2e9b6c917f6b825fb91d993f92236f9b5b28595f539b48b13d758bae1dbe1fd6ede6928ea202b95638d010ac0cf6e5b06ef81e930781ded
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.3"
4
+ - "2.0.0"
5
+ - jruby-19mode # JRuby in 1.9 mode
6
+ - rbx-19mode
data/Gemfile.lock CHANGED
@@ -1,10 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- trackerific (0.7.1)
4
+ trackerific (0.7.2)
5
5
  activesupport
6
6
  builder (>= 3.1.4)
7
7
  httparty (>= 0.12.0)
8
+ savon (~> 2.3.0)
8
9
 
9
10
  GEM
10
11
  remote: https://rubygems.org/
@@ -15,19 +16,39 @@ GEM
15
16
  multi_json (~> 1.3)
16
17
  thread_safe (~> 0.1)
17
18
  tzinfo (~> 0.3.37)
19
+ akami (1.2.0)
20
+ gyoku (>= 0.4.0)
21
+ nokogiri (>= 1.4.0)
18
22
  atomic (1.1.14)
19
23
  builder (3.2.2)
24
+ coveralls (0.7.0)
25
+ multi_json (~> 1.3)
26
+ rest-client
27
+ simplecov (>= 0.7)
28
+ term-ansicolor
29
+ thor
20
30
  diff-lcs (1.1.3)
21
31
  fakeweb (1.3.0)
32
+ gyoku (1.1.0)
33
+ builder (>= 2.1.2)
22
34
  httparty (0.12.0)
23
35
  json (~> 1.8)
24
36
  multi_xml (>= 0.5.2)
37
+ httpi (2.1.0)
38
+ rack
39
+ rubyntlm (~> 0.3.2)
25
40
  i18n (0.6.5)
26
41
  json (1.8.0)
42
+ mime-types (1.25)
27
43
  minitest (4.7.5)
28
44
  multi_json (1.8.2)
29
45
  multi_xml (0.5.5)
46
+ nokogiri (1.5.10)
47
+ nori (2.3.0)
48
+ rack (1.5.2)
30
49
  rake (10.1.0)
50
+ rest-client (1.6.7)
51
+ mime-types (>= 1.16)
31
52
  rspec (2.6.0)
32
53
  rspec-core (~> 2.6.0)
33
54
  rspec-expectations (~> 2.6.0)
@@ -36,15 +57,36 @@ GEM
36
57
  rspec-expectations (2.6.0)
37
58
  diff-lcs (~> 1.1.2)
38
59
  rspec-mocks (2.6.0)
60
+ rubyntlm (0.3.4)
61
+ savon (2.3.0)
62
+ akami (~> 1.2.0)
63
+ builder (>= 2.1.2)
64
+ gyoku (~> 1.1.0)
65
+ httpi (~> 2.1.0)
66
+ nokogiri (>= 1.4.0, < 1.6)
67
+ nori (~> 2.3.0)
68
+ wasabi (~> 3.2.0)
69
+ simplecov (0.7.1)
70
+ multi_json (~> 1.0)
71
+ simplecov-html (~> 0.7.1)
72
+ simplecov-html (0.7.1)
73
+ term-ansicolor (1.2.2)
74
+ tins (~> 0.8)
75
+ thor (0.18.1)
39
76
  thread_safe (0.1.3)
40
77
  atomic
78
+ tins (0.12.0)
41
79
  tzinfo (0.3.38)
80
+ wasabi (3.2.0)
81
+ httpi (~> 2.0)
82
+ nokogiri (>= 1.4.0, < 1.6)
42
83
 
43
84
  PLATFORMS
44
85
  ruby
45
86
 
46
87
  DEPENDENCIES
47
88
  bundler (>= 1.3.5)
89
+ coveralls (~> 0.7.0)
48
90
  fakeweb (~> 1.3.0)
49
91
  rake
50
92
  rspec (~> 2.6.0)
data/README.rdoc CHANGED
@@ -1,3 +1,25 @@
1
+ = Trackerific {<img src="https://badge.fury.io/rb/trackerific.png" alt="Gem Version" />}[http://badge.fury.io/rb/trackerific] {<img src="https://travis-ci.org/travishaynes/trackerific.png" />}[https://travis-ci.org/travishaynes/trackerific] {<img src="https://coveralls.io/repos/travishaynes/trackerific/badge.png" alt="Coverage Status" />}[https://coveralls.io/r/travishaynes/trackerific]
2
+
3
+ Package tracking in a gem. Currently supported carriers are:
4
+
5
+ * FedEx
6
+ * UPS
7
+ * USPS
8
+
9
+ == Prerequisites
10
+
11
+ You will need to sign up to each carrier you wish to utilize. They each have
12
+ their own requirements and license agreements, so it's up to you to make sure
13
+ you follow their terms of agreement. For example, at the time this was written
14
+ UPS requires that you include their logo on your website when you use their
15
+ API.
16
+
17
+ You'll also need the proper credentials from each carrier, which requires
18
+ signing up through their individual websites, and is not always free, depending
19
+ on which portion of their API you plan on using. Trackerific focuses primarily
20
+ on the tracking APIs, so that's all you'll need to use this gem, unless you
21
+ plan on implementing additional features.
22
+
1
23
  == Installation
2
24
 
3
25
  To use this gem, add this line to your Gemfile
@@ -7,24 +29,15 @@ and then run
7
29
 
8
30
  === Configuration
9
31
 
10
- You will need to configure your credentials for each service:
32
+ You will need to configure the credentials for each service you're utilizing.
33
+ Services without credentials will not be accessed by the gem.
11
34
 
12
35
  Trackerific.configure do |config|
13
- config.fedex :account => 'account',
14
- :meter => '123456789'
15
-
16
- config.ups :key => 'key',
17
- :user_id => 'userid',
18
- :password => 'secret'
19
-
20
- config.usps :user_id => 'userid',
21
- :use_city_state_lookup => true
36
+ config.fedex = { account: 'account', meter: '123456789' }
37
+ config.ups = { key: 'key', user_id: 'userid', password: 'secret' }
38
+ config.usps = { user_id: 'userid' }
22
39
  end
23
40
 
24
- For USPS packages, the option :use_city_state_lookup defaults to false, and will
25
- only work if you have access to USPS's CityStateLookup API. If you can enable
26
- it, this feature will provide the location for USPS package events.
27
-
28
41
  === Tracking with Automatic Service Discovery
29
42
 
30
43
  Once you configured the services, tracking a package is as easy as
@@ -36,64 +49,47 @@ Once you configured the services, tracking a package is as easy as
36
49
  If you do not know the tracking service provider of a package id you can use
37
50
  Trackerific::Services.find_by_tracking_id:
38
51
 
39
- Trackerific::Services.find_by_tracking_id("183689015000001") # => Trackerific::Services::FedEx
40
- Trackerific::Services.find_by_tracking_id("1Z12345E0291980793") # => Trackerific::Services::UPS
41
- Trackerific::Services.find_by_tracking_id("EJ958083578US") # => Trackerific::Services::USPS
42
- Trackerific::Services.find_by_tracking_id("unknown package id") # => nil
52
+ Trackerific::Services.find_by_tracking_id("123456789012")
53
+ Trackerific::Services.find_by_tracking_id("1Z12345E0291980793")
54
+ Trackerific::Services.find_by_tracking_id("EJ958083578US")
55
+
56
+ Each of the above examples will return an Array of
57
+ Trackerific::Service::Base subclasses that are capable of tracking the given
58
+ package ID.
43
59
 
44
60
  === Tracking a Package with a Specific Service
45
61
 
46
62
  Use this method if you need to specify exactly which service to track a package.
47
63
 
48
- # Track a FedEx package:
49
- details = Trackerific::Services::FedEx.track('183689015000001')
50
-
51
- # Track a USPS package:
52
- details = Trackerific::Services::USPS.track('EJ958083578US')
64
+ details = Trackerific::Services::FedEx.track('123456789012')
53
65
 
54
- # Track a UPS package:
55
- details = Trackerific::Services::UPS.track('1Z12345E0291980793')
66
+ Using #track will automatically read the credentials from Trackerific.config.
67
+ If you need to assign them manually, use #new:
56
68
 
57
- Using #track will automatically read the credentials from
58
- `Trackerific.configuration`. If you need to assign them manually, use #new:
59
-
60
- fedex = Trackerific::Services::FedEx.new account: "account", meter: "123456789"
69
+ fedex = Trackerific::Services::FedEx.new(
70
+ :account => "account",
71
+ :meter => "123456789"
72
+ )
61
73
  details = fedex.track('183689015000001')
62
74
 
63
75
  === Tracking Details
64
76
 
65
77
  The tracking information is returned in a Trackerific::Details instance.
66
78
 
67
- details.summary # => a summary of the tracking events
68
- details.events # => an Array of Trackerific::Events
69
-
70
- You can easily print out the tracking events just by doing:
71
-
72
- puts details.events # for all the events
73
- puts details.events.first # for just one event
74
-
75
- Or, if you need specific information about an event:
76
-
77
- details.events.last.date # => the date the package was shipped
78
- details.events.first.date # => the last date the package was updated
79
- details.events.first.description # => a description of an event
80
- details.events.first.location # => the location of the package during that event
81
-
82
- location will not work for USPS packages, because USPS does not provide that
83
- information seperately from the description. So for USPS packages, the location
84
- will always be at the end of the description.
79
+ details.summary - Summary of the tracking events
80
+ details.events - Array of Trackerific::Events
85
81
 
86
- Note that events.last will return the first event the tracking provider
87
- supplied. This is because the events are listed in LIFO order, so the most
88
- recent events will always be at the top of the list.
82
+ === Tracking Events
89
83
 
90
- === City / State Lookup Via USPS
84
+ Tracking::Details has an events Array with the following properties:
91
85
 
92
- If you have access to the USPS CityStateLookup API, you can use Trackerific to
93
- look up the city and state of a zipcode.
86
+ event.date - The date the package was shipped.
87
+ event.date - The date/time of the event.
88
+ event.description - Description of an event.
89
+ event.location - The location of the package during that event.
94
90
 
95
- usps = Trackerific::Services::USPS.new :user_id => 'userid'
96
- usps.city_state_lookup "90210" # => { :city => 'BEVERLY HILLS', :state => 'CA', :zip => '90210' }
91
+ Note that events are in last-in-first-out order, so the last event will always
92
+ be the first event the carrier supplied.
97
93
 
98
94
  === Exception handling
99
95
 
@@ -115,13 +111,15 @@ Trackerific provides a mocked service you can use in your unit tests of your
115
111
  application. You must require the service manually.
116
112
 
117
113
  require 'trackerific/services/mock_service'
118
- details = track_package("XXXXXXXXXX") # => returns a populated Trackerific::Details
119
- details = track_package("XXXxxxxxxx") # => throws a Trackerific::Error exception
114
+ # Get a populated Trackerific::Details
115
+ details = Trackerific.track("XXXXXXXXXX")
116
+ # Throw a Trackerific::Error exception
117
+ details = Trackerific.track("XXXxxxxxxx")
120
118
 
121
119
  == Contributing
122
120
 
123
121
  1. Fork it
124
- 2. Create your feature branch (`git checkout -b my-new-feature`)
125
- 3. Commit your changes (`git commit -am 'Add some feature'`)
126
- 4. Push to the branch (`git push origin my-new-feature`)
122
+ 2. Create your feature branch (git checkout -b my-new-feature)
123
+ 3. Commit your changes (git commit -am 'Add some feature')
124
+ 4. Push to the branch (git push origin my-new-feature)
127
125
  5. Create new Pull Request
data/lib/trackerific.rb CHANGED
@@ -1,8 +1,21 @@
1
+ require 'active_support'
2
+ require 'active_support/core_ext/object/to_query'
3
+ require 'securerandom'
4
+ require 'date'
5
+ require 'savon'
6
+ require 'httparty'
7
+ require 'builder'
1
8
  require 'trackerific/version'
2
- require 'trackerific/configuration'
9
+ require 'trackerific/environment'
3
10
  require 'trackerific/error'
4
11
  require 'trackerific/details'
5
12
  require 'trackerific/event'
13
+ require 'trackerific/soap/wsdl'
14
+ require 'trackerific/builders/base/soap'
15
+ require 'trackerific/builders/base/xml'
16
+ require 'trackerific/parsers/base'
17
+ require 'trackerific/services/concerns/soap'
18
+ require 'trackerific/services/concerns/xml'
6
19
  require 'trackerific/services'
7
20
  require 'trackerific/services/base'
8
21
 
@@ -12,32 +25,16 @@ require 'trackerific/services/ups'
12
25
  require 'trackerific/services/usps'
13
26
 
14
27
  module Trackerific
15
- class << self
16
- # Used to access the Trackerific service credentials
17
- # @api public
18
- def configuration
19
- Trackerific::Configuration.config
20
- end
21
-
22
- # Use to configure Trackerific service credentials
23
- # @example Configure FedEx credentials
24
- # Trackerific.configure do |config|
25
- # config.fedex account: 'account', meter: '123456789'
26
- # end
27
- # @api public
28
- def configure(&block)
29
- Trackerific::Configuration.configure {|config| yield(config) }
30
- end
28
+ include ActiveSupport::Configurable
31
29
 
30
+ class << self
32
31
  # Looks up which service(s) can track the given ID and tracks it.
33
32
  # @param [String] id The package identifier
34
33
  # @return [Array, Trackerific::Details] The tracking results
35
34
  # @raise [Trackerific::Error] Raised when the server returns an error
36
35
  # @api public
37
36
  def track(id)
38
- Trackerific::Services.find_by_package_id(id).map do |service|
39
- service.new.track(id)
40
- end
37
+ Trackerific::Services.find_by_package_id(id).map {|s| s.track(id) }
41
38
  end
42
39
  end
43
40
  end
@@ -0,0 +1,21 @@
1
+ module Trackerific
2
+ module Builders
3
+ module Base
4
+ class SOAP < Struct
5
+ attr_reader :hash
6
+
7
+ def initialize(*args)
8
+ super(*args)
9
+ @hash = build
10
+ end
11
+
12
+ protected
13
+
14
+ def build
15
+ raise NotImplementedError,
16
+ "Implement this method in your builder subclass", caller
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,38 @@
1
+ module Trackerific
2
+ module Builders
3
+ module Base
4
+ class XML < Struct
5
+ @xml_version = "1.0"
6
+
7
+ class << self
8
+ attr_accessor :xml_version
9
+ end
10
+
11
+ attr_reader :xml
12
+
13
+ def initialize(*args)
14
+ super(*args)
15
+ @xml = ""
16
+ build
17
+ end
18
+
19
+ protected
20
+
21
+ def build
22
+ raise NotImplementedError,
23
+ "Implement this method in your builder subclass", caller
24
+ end
25
+
26
+ private
27
+
28
+ def builder
29
+ @builder ||= begin
30
+ builder = Builder::XmlMarkup.new(target: @xml)
31
+ builder.instruct! :xml, version: self.class.xml_version
32
+ builder
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,46 @@
1
+ module Trackerific
2
+ module Builders
3
+ class FedEx < Base::SOAP.new(:key, :password, :account_number, :meter_number, :package_id)
4
+ protected
5
+
6
+ def build
7
+ root_elements.inject({}) {|r, k| r[k] = send(k); r }
8
+ end
9
+
10
+ private
11
+
12
+ def root_elements
13
+ [ :web_authentication_detail, :client_detail, :transaction_detail,
14
+ :version, :selection_details, :processing_options ]
15
+ end
16
+
17
+ def web_authentication_detail
18
+ { user_credential: { key: key, password: password } }
19
+ end
20
+
21
+ def client_detail
22
+ { account_number: account_number, meter_number: meter_number }
23
+ end
24
+
25
+ def transaction_detail
26
+ { customer_transaction_id: "Trackerific" }
27
+ end
28
+
29
+ def version
30
+ { service_id: 'trck', major: '8', intermediate: '0', minor: '0' }
31
+ end
32
+
33
+ def selection_details
34
+ { carrier_code: 'FDXE', package_identifier: package_identifier }
35
+ end
36
+
37
+ def package_identifier
38
+ { type: 'TRACKING_NUMBER_OR_DOORTAG', value: package_id }
39
+ end
40
+
41
+ def processing_options
42
+ 'INCLUDE_DETAILED_SCANS'
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,32 @@
1
+ module Trackerific
2
+ module Builders
3
+ class UPS < Base::XML.new(:key, :user_id, :password, :package_id)
4
+ protected
5
+
6
+ def build
7
+ add_access_request
8
+ add_track_request
9
+ end
10
+
11
+ private
12
+
13
+ def add_access_request
14
+ builder.AccessRequest do |ar|
15
+ ar.AccessLicenseNumber key
16
+ ar.UserId user_id
17
+ ar.Password password
18
+ end
19
+ end
20
+
21
+ def add_track_request
22
+ builder.TrackRequest do |tr|
23
+ tr.Request do |r|
24
+ r.RequestAction 'Track'
25
+ r.RequestOption 'activity'
26
+ end
27
+ tr.TrackingNumber package_id
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end