trackerific 0.3.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. data/Gemfile +1 -0
  2. data/Gemfile.lock +40 -38
  3. data/README.rdoc +4 -9
  4. data/VERSION +1 -1
  5. data/doc/Trackerific.html +34 -22
  6. data/doc/Trackerific/Base.html +237 -20
  7. data/doc/Trackerific/Details.html +6 -6
  8. data/doc/Trackerific/Error.html +2 -2
  9. data/doc/Trackerific/Event.html +7 -7
  10. data/doc/Trackerific/FedEx.html +190 -3
  11. data/doc/Trackerific/UPS.html +190 -3
  12. data/doc/Trackerific/USPS.html +190 -3
  13. data/doc/_index.html +1 -1
  14. data/doc/file.README.html +6 -24
  15. data/doc/index.html +6 -24
  16. data/doc/method_list.html +68 -4
  17. data/doc/top-level-namespace.html +1 -1
  18. data/lib/trackerific.rb +37 -74
  19. data/lib/trackerific/base.rb +70 -0
  20. data/lib/{trackerific_details.rb → trackerific/details.rb} +0 -0
  21. data/lib/trackerific/error.rb +4 -0
  22. data/lib/{trackerific_event.rb → trackerific/event.rb} +0 -0
  23. data/lib/{fedex.rb → trackerific/services/fedex.rb} +9 -2
  24. data/lib/{ups.rb → trackerific/services/ups.rb} +10 -4
  25. data/lib/{usps.rb → trackerific/services/usps.rb} +10 -3
  26. data/spec/lib/trackerific/base_spec.rb +34 -0
  27. data/spec/lib/{trackerific_details_spec.rb → trackerific/details_spec.rb} +0 -0
  28. data/spec/lib/trackerific/error_spec.rb +5 -0
  29. data/spec/lib/{trackerific_event_spec.rb → trackerific/event_spec.rb} +0 -0
  30. data/spec/lib/{fedex_spec.rb → trackerific/services/fedex_spec.rb} +19 -14
  31. data/spec/lib/{ups_spec.rb → trackerific/services/ups_spec.rb} +20 -14
  32. data/spec/lib/{usps_spec.rb → trackerific/services/usps_spec.rb} +18 -14
  33. data/spec/lib/trackerific_spec.rb +7 -30
  34. data/spec/spec_helper.rb +1 -0
  35. data/trackerific.gemspec +18 -22
  36. metadata +38 -27
@@ -94,7 +94,7 @@
94
94
  </div>
95
95
 
96
96
  <div id="footer">
97
- Generated on Mon Jun 13 16:20:06 2011 by
97
+ Generated on Mon Jun 13 21:28:36 2011 by
98
98
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
99
99
  0.7.1 (ruby-1.9.2).
100
100
  </div>
data/lib/trackerific.rb CHANGED
@@ -1,71 +1,15 @@
1
- # Trackerific is a UPS, FedEx and USPS tracking provider.
1
+ require 'rails'
2
+ require 'trackerific/base'
3
+ require 'trackerific/error'
4
+ require 'trackerific/details'
5
+ require 'trackerific/event'
6
+
7
+ # require all the Trackerific services
8
+ services_path = File.join(File.dirname(__FILE__), "trackerific", "services", "**", "*.rb")
9
+ Dir[File.expand_path(services_path)].each { |file| require file }
10
+
11
+ # Trackerific provides package tracking to Rails apps.
2
12
  module Trackerific
3
- require 'rails'
4
- require 'trackerific_details'
5
- require 'trackerific_event'
6
-
7
- # Raised if something other than tracking information is returned.
8
- class Error < StandardError; end
9
-
10
- # Base class for Trackerific package tracking services.
11
- class Base
12
- # Creates a new instance of Trackerific::Base with required options
13
- # @api private
14
- def initialize(options = {})
15
- required = required_options
16
- # make sure all the required options exist
17
- required.each do |k|
18
- raise ArgumentError.new("Missing required parameter: #{k}") unless options.has_key?(k)
19
- end
20
- # make sure no invalid options exist
21
- options.each do |k, v|
22
- raise ArgumentError.new("Invalid parameter: #{k}") unless required.include?(k)
23
- end
24
- @options = options
25
- end
26
-
27
- # Gets the tracking information for the package from the server
28
- # @param [String] package_id the package identifier
29
- # @return [Trackerific::Details] the tracking details
30
- # @example Override this method in your custom tracking provider to implement tracking
31
- # module Trackerific
32
- # class MyTrackingProvider < Base
33
- # def track_package
34
- # Trackerific::Details.new(
35
- # "summary of tracking events",
36
- # [Trackerific::Event.new(Time.now, "summary", "location")]
37
- # )
38
- # end
39
- # end
40
- # end
41
- # @api public
42
- def track_package(package_id)
43
- @package_id = package_id
44
- end
45
-
46
- protected
47
-
48
- # An array of options that are required to create a new instance of this class
49
- # @return [Array] the required options
50
- # @example Override this method in your custom tracking provider to enforce some options
51
- # module Trackerific
52
- # class MyTrackingProvider < Base
53
- # def required_options
54
- # [:all, :these, :are, :required]
55
- # end
56
- # end
57
- # end
58
- # @api private
59
- def required_options
60
- []
61
- end
62
-
63
- end
64
-
65
- require 'usps'
66
- require 'fedex'
67
- require 'ups'
68
-
69
13
  # Checks a string for a valid package tracking service
