trackerific 0.7.2 → 0.7.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/README.rdoc +2 -1
  4. data/lib/dependencies.rb +9 -0
  5. data/lib/trackerific.rb +5 -19
  6. data/lib/trackerific/builders.rb +12 -0
  7. data/lib/trackerific/builders/base/soap.rb +14 -16
  8. data/lib/trackerific/builders/base/xml.rb +22 -28
  9. data/lib/trackerific/builders/fedex.rb +66 -44
  10. data/lib/trackerific/builders/ups.rb +28 -24
  11. data/lib/trackerific/builders/usps.rb +15 -13
  12. data/lib/trackerific/parsers.rb +8 -0
  13. data/lib/trackerific/parsers/base.rb +24 -28
  14. data/lib/trackerific/parsers/fedex.rb +43 -47
  15. data/lib/trackerific/parsers/ups.rb +49 -53
  16. data/lib/trackerific/parsers/usps.rb +44 -48
  17. data/lib/trackerific/services.rb +10 -0
  18. data/lib/trackerific/services/base.rb +82 -55
  19. data/lib/trackerific/services/concerns/soap.rb +10 -40
  20. data/lib/trackerific/services/concerns/xml.rb +15 -37
  21. data/lib/trackerific/services/fedex.rb +9 -19
  22. data/lib/trackerific/services/mock_service.rb +26 -37
  23. data/lib/trackerific/services/ups.rb +11 -24
  24. data/lib/trackerific/services/usps.rb +23 -35
  25. data/lib/trackerific/soap.rb +5 -0
  26. data/lib/trackerific/soap/wsdl.rb +8 -12
  27. data/lib/trackerific/version.rb +1 -1
  28. data/spec/lib/trackerific/services/base_spec.rb +21 -4
  29. data/spec/lib/trackerific/services/concerns/soap_spec.rb +6 -21
  30. data/spec/lib/trackerific/services/concerns/xml_spec.rb +5 -18
  31. data/spec/lib/trackerific/services/mock_service_spec.rb +12 -0
  32. data/spec/lib/trackerific/services/usps_spec.rb +4 -4
  33. data/spec/lib/trackerific/version_spec.rb +1 -1
  34. data/spec/support/test_concerns.rb +15 -0
  35. metadata +8 -2
@@ -1,59 +1,55 @@
1
- module Trackerific
2
- module Parsers
3
- class FedEx < Parsers::Base
4
- protected
5
-
6
- def response_error
7
- @response_error ||= if highest_severity == 'ERROR'
8
- Trackerific::Error.new(notifications[:message])
9
- else
10
- false
11
- end
12
- end
1
+ class Trackerific::Parsers::FedEx < Trackerific::Parsers::Base
2
+ protected
3
+
4
+ def response_error
5
+ @response_error ||= if highest_severity == 'ERROR'
6
+ Trackerific::Error.new(notifications[:message])
7
+ else
8
+ false
9
+ end
10
+ end
13
11
 
14
- def summary
15
- nil
16
- end
12
+ def summary
13
+ nil
14
+ end
17
15
 
18
- def events
19
- track_details.map do |detail|
20
- Trackerific::Event.new(parse_date(detail), nil, location(detail))
21
- end
22
- end
16
+ def events
17
+ track_details.map do |detail|
18
+ Trackerific::Event.new(parse_date(detail), nil, location(detail))
19
+ end
20
+ end
23
21
 
24
- private
22
+ private
25
23
 
26
- def location(detail)
27
- a = detail[:destination_address]
28
- "#{a[:city]}, #{a[:state_or_province_code]} #{a[:country_code]}"
29
- end
24
+ def location(detail)
25
+ a = detail[:destination_address]
26
+ "#{a[:city]}, #{a[:state_or_province_code]} #{a[:country_code]}"
27
+ end
30
28
 
31
- def parse_date(detail)
32
- detail[:ship_timestamp]
33
- end
29
+ def parse_date(detail)
30
+ detail[:ship_timestamp]
31
+ end
34
32
 
35
- def track_reply
36
- @response.hash[:envelope][:body][:track_reply]
37
- end
33
+ def track_reply
34
+ @response.hash[:envelope][:body][:track_reply]
35
+ end
38
36
 
