trackerific 0.3.5 → 0.4.0
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/Gemfile +1 -1
- data/README.rdoc +37 -13
- data/VERSION +1 -1
- data/doc/OptionsHelper.html +287 -0
- data/doc/Trackerific.html +588 -35
- data/doc/Trackerific/Configuration.html +354 -0
- data/doc/Trackerific/Details.html +1 -1
- data/doc/Trackerific/Error.html +1 -1
- data/doc/Trackerific/Event.html +1 -1
- data/doc/Trackerific/FedEx.html +52 -35
- data/doc/Trackerific/{Base.html → Service.html} +54 -49
- data/doc/Trackerific/UPS.html +48 -31
- data/doc/Trackerific/USPS.html +51 -34
- data/doc/_index.html +35 -4
- data/doc/class_list.html +1 -1
- data/doc/file.README.html +42 -15
- data/doc/index.html +42 -15
- data/doc/method_list.html +83 -19
- data/doc/top-level-namespace.html +2 -2
- data/lib/helpers/options_helper.rb +20 -0
- data/lib/trackerific.rb +52 -18
- data/lib/trackerific/configuration.rb +49 -0
- data/lib/trackerific/service.rb +68 -0
- data/lib/trackerific/services/fedex.rb +18 -16
- data/lib/trackerific/services/ups.rb +16 -14
- data/lib/trackerific/services/usps.rb +17 -15
- data/spec/lib/trackerific/configuration_spec.rb +9 -0
- data/spec/lib/trackerific/details_spec.rb +12 -9
- data/spec/lib/trackerific/error_spec.rb +6 -2
- data/spec/lib/trackerific/event_spec.rb +21 -8
- data/spec/lib/trackerific/service_spec.rb +34 -0
- data/spec/lib/trackerific/services/fedex_spec.rb +23 -9
- data/spec/lib/trackerific/services/ups_spec.rb +23 -8
- data/spec/lib/trackerific/services/usps_spec.rb +22 -8
- data/spec/lib/trackerific_spec.rb +29 -7
- data/spec/spec_helper.rb +1 -0
- data/spec/support/fixtures.rb +16 -10
- data/spec/support/trackerific.rb +2 -2
- data/trackerific.gemspec +13 -8
- metadata +30 -25
- data/lib/trackerific/base.rb +0 -70
- data/spec/lib/trackerific/base_spec.rb +0 -34
@@ -0,0 +1,20 @@
|
|
1
|
+
# Helper for validating required options
|
2
|
+
module OptionsHelper
|
3
|
+
# Validates a list of options against a list of required options
|
4
|
+
# @param [Array] options list of options to validate
|
5
|
+
# @param [Array] required list of required options
|
6
|
+
# @return true
|
7
|
+
# @raise [ArgumentError] if the options do not pass validation
|
8
|
+
# @api private
|
9
|
+
def validate_options(options, required)
|
10
|
+
# make sure all the required options exist
|
11
|
+
required.each do |k|
|
12
|
+
raise ArgumentError.new("Missing required parameter: #{k}") unless options.has_key?(k)
|
13
|
+
end
|
14
|
+
# make sure no invalid options exist
|
15
|
+
options.each do |k, v|
|
16
|
+
raise ArgumentError.new("Invalid parameter: #{k}") unless required.include?(k)
|
17
|
+
end
|
18
|
+
true
|
19
|
+
end
|
20
|
+
end
|
data/lib/trackerific.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'rails'
|
2
|
-
require '
|
2
|
+
require 'helpers/options_helper'
|
3
|
+
require 'trackerific/configuration'
|
4
|
+
require 'trackerific/service'
|
3
5
|
require 'trackerific/error'
|
4
6
|
require 'trackerific/details'
|
5
7
|
require 'trackerific/event'
|
@@ -10,6 +12,30 @@ Dir[File.expand_path(services_path)].each { |file| require file }
|
|
10
12
|
|
11
13
|
# Trackerific provides package tracking to Rails apps.
|
12
14
|
module Trackerific
|
15
|
+
|
16
|
+
class << self
|
17
|
+
# Gets a list of all Trackerific services
|
18
|
+
# @return [Array, Symbol] the services
|
19
|
+
# @api private
|
20
|
+
def services
|
21
|
+
# a service is any Trackerific class that descends from Trackerific::Service
|
22
|
+
Trackerific.constants.reject { |const|
|
23
|
+
const unless Trackerific.const_get(const).superclass == Trackerific::Service
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
# Gets a Trackerific::Service class
|
28
|
+
# @param [Symbol] name the name of the service
|
29
|
+
# @return [Trackerific::Service] the service, or nil
|
30
|
+
# @api private
|
31
|
+
def service_get(name)
|
32
|
+
services.each do |service|
|
33
|
+
return Trackerific.const_get(service) if name == service.to_s.downcase.to_sym
|
34
|
+
end
|
35
|
+
return nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
13
39
|
# Checks a string for a valid package tracking service
|
14
40
|
# @param [String] package_id the package identifier
|
15
41
|
# @return [Trackerific::Base] the Trackerific class that can track the given
|
@@ -19,33 +45,41 @@ module Trackerific
|
|
19
45
|
# tracking_service "183689015000001" # => Trackerific::FedEx
|
20
46
|
# @api public
|
21
47
|
def tracking_service(package_id)
|
22
|
-
# loop through
|
23
|
-
Trackerific.
|
24
|
-
# get the
|
25
|
-
cls = Trackerific.const_get(
|
26
|
-
#
|
27
|
-
|
28
|
-
#
|
29
|
-
cls
|
30
|
-
# return the class if it matches
|
31
|
-
return cls if package_id =~ matcher
|
32
|
-
end
|
48
|
+
# loop through all the services
|
49
|
+
Trackerific.services.each do |service|
|
50
|
+
# get the class associated with this service
|
51
|
+
cls = Trackerific.const_get(service)
|
52
|
+
# loop through all the packge id regular expressions
|
53
|
+
cls.package_id_matchers.each do |matcher|
|
54
|
+
# return this class if the regular expression matches
|
55
|
+
return cls if package_id =~ matcher
|
33
56
|
end
|
34
57
|
end
|
35
58
|
# if we've made it this far, nothing matched
|
36
59
|
nil
|
37
60
|
end
|
38
61
|
|
39
|
-
#
|
62
|
+
# Tracks a package by determining its service from the package id
|
40
63
|
# @param [String] package_id the package identifier
|
41
64
|
# @return [Trackerific::Details] the tracking results
|
42
65
|
# @raise [Trackerific::Error] raised when the server returns an error (invalid credentials, tracking package, etc.)
|
43
66
|
# @example Track a package
|
44
67
|
# include Trackerific
|
45
|
-
#
|
68
|
+
# # make sure to configure Trackerific before hand with the different services credentials
|
69
|
+
# Trackerific.config do |config|
|
70
|
+
# config.fedex :meter => '123456789', :account => '123456789'
|
71
|
+
# end
|
72
|
+
# details = track_package "183689015000001"
|
46
73
|
# @api public
|
47
|
-
|
48
|
-
#
|
49
|
-
|
50
|
-
#
|
74
|
+
def track_package(package_id)
|
75
|
+
# find the service that will be able to track this package
|
76
|
+
service = tracking_service package_id
|
77
|
+
raise Trackerific::Error "Cannot find a service to track package id #{package_id}" if service.nil?
|
78
|
+
# get the name of the service
|
79
|
+
service_name = service.to_s.split('::')[1].downcase
|
80
|
+
# get the default configuration for the service
|
81
|
+
options = Trackerific.configuration.send service_name
|
82
|
+
# track the package
|
83
|
+
service.new(options).track_package package_id
|
84
|
+
end
|
51
85
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Trackerific
|
2
|
+
# Provides a dynamic configuration
|
3
|
+
class Configuration
|
4
|
+
include OptionsHelper
|
5
|
+
# Creates a new instance of Trackerific::Configuration
|
6
|
+
# @api private
|
7
|
+
def initialize
|
8
|
+
@options = {}
|
9
|
+
end
|
10
|
+
# Overriding the method_missing method allows dynamic methods
|
11
|
+
# @return [Hash]
|
12
|
+
# @api private
|
13
|
+
def method_missing(sym, *args, &block)
|
14
|
+
# Get a list of all the services (convert symbols to lower case)
|
15
|
+
services = Trackerific.services.map { |service| service.to_s.downcase.to_sym }
|
16
|
+
# Do not accept any configuration values for anything except services
|
17
|
+
raise NoMethodError unless services.include? sym
|
18
|
+
# Only accept Hashes
|
19
|
+
unless args.empty?
|
20
|
+
raise ArgumentError unless args[0].class == Hash
|
21
|
+
# Validate configuration values against the required options for that service
|
22
|
+
validate_options args[0], Trackerific.service_get(sym).required_options
|
23
|
+
# Store the configuration options
|
24
|
+
@options[sym] = args[0]
|
25
|
+
end
|
26
|
+
# return the configuration options
|
27
|
+
@options[sym]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
class << self
|
31
|
+
# Stores the configuration options for Trackerific
|
32
|
+
# @return [Trackerific::Configuration]
|
33
|
+
# @api private
|
34
|
+
def configuration
|
35
|
+
@configuration ||= Trackerific::Configuration.new
|
36
|
+
end
|
37
|
+
# Configures Trackerific
|
38
|
+
# @return [Trackerific::Configuration]
|
39
|
+
# @example Defining credentials
|
40
|
+
# Trackerific.configure do |config|
|
41
|
+
# config.fedex :meter => '123456789', :account => '123456789'
|
42
|
+
# end
|
43
|
+
# @api public
|
44
|
+
def configure
|
45
|
+
yield configuration
|
46
|
+
configuration
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Trackerific
|
2
|
+
# Base class for Trackerific services
|
3
|
+
class Service
|
4
|
+
include OptionsHelper
|
5
|
+
|
6
|
+
# Creates a new instance of Trackerific::Service with required options
|
7
|
+
# @api private
|
8
|
+
def initialize(options = {})
|
9
|
+
validate_options options, self.class.required_options
|
10
|
+
@options = options
|
11
|
+
end
|
12
|
+
|
13
|
+
# Gets the tracking information for the package from the server
|
14
|
+
# @param [String] package_id the package identifier
|
15
|
+
# @return [Trackerific::Details] the tracking details
|
16
|
+
# @example Override this method in your custom tracking service to implement tracking
|
17
|
+
# module Trackerific
|
18
|
+
# class MyTrackingService < Trackerific::Service
|
19
|
+
# def track_package
|
20
|
+
# # your tracking code here
|
21
|
+
# Trackerific::Details.new(
|
22
|
+
# "summary of tracking events",
|
23
|
+
# [Trackerific::Event.new(Time.now, "summary", "location")]
|
24
|
+
# )
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
# @api semipublic
|
29
|
+
def track_package(package_id)
|
30
|
+
@package_id = package_id
|
31
|
+
end
|
32
|
+
|
33
|
+
class << self
|
34
|
+
|
35
|
+
# An Array of Regexp that matches valid package identifiers for your service
|
36
|
+
# @example Override this method in your custom tracking service
|
37
|
+
# module Trackerific
|
38
|
+
# class MyTrackingService < Service
|
39
|
+
# def self.package_id_matchers
|
40
|
+
# [ /^.Z/, /^[HK].{10}$/ ] # matchers for UPS package identifiers
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
# end
|
44
|
+
# @return [Array, Regexp] an array of regular expressions
|
45
|
+
# @api semipublic
|
46
|
+
def package_id_matchers
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
|
50
|
+
# An array of options that are required to create a new instance of this class
|
51
|
+
# @return [Array] the required options
|
52
|
+
# @example Override this method in your custom tracking service to enforce some options
|
53
|
+
# module Trackerific
|
54
|
+
# class MyTrackingService < Service
|
55
|
+
# def self.required_options
|
56
|
+
# [:all, :these, :are, :required]
|
57
|
+
# end
|
58
|
+
# end
|
59
|
+
# end
|
60
|
+
# @api semipublic
|
61
|
+
def required_options
|
62
|
+
[]
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
@@ -3,12 +3,29 @@ require 'httparty'
|
|
3
3
|
module Trackerific
|
4
4
|
|
5
5
|
# Provides package tracking support for FedEx
|
6
|
-
class FedEx <
|
6
|
+
class FedEx < Trackerific::Service
|
7
7
|
# setup HTTParty
|
8
8
|
include ::HTTParty
|
9
9
|
format :xml
|
10
10
|
base_uri "https://gateway.fedex.com"
|
11
11
|
|
12
|
+
class << self
|
13
|
+
# An Array of Regexp that matches valid FedEx package IDs
|
14
|
+
# @return [Array, Regexp] the regular expression
|
15
|
+
# @api private
|
16
|
+
def package_id_matchers
|
17
|
+
[ /^[0-9]{15}$/ ]
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns an Array of required options used when creating a new instance
|
21
|
+
# @return [Array] required options for tracking a FedEx package are :account
|
22
|
+
# and :meter
|
23
|
+
# @api private
|
24
|
+
def required_options
|
25
|
+
[:account, :meter]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
12
29
|
# Tracks a FedEx package
|
13
30
|
# @param [String] package_id the package identifier
|
14
31
|
# @return [Trackerific::Details] the tracking details
|
@@ -45,21 +62,6 @@ module Trackerific
|
|
45
62
|
)
|
46
63
|
end
|
47
64
|
|
48
|
-
# An Array of Regexp that matches valid FedEx package IDs
|
49
|
-
# @return [Array, Regexp] the regular expression
|
50
|
-
# @api private
|
51
|
-
def self.package_id_matchers
|
52
|
-
[ /^[0-9]{15}$/ ]
|
53
|
-
end
|
54
|
-
|
55
|
-
# Returns an Array of required options used when creating a new instance
|
56
|
-
# @return [Array] required options for tracking a FedEx package are :account
|
57
|
-
# and :meter
|
58
|
-
# @api private
|
59
|
-
def self.required_options
|
60
|
-
[:account, :meter]
|
61
|
-
end
|
62
|
-
|
63
65
|
protected
|
64
66
|
|
65
67
|
# Builds the XML request to send to FedEx
|
@@ -4,7 +4,7 @@ module Trackerific
|
|
4
4
|
require 'httparty'
|
5
5
|
|
6
6
|
# Provides package tracking support for UPS.
|
7
|
-
class UPS <
|
7
|
+
class UPS < Trackerific::Service
|
8
8
|
# setup HTTParty
|
9
9
|
include ::HTTParty
|
10
10
|
format :xml
|
@@ -14,6 +14,21 @@ module Trackerific
|
|
14
14
|
when 'production' then 'https://www.ups.com/ups.app/xml'
|
15
15
|
end : 'https://www.ups.com/ups.app/xml'
|
16
16
|
|
17
|
+
class << self
|
18
|
+
# An Array of Regexp that matches valid UPS package IDs
|
19
|
+
# @return [Array, Regexp] the regular expression
|
20
|
+
# @api private
|
21
|
+
def package_id_matchers
|
22
|
+
[ /^.Z/, /^[HK].{10}$/ ]
|
23
|
+
end
|
24
|
+
# The required options for tracking a UPS package
|
25
|
+
# @return [Array] the required options for tracking a UPS package
|
26
|
+
# @api private
|
27
|
+
def required_options
|
28
|
+
[:key, :user_id, :password]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
17
32
|
# Tracks a UPS package
|
18
33
|
# @param [String] package_id the package identifier
|
19
34
|
# @return [Trackerific::Details] the tracking details
|
@@ -37,19 +52,6 @@ module Trackerific
|
|
37
52
|
end
|
38
53
|
end
|
39
54
|
|
40
|
-
# An Array of Regexp that matches valid UPS package IDs
|
41
|
-
# @return [Array, Regexp] the regular expression
|
42
|
-
# @api private
|
43
|
-
def self.package_id_matchers
|
44
|
-
[ /^.Z/, /^[HK].{10}$/ ]
|
45
|
-
end
|
46
|
-
# The required options for tracking a UPS package
|
47
|
-
# @return [Array] the required options for tracking a UPS package
|
48
|
-
# @api private
|
49
|
-
def self.required_options
|
50
|
-
[:key, :user_id, :password]
|
51
|
-
end
|
52
|
-
|
53
55
|
protected
|
54
56
|
|
55
57
|
# Parses the response from UPS
|
@@ -5,7 +5,7 @@ module Trackerific
|
|
5
5
|
require 'httparty'
|
6
6
|
|
7
7
|
# Provides package tracking support for USPS.
|
8
|
-
class USPS <
|
8
|
+
class USPS < Trackerific::Service
|
9
9
|
# setup HTTParty
|
10
10
|
include HTTParty
|
11
11
|
format :xml
|
@@ -15,6 +15,22 @@ module Trackerific
|
|
15
15
|
when 'production' then 'https://secure.shippingapis.com'
|
16
16
|
end : 'https://secure.shippingapis.com'
|
17
17
|
|
18
|
+
class << self
|
19
|
+
# An Array of Regexp that matches valid USPS package IDs
|
20
|
+
# @return [Array, Regexp] the regular expression
|
21
|
+
# @api private
|
22
|
+
def package_id_matchers
|
23
|
+
[ /^E\D{1}\d{9}\D{2}$|^9\d{15,21}$/ ]
|
24
|
+
end
|
25
|
+
|
26
|
+
# The required options for tracking a UPS package
|
27
|
+
# @return [Array] the required options for tracking a UPS package
|
28
|
+
# @api private
|
29
|
+
def required_options
|
30
|
+
[:user_id]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
18
34
|
# Tracks a USPS package
|
19
35
|
# @param [String] package_id the package identifier
|
20
36
|
# @return [Trackerific::Details] the tracking details
|
@@ -56,20 +72,6 @@ module Trackerific
|
|
56
72
|
)
|
57
73
|
end
|
58
74
|
|
59
|
-
# An Array of Regexp that matches valid USPS package IDs
|
60
|
-
# @return [Array, 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
|
65
|
-
|
66
|
-
# The required options for tracking a UPS package
|
67
|
-
# @return [Array] the required options for tracking a UPS package
|
68
|
-
# @api private
|
69
|
-
def self.required_options
|
70
|
-
[:user_id]
|
71
|
-
end
|
72
|
-
|
73
75
|
protected
|
74
76
|
|
75
77
|
# Builds an XML request to send to USPS
|
@@ -1,19 +1,22 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Trackerific::Details do
|
4
|
-
|
5
|
-
|
6
|
-
end
|
4
|
+
|
5
|
+
before { @details = Trackerific::Details.new(String.new, String.new, Array.new) }
|
7
6
|
|
8
|
-
describe
|
9
|
-
|
7
|
+
describe :events do
|
8
|
+
subject { @details.events }
|
9
|
+
it { should be_a Array }
|
10
10
|
end
|
11
11
|
|
12
|
-
describe
|
13
|
-
|
12
|
+
describe :package_id do
|
13
|
+
subject { @details.package_id }
|
14
|
+
it { should be_a String }
|
14
15
|
end
|
15
16
|
|
16
|
-
describe
|
17
|
-
|
17
|
+
describe :summary do
|
18
|
+
subject { @details.summary }
|
19
|
+
it { should be_a String }
|
18
20
|
end
|
21
|
+
|
19
22
|
end
|