70
14
  # @param [String] package_id the package identifier
71
15
  # @return [Trackerific::Base] the Trackerific class that can track the given
@@ -75,14 +19,33 @@ module Trackerific
75
19
  # tracking_service "183689015000001" # => Trackerific::FedEx
76
20
  # @api public
77
21
  def tracking_service(package_id)
78
- case package_id
79
- when /^.Z/, /^[HK].{10}$/ then Trackerific::UPS
80
- when /^96.{20}$/ then Trackerific::FedEx
81
- else case package_id.length
82
- when 13, 20, 22, 30 then Trackerific::USPS
83
- when 12, 15, 19 then Trackerific::FedEx
84
- else nil
22
+ # loop through each constant in Trackerific
23
+ Trackerific.constants.each do |const|
24
+ # get the constant's class
25
+ cls = Trackerific.const_get(const)
26
+ # check if it descends from Trackerific::Base
27
+ if cls.superclass == Trackerific::Base
28
+ # loop through each package id matcher
29
+ cls.package_id_matchers.each do |matcher|
30
+ # return the class if it matches
31
+ return cls if package_id =~ matcher
32
+ end
85
33
  end
86
34
  end
35
+ # if we've made it this far, nothing matched
36
+ nil
87
37
  end
38
+
39
+ # TODO: Tracks a package by determining its service from the package id
40
+ # @param [String] package_id the package identifier
41
+ # @return [Trackerific::Details] the tracking results
42
+ # @raise [Trackerific::Error] raised when the server returns an error (invalid credentials, tracking package, etc.)
43
+ # @example Track a package
44
+ # include Trackerific
45
+ # details = track_package("183689015000001")
46
+ # @api public
47
+ # def track_package(package_id)
48
+ # service = tracking_service(package_id)
49
+ #
50
+ # end
88
51
  end
@@ -0,0 +1,70 @@
1
+ module Trackerific
2
+ # Base class for Trackerific package tracking services.
3
+ class Base
4
+ # Creates a new instance of Trackerific::Base with required options
5
+ # @api private
6
+ def initialize(options = {})
7
+ required = self.class.required_options
8
+ # make sure all the required options exist
9
+ required.each do |k|
10
+ raise ArgumentError.new("Missing required parameter: #{k}") unless options.has_key?(k)
11
+ end
12
+ # make sure no invalid options exist
13
+ options.each do |k, v|
14
+ raise ArgumentError.new("Invalid parameter: #{k}") unless required.include?(k)
15
+ end
16
+ @options = options
17
+ end
18
+
19
+ # Gets the tracking information for the package from the server
20
+ # @param [String] package_id the package identifier
21
+ # @return [Trackerific::Details] the tracking details
22
+ # @example Override this method in your custom tracking service to implement tracking
23
+ # module Trackerific
24
+ # class MyTrackingService < Base
25
+ # def track_package
26
+ # # your tracking code here
27
+ # Trackerific::Details.new(
28
+ # "summary of tracking events",
29
+ # [Trackerific::Event.new(Time.now, "summary", "location")]
30
+ # )
31
+ # end
32
+ # end
33
+ # end
34
+ # @api semipublic
35
+ def track_package(package_id)
36
+ @package_id = package_id
37
+ end
38
+
39
+ # An Array of Regexp that matches valid package identifiers for your service
40
+ # @example Override this method in your custom tracking service
41
+ # module Trackerific
42
+ # class MyTrackingService < Base
43
+ # def self.package_id_matchers
44
+ # [ /^.Z/, /^[HK].{10}$/ ] # matchers for UPS package identifiers
45
+ # end
46
+ # end
47
+ # end
48
+ # @return [Array, Regexp] an array of regular expressions
49
+ # @api semipublic
50
+ def self.package_id_matchers
51
+ nil
52
+ end
53
+
54
+ # An array of options that are required to create a new instance of this class
55
+ # @return [Array] the required options
56
+ # @example Override this method in your custom tracking service to enforce some options
57
+ # module Trackerific
58
+ # class MyTrackingService < Base
59
+ # def self.required_options
60
+ # [:all, :these, :are, :required]
61
+ # end
62
+ # end
63
+ # end
64
+ # @api semipublic
65
+ def self.required_options
66
+ []
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,4 @@
1
+ module Trackerific
2
+ # Raised if something other than tracking information is returned.
3
+ class Error < StandardError; end
4
+ end
File without changes
@@ -45,16 +45,23 @@ module Trackerific
45
45
  )