39
- def track_details
40
- @track_details ||= begin
41
- details = track_reply[:completed_track_details][:track_details]
42
- details.select do |d|
43
- d[:ship_timestamp].present? && d[:destination_address].present? &&
44
- d[:destination_address][:city].present? &&
45
- d[:destination_address][:state_or_province_code].present?
46
- end
47
- end
37
+ def track_details
38
+ @track_details ||= begin
39
+ details = track_reply[:completed_track_details][:track_details]
40
+ details.select do |d|
41
+ d[:ship_timestamp].present? && d[:destination_address].present? &&
42
+ d[:destination_address][:city].present? &&
43
+ d[:destination_address][:state_or_province_code].present?
48
44
  end
45
+ end
46
+ end
49
47
 
50
- def highest_severity
51
- track_reply[:highest_severity]
52
- end
48
+ def highest_severity
49
+ track_reply[:highest_severity]
50
+ end
53
51
 
54
- def notifications
55
- track_reply[:notifications]
56
- end
57
- end
52
+ def notifications
53
+ track_reply[:notifications]
58
54
  end
59
55
  end
@@ -1,66 +1,62 @@
1
- module Trackerific
2
- module Parsers
3
- class UPS < Parsers::Base
4
- protected
5
-
6
- def response_error
7
- @response_error ||= if @response.code != 200
8
- Trackerific::Error.new("HTTP returned status #{@response.code}")
9
- elsif response_status_code == :error
10
- Trackerific::Error.new(error_response)
11
- elsif response_status_code == :success
12
- false
13
- else
14
- Trackerific::Error.new("Unknown status code from server.")
15
- end
16
- end
1
+ class Trackerific::Parsers::UPS < Trackerific::Parsers::Base
2
+ protected
3
+
4
+ def response_error
5
+ @response_error ||= if @response.code != 200
6
+ Trackerific::Error.new("HTTP returned status #{@response.code}")
7
+ elsif response_status_code == :error
8
+ Trackerific::Error.new(error_response)
9
+ elsif response_status_code == :success
10
+ false
11
+ else
12
+ Trackerific::Error.new("Unknown status code from server.")
13
+ end
14
+ end
17
15
 
18
- def summary
19
- description(activity.first)
20
- end
16
+ def summary
17
+ description(activity.first)
18
+ end
21
19
 
22
- def events
23
- activity.map do |a|
24
- date = parse_ups_date_time(a['Date'], a['Time'])
25
- Trackerific::Event.new(date, description(a), location(a))
26
- end
27
- end
20
+ def events
21
+ activity.map do |a|
22
+ date = parse_ups_date_time(a['Date'], a['Time'])
23
+ Trackerific::Event.new(date, description(a), location(a))
24
+ end
25
+ end
28
26
 
29
- private
27
+ private
30
28
 
31
- def track_response
32
- @response['TrackResponse']
33
- end
29
+ def track_response
30
+ @response['TrackResponse']
31
+ end
34
32
 
35
- def response_status_code
36
- { "0" => :error,
37
- "1" => :success
38
- }[track_response['Response']['ResponseStatusCode']]
39
- end
33
+ def response_status_code
34
+ { "0" => :error,
35
+ "1" => :success
36
+ }[track_response['Response']['ResponseStatusCode']]
37
+ end
40
38
 
41
- def error_response
42
- track_response['Response']['Error']['ErrorDescription']
43
- end
39
+ def error_response
40
+ track_response['Response']['Error']['ErrorDescription']
41
+ end
44
42
 
45
- def parse_ups_date_time(date, time)
46
- hours, minutes, seconds = time.scan(/.{2}/)
47
- DateTime.parse("#{Date.parse(date)} #{hours}:#{minutes}:#{seconds}")
48
- end
43
+ def parse_ups_date_time(date, time)
44
+ hours, minutes, seconds = time.scan(/.{2}/)
45
+ DateTime.parse("#{Date.parse(date)} #{hours}:#{minutes}:#{seconds}")
46
+ end
49
47
 
50
- def description(a)
51
- a['Status']['StatusType']['Description']
52
- end
48
+ def description(a)
49
+ a['Status']['StatusType']['Description']
50
+ end
53
51
 