46
46
  end
47
47
 
48
- protected
48
+ # A regex that matches valid package identifiers for FedEx package ids
49
+ # @return [Regexp] the regular expression
50
+ # @api private
51
+ def self.package_id_matchers
52
+ [ /^[0-9]{15}$/ ]
53
+ end
49
54
 
50
55
  # Returns an Array of required options used when creating a new instance
51
56
  # @return [Array] required options for tracking a FedEx package are :account
52
57
  # and :meter
53
58
  # @api private
54
- def required_options
59
+ def self.required_options
55
60
  [:account, :meter]
56
61
  end
57
62
 
63
+ protected
64
+
58
65
  # Builds the XML request to send to FedEx
59
66
  # @return [String] a FDXTrack2Request XML
60
67
  # @api private
@@ -37,15 +37,21 @@ module Trackerific
37
37
  end
38
38
  end
39
39
 
40
- protected
41
-
40
+ # A regex that matches valid package identifiers for UPS package ids
41
+ # @return [Regexp] the regular expression
42
+ # @api private
43
+ def self.package_id_matchers
44
+ [ /^.Z/, /^[HK].{10}$/ ]
45
+ end
42
46
  # The required options for tracking a UPS package
43
- # @return [Array] the required options for tracking a UPS package.
47
+ # @return [Array] the required options for tracking a UPS package
44
48
  # @api private
45
- def required_options
49
+ def self.required_options
46
50
  [:key, :user_id, :password]
47
51
  end
48
52
 
53
+ protected
54
+
49
55
  # Parses the response from UPS
50
56
  # @return [Trackerific::Details]
51
57
  # @api private
@@ -56,15 +56,22 @@ module Trackerific
56
56
  )
57
57
  end
58
58
 
59
- protected
59
+ # A regex that matches valid package identifiers for USPS package ids
60
+ # @return [Regexp] the regular expression
61
+ # @api private
62
+ def self.package_id_matchers
63
+ [ /^E\D{1}\d{9}\D{2}$|^9\d{15,21}$/ ]
64
+ end
60
65
 
61
66
  # The required options for tracking a UPS package
62
- # @return [Array] the required options for tracking a UPS package.
67
+ # @return [Array] the required options for tracking a UPS package
63
68
  # @api private
64
- def required_options
69
+ def self.required_options
65
70
  [:user_id]
66
71
  end
67
72
 
73
+ protected
74
+
68
75
  # Builds an XML request to send to USPS
69
76
  # @return [String] the xml request
70
77
  # @api private
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ class TestBaseClass < Trackerific::Base
4
+ def self.required_options
5
+ [:required, :also_required]
6
+ end
7
+ end
8
+
9
+ describe 'Trackerific::Base' do
10
+
11
+ before(:all) do
12
+ @base = Trackerific::Base.new
13
+ end
14
+
15
+ context "with a new Trackerific::Base class that has required options" do
16
+ context "has all the required options" do
17
+ it "should be able to create a new instance" do
18
+ t = TestBaseClass.new(:required => true, :also_required => :yup)
19
+ t.should be_a TestBaseClass
20
+ end
21
+ end
22
+ context "is missing some required options" do
23
+ it "should raise an ArgumentError" do
24
+ lambda { TestBaseClass.new() }.should raise_error(ArgumentError)
25
+ end
26
+ end
27
+ context "has an invalid option" do
28
+ it "should raise an ArgumentError" do
29
+ lambda { TestBaseClass.new(:unknown => :argument ) }.should raise_error(ArgumentError)
30
+ end
31
+ end
32
+ end
33
+
34
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Trackerific::Error' do
4
+ # nothing to do here, yet
5
+ end
@@ -6,19 +6,27 @@ FEDEX_TRACK_URL = "https://gateway.fedex.com/GatewayDC"
6
6
  describe "Trackerific::FedEx" do