54
- def location(a)
55
- a['ActivityLocation']['Address'].map {|k,v| v}.join(" ")
56
- end
52
+ def location(a)
53
+ a['ActivityLocation']['Address'].map {|k,v| v}.join(" ")
54
+ end
57
55
 
58
- def activity
59
- @activity ||= begin
60
- a = track_response['Shipment']['Package']['Activity']
61
- a.is_a?(Array) ? a : [a]
62
- end
63
- end
56
+ def activity
57
+ @activity ||= begin
58
+ a = track_response['Shipment']['Package']['Activity']
59
+ a.is_a?(Array) ? a : [a]
64
60
  end
65
61
  end
66
62
  end
@@ -1,51 +1,47 @@
1
- module Trackerific
2
- module Parsers
3
- class USPS < Parsers::Base
4
- protected
5
-
6
- def response_error
7
- @response_error ||= if @response.code != 200
8
- Trackerific::Error.new("HTTP returned status #{@response.code}")
9
- elsif @response['Error']
10
- Trackerific::Error.new(@response['Error']['Description'])
11
- elsif @response['TrackResponse'].nil? && @response['CityStateLookupResponse'].nil?
12
- Trackerific::Error.new("Invalid response from server.")
13
- else
14
- false
15
- end
16
- end
17
-
18
- def summary
19
- tracking_info['TrackSummary']
20
- end
21
-
22
- def events
23
- tracking_info.fetch('TrackDetail', []).map do |e|
24
- Trackerific::Event.new(date(e), description(e), location(e))
25
- end
26
- end
27
-
28
- private
29
-
30
- def tracking_info
31
- @response['TrackResponse']['TrackInfo']
32
- end
33
-
34
- def date(event)
35
- d = event.split(" ")
36
- DateTime.parse(d[0..3].join(" "))
37
- end
38
-
39
- def description(event)
40
- d = event.split(" ")
41
- d[4..d.length-4].join(" ")
42
- end
43
-
44
- def location(event)
45
- d = event.gsub(".", "").split(" ")
46
- city, state, zip = d.last(3)
47
- "#{city}, #{state} #{zip}"
48
- end
1
+ class Trackerific::Parsers::USPS < Trackerific::Parsers::Base
2
+ protected
3
+
4
+ def response_error
5
+ @response_error ||= if @response.code != 200
6
+ Trackerific::Error.new("HTTP returned status #{@response.code}")
7
+ elsif @response['Error']
8
+ Trackerific::Error.new(@response['Error']['Description'])
9
+ elsif @response['TrackResponse'].nil? && @response['CityStateLookupResponse'].nil?
10
+ Trackerific::Error.new("Invalid response from server.")
11
+ else
12
+ false
49
13
  end
50
14
  end
15
+
16
+ def summary
17
+ tracking_info['TrackSummary']
18
+ end
19
+
20
+ def events
21
+ tracking_info.fetch('TrackDetail', []).map do |e|
22
+ Trackerific::Event.new(date(e), description(e), location(e))
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ def tracking_info
29
+ @response['TrackResponse']['TrackInfo']
30
+ end
31
+
32
+ def date(event)
33
+ d = event.split(" ")
34
+ DateTime.parse(d[0..3].join(" "))
35
+ end
36
+
37
+ def description(event)
38
+ d = event.split(" ")
39
+ d[4..d.length-4].join(" ")
40
+ end
41
+
42
+ def location(event)
43
+ d = event.gsub(".", "").split(" ")
44
+ city, state, zip = d.last(3)
45
+ "#{city}, #{state} #{zip}"
46
+ end
51
47
  end
@@ -37,5 +37,15 @@ module Trackerific
37
37
  @services.map {|n,s| s if s.can_track?(id) }.compact
38
38
  end
39
39
  end
40
+
41
+ module Concerns
42
+ require 'trackerific/services/concerns/soap'
43
+ require 'trackerific/services/concerns/xml'
44
+ end
45
+
46
+ require 'trackerific/services/base'
47
+ require 'trackerific/services/fedex'
48
+ require 'trackerific/services/ups'
49
+ require 'trackerific/services/usps'
40
50
  end
41
51
  end
@@ -1,58 +1,85 @@
1
- module Trackerific
2
- module Services
3
- class Base
4
- @name = nil
5
-
6
- class << self
7
- attr_accessor :name
8
-
9
- # Registers the service with Trackerific
10
- # @api semipublic
11
- def register(name)
12
- self.name = name.to_sym
13
- Trackerific::Services[self.name] = self
14
- end
15
-
16
- # Creates a new instance and calls #track with the given id
17
- # @param id The package identifier
18
- # @return Either a Trackerific::Details or Trackerific::Error
19
- def track(id)
20
- new.track(id)
21
- end
22
-
23
- # Reads the credentials from Trackerific.config
24
- # @return [Hash] The service's credentials
25
- def credentials
26
- Trackerific.config[name]
27
- end
28
-
29
- # Checks if the given package ID can be tracked by this service
30
- # @param [String] id The package ID
31
- # @return [Boolean] true when this service can track the given ID
32
- # @note This will always be false if no credentials were found for the
33
- # service in Trackerific.config
34
- def can_track?(id)
35
- return false if credentials.nil?
36
- package_id_matchers.each {|m| return true if id =~ m }
37
- false
38
- end
39
-
40
- # An Array of Regexp that matches valid package ids for the service
41
- # @api semipublic
42
- def package_id_matchers
43
- raise NotImplementedError,
44
- "You must implement this method in your service", caller
45
- end
46
- end
47
-
48
- def initialize(credentials=self.class.credentials)
49
- @credentials = credentials
50
-
51
- if credentials.nil?
52
- raise Trackerific::Error,
53
- "Missing credentials for #{self.class.name}", caller
54
- end
55
- end
1
+ class Trackerific::Services::Base
2
+ class << self
3
+ attr_accessor :name
4
+ attr_accessor :config
5
+
6
+ # Configures the service
7
+ # @api semipublic
8
+ def configure(&block)
9
+ yield self.config = OpenStruct.new
10
+ end
11
+
12
+ # Includes the service concerns for the given service type
13
+ # @param [Symbol] service_type The module name for the service type
14
+ # @api semipublic
15
+ def concerns(service_type)
16
+ self.send :include,
17
+ "Trackerific::Services::Concerns::#{service_type}".constantize
18
+ end
19
+
20
+ # Registers the service with Trackerific
21
+ # @api semipublic
22
+ def register(name, options={})
23
+ concerns(options[:as]) if options[:as].present?
24
+ self.name = name.to_sym
25
+ Trackerific::Services[self.name] = self
26
+ end
27
+
28
+ # Creates a new instance and calls #track with the given id
29
+ # @param id The package identifier
30
+ # @return Either a Trackerific::Details or Trackerific::Error
31
+ def track(id)
32
+ new.track(id)
33
+ end
34
+
35
+ # Reads the credentials from Trackerific.config
36
+ # @return [Hash] The service's credentials
37
+ def credentials
38
+ Trackerific.config[name]
39
+ end
40
+
41
+ # Checks if the given package ID can be tracked by this service
42
+ # @param [String] id The package ID
43
+ # @return [Boolean] true when this service can track the given ID
44
+ # @note This will always be false if no credentials were found for the
45
+ # service in Trackerific.config
46
+ def can_track?(id)
47
+ return false if credentials.nil?
48
+ package_id_matchers.each {|m| return true if id =~ m }
49
+ false
50
+ end
51
+
52
+ # An Array of Regexp that matches valid package ids for the service
53
+ # @api semipublic
54
+ def package_id_matchers
55
+ config.package_id_matchers
56
+ end
57
+ end
58
+
59
+ def initialize(credentials=self.class.credentials)
60
+ @credentials = credentials
61
+
62
+ if credentials.nil?
63
+ raise Trackerific::Error,
64
+ "Missing credentials for #{self.class.name}", caller
56
65
  end
57
66
  end
67
+
68
+ def config
69
+ self.class.config
70
+ end
71
+
72
+ def track(id)
73
+ result = config.parser.new(id, request(id)).parse
74
+ result.is_a?(Trackerific::Error) ? raise(result) : result
75
+ end
76
+
77
+ protected
78
+
79
+ def builder(id)
80
+ members = config.builder.members - [:package_id]
81
+ credentials = @credentials.values_at(*members)
82
+ credentials << id
83
+ config.builder.new(*credentials)
84
+ end
58
85
  end