7
7
  include Fixtures
8
8
 
9
- before(:all) do
10
- @package_id = "183689015000001"
11
- @fedex = Trackerific::FedEx.new :account => "123456789", :meter => "123456789"
9
+ describe :required_options do
10
+ subject { Trackerific::FedEx.required_options }
11
+ it { should include(:account) }
12
+ it { should include(:meter) }
12
13
  end
13
14
 
14
- describe "track_package" do
15
+ describe :package_id_matchers do
16
+ it "should be an Array of Regexp" do
17
+ Trackerific::FedEx.package_id_matchers.should each { |m| m.should be_a Regexp }
18
+ end
19
+ end
20
+
21
+ describe :track_package do
22
+ before(:all) do
23
+ @package_id = "183689015000001"
24
+ @fedex = Trackerific::FedEx.new :account => "123456789", :meter => "123456789"
25
+ end
26
+
15
27
  context "with a successful response from the server" do
16
28
  before(:each) do
17
- FakeWeb.register_uri(
18
- :post,
19
- FEDEX_TRACK_URL,
20
- :body => load_fixture(:fedex_success_response)
21
- )
29
+ FakeWeb.register_uri(:post, FEDEX_TRACK_URL, :body => load_fixture(:fedex_success_response))
22
30
  @tracking = @fedex.track_package(@package_id)
23
31
  end
24
32
  specify { @tracking.should be_a Trackerific::Details }
@@ -29,13 +37,10 @@ describe "Trackerific::FedEx" do
29
37
  @tracking.summary.should_not be_empty
30
38
  end
31
39
  end
40
+
32
41
  context "with an error response from the server" do
33
42
  before(:all) do
34
- FakeWeb.register_uri(
35
- :post,
36
- FEDEX_TRACK_URL,
37
- :body => load_fixture(:fedex_error_response)
38
- )
43
+ FakeWeb.register_uri(:post, FEDEX_TRACK_URL, :body => load_fixture(:fedex_error_response))
39
44
  end
40
45
  specify { lambda { @fedex.track_package("invalid package id") }.should raise_error(Trackerific::Error) }
41
46
  end
@@ -6,19 +6,28 @@ UPS_TRACK_URL = 'https://wwwcie.ups.com/ups.app/xml/Track'
6
6
  describe "Trackerific::UPS" do
7
7
  include Fixtures
8
8
 
9
- before(:all) do
10
- @package_id = '1Z12345E0291980793'
11
- @ups = Trackerific::UPS.new :key => 'testkey', :user_id => 'testuser', :password => 'secret'
9
+ describe :required_options do
10
+ subject { Trackerific::UPS.required_options }
11
+ it { should include(:key) }
12
+ it { should include(:user_id) }
13
+ it { should include(:password) }
12
14
  end
13
15
 
14
- describe "track_package" do
16
+ describe :package_id_matchers do
17
+ it "should be an Array of Regexp" do
18
+ Trackerific::UPS.package_id_matchers.should each { |m| m.should be_a Regexp }
19
+ end
20
+ end
21
+
22
+ describe :track_package do
23
+ before(:all) do
24
+ @package_id = '1Z12345E0291980793'
25
+ @ups = Trackerific::UPS.new :key => 'testkey', :user_id => 'testuser', :password => 'secret'
26
+ end
27
+
15
28
  context "with a successful response from the server" do
16
29
  before(:all) do
17
- FakeWeb.register_uri(
18
- :post,
19
- UPS_TRACK_URL,
20
- :body => load_fixture(:ups_success_response)
21
- )
30
+ FakeWeb.register_uri(:post, UPS_TRACK_URL, :body => load_fixture(:ups_success_response))
22
31
  @tracking = @ups.track_package(@package_id)
23
32
  end
24
33
  specify { @tracking.should be_a Trackerific::Details }
@@ -29,13 +38,10 @@ describe "Trackerific::UPS" do
29
38
  @tracking.summary.should_not be_empty
30
39
  end
31
40
  end
41
+
32
42
  context "with an error response from the server" do
33
43
  before(:all) do
34
- FakeWeb.register_uri(
35
- :post,
36
- UPS_TRACK_URL,
37
- :body => load_fixture(:ups_error_response)
38
- )
44
+ FakeWeb.register_uri(:post, UPS_TRACK_URL, :body => load_fixture(:ups_error_response))
39
45
  end
40
46
  specify { lambda { @ups.track_package("invalid package id") }.should raise_error(Trackerific::Error) }
41
47
  end