shippinglogic 1.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/.document +5 -0
  2. data/CHANGELOG.rdoc +55 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +175 -0
  5. data/Rakefile +37 -0
  6. data/VERSION.yml +5 -0
  7. data/init.rb +1 -0
  8. data/lib/shippinglogic.rb +3 -0
  9. data/lib/shippinglogic/attributes.rb +121 -0
  10. data/lib/shippinglogic/error.rb +22 -0
  11. data/lib/shippinglogic/fedex.rb +84 -0
  12. data/lib/shippinglogic/fedex/cancel.rb +47 -0
  13. data/lib/shippinglogic/fedex/enumerations.rb +348 -0
  14. data/lib/shippinglogic/fedex/error.rb +47 -0
  15. data/lib/shippinglogic/fedex/rate.rb +229 -0
  16. data/lib/shippinglogic/fedex/request.rb +134 -0
  17. data/lib/shippinglogic/fedex/response.rb +72 -0
  18. data/lib/shippinglogic/fedex/service.rb +11 -0
  19. data/lib/shippinglogic/fedex/ship.rb +238 -0
  20. data/lib/shippinglogic/fedex/signature.rb +68 -0
  21. data/lib/shippinglogic/fedex/track.rb +124 -0
  22. data/lib/shippinglogic/proxy.rb +23 -0
  23. data/lib/shippinglogic/service.rb +42 -0
  24. data/lib/shippinglogic/ups.rb +83 -0
  25. data/lib/shippinglogic/ups/cancel.rb +52 -0
  26. data/lib/shippinglogic/ups/enumerations.rb +56 -0
  27. data/lib/shippinglogic/ups/error.rb +42 -0
  28. data/lib/shippinglogic/ups/label.rb +50 -0
  29. data/lib/shippinglogic/ups/rate.rb +228 -0
  30. data/lib/shippinglogic/ups/request.rb +49 -0
  31. data/lib/shippinglogic/ups/response.rb +58 -0
  32. data/lib/shippinglogic/ups/service.rb +11 -0
  33. data/lib/shippinglogic/ups/ship_accept.rb +53 -0
  34. data/lib/shippinglogic/ups/ship_confirm.rb +170 -0
  35. data/lib/shippinglogic/ups/track.rb +118 -0
  36. data/lib/shippinglogic/validation.rb +32 -0
  37. data/shippinglogic.gemspec +120 -0
  38. data/spec/attributes_spec.rb +67 -0
  39. data/spec/config/fedex_credentials.example.yml +4 -0
  40. data/spec/config/ups_credentials.example.yml +3 -0
  41. data/spec/error_spec.rb +43 -0
  42. data/spec/fedex/cancel_spec.rb +10 -0
  43. data/spec/fedex/error_spec.rb +26 -0
  44. data/spec/fedex/rate_spec.rb +87 -0
  45. data/spec/fedex/request_spec.rb +15 -0
  46. data/spec/fedex/responses/blank.xml +0 -0
  47. data/spec/fedex/responses/cancel_not_found.xml +7 -0
  48. data/spec/fedex/responses/failed_authentication.xml +7 -0
  49. data/spec/fedex/responses/malformed.xml +8 -0
  50. data/spec/fedex/responses/rate_defaults.xml +7 -0
  51. data/spec/fedex/responses/rate_insurance.xml +9 -0
  52. data/spec/fedex/responses/rate_no_services.xml +7 -0
  53. data/spec/fedex/responses/rate_non_custom_packaging.xml +7 -0
  54. data/spec/fedex/responses/ship_defaults.xml +7 -0
  55. data/spec/fedex/responses/ship_with_no_signature.xml +7 -0
  56. data/spec/fedex/responses/signature_defaults.xml +7 -0
  57. data/spec/fedex/responses/track_defaults.xml +7 -0
  58. data/spec/fedex/responses/unexpected.xml +1 -0
  59. data/spec/fedex/service_spec.rb +19 -0
  60. data/spec/fedex/ship_spec.rb +37 -0
  61. data/spec/fedex/signature_spec.rb +11 -0
  62. data/spec/fedex/spec_helper.rb +84 -0
  63. data/spec/fedex/track_spec.rb +37 -0
  64. data/spec/fedex_spec.rb +16 -0
  65. data/spec/lib/interceptor.rb +17 -0
  66. data/spec/proxy_spec.rb +42 -0
  67. data/spec/service_spec.rb +23 -0
  68. data/spec/spec_helper.rb +12 -0
  69. data/spec/ups/responses/blank.xml +0 -0
  70. data/spec/ups/responses/track_defaults.xml +2 -0
  71. data/spec/ups/spec_helper.rb +43 -0
  72. data/spec/ups_spec.rb +16 -0
  73. data/spec/validation_spec.rb +49 -0
  74. metadata +163 -0
@@ -0,0 +1,11 @@
1
+ require "shippinglogic/fedex/request"
2
+ require "shippinglogic/fedex/response"
3
+
4
+ module Shippinglogic
5
+ class FedEx
6
+ class Service < Shippinglogic::Service
7
+ include Request
8
+ include Response
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,238 @@
1
+ require "base64"
2
+
3
+ module Shippinglogic
4
+ class FedEx
5
+ # An interface to the shipe services provided by FedEx. Allows you to create shipments and get various information on the shipment
6
+ # created. Such as the tracking number, the label image, barcode image, delivery date, etc.
7
+ #
8
+ # == Options
9
+ # === Shipper options
10
+ #
11
+ # * <tt>shipper_name</tt> - name of the shipper.
12
+ # * <tt>shipper_title</tt> - title of the shipper.
13
+ # * <tt>shipper_company_name</tt> - company name of the shipper.
14
+ # * <tt>shipper_phone_number</tt> - phone number of the shipper.
15
+ # * <tt>shipper_email</tt> - email of the shipper.
16
+ # * <tt>shipper_streets</tt> - street part of the address, separate multiple streets with a new line, dont include blank lines.
17
+ # * <tt>shipper_city</tt> - city part of the address.
18
+ # * <tt>shipper_state_</tt> - state part of the address, use state abreviations.
19
+ # * <tt>shipper_postal_code</tt> - postal code part of the address. Ex: zip for the US.
20
+ # * <tt>shipper_country</tt> - country code part of the address. FedEx expects abbreviations, but Shippinglogic will convert full names to abbreviations for you.
21
+ # * <tt>shipper_residential</tt> - a boolean value representing if the address is redential or not (default: false)
22
+ #
23
+ # === Recipient options
24
+ #
25
+ # * <tt>recipient_name</tt> - name of the recipient.
26
+ # * <tt>recipient_title</tt> - title of the recipient.
27
+ # * <tt>recipient_company_name</tt> - company name of the recipient.
28
+ # * <tt>recipient_phone_number</tt> - phone number of the recipient.
29
+ # * <tt>recipient_email</tt> - email of the recipient.
30
+ # * <tt>recipient_streets</tt> - street part of the address, separate multiple streets with a new line, dont include blank lines.
31
+ # * <tt>recipient_city</tt> - city part of the address.
32
+ # * <tt>recipient_state</tt> - state part of the address, use state abreviations.
33
+ # * <tt>recipient_postal_code</tt> - postal code part of the address. Ex: zip for the US.
34
+ # * <tt>recipient_country</tt> - country code part of the address. FedEx expects abbreviations, but Shippinglogic will convert full names to abbreviations for you.
35
+ # * <tt>recipient_residential</tt> - a boolean value representing if the address is redential or not (default: false)
36
+ #
37
+ # === Label options
38
+ #
39
+ # * <tt>label_format</tt> - one of Enumerations::LABEL_FORMATS. (default: COMMON2D)
40
+ # * <tt>label_file_type</tt> - one of Enumerations::LABEL_FILE_TYPES. (default: PDF)
41
+ # * <tt>label_stock_type</tt> - one of Enumerations::LABEL_STOCK_TYPES. (default: PAPER_8.5X11_TOP_HALF_LABEL)
42
+ #
43
+ # === Packaging options
44
+ #
45
+ # One thing to note is that FedEx does support multiple package shipments. The problem is that all of the packages must be identical.
46
+ # FedEx specifically notes in their documentation that mutiple package specifications are not allowed. So your only option for a
47
+ # multi package shipment is to increase the package_count option and keep the dimensions and weight the same for all packages. Then again,
48
+ # the documentation for the FedEx web services is terrible, so I could be wrong. Any tests I tried resulted in an error though.
49
+ #
50
+ # * <tt>packaging_type</tt> - one of Enumerations::PACKAGE_TYPES. (default: YOUR_PACKAGING)
51
+ # * <tt>package_count</tt> - the number of packages in your shipment. (default: 1)
52
+ # * <tt>package_weight</tt> - a single packages weight.
53
+ # * <tt>package_weight_units</tt> - either LB or KG. (default: LB)
54
+ # * <tt>package_length</tt> - a single packages length, only required if using YOUR_PACKAGING for packaging_type.
55
+ # * <tt>package_width</tt> - a single packages width, only required if using YOUR_PACKAGING for packaging_type.
56
+ # * <tt>package_height</tt> - a single packages height, only required if using YOUR_PACKAGING for packaging_type.
57
+ # * <tt>package_dimension_units</tt> - either IN or CM. (default: IN)
58
+ #
59
+ # === Monetary options
60
+ #
61
+ # * <tt>currency_type</tt> - the type of currency. (default: nil, because FedEx will default to your account preferences)
62
+ # * <tt>insured_value</tt> - the value you want to insure, if any. (default: nil)
63
+ # * <tt>payment_type</tt> - one of Enumerations::PAYMENT_TYPES. (default: SENDER)
64
+ # * <tt>payor_account_number</tt> - if the account paying for this ship is different than the account you specified then
65
+ # you can specify that here. (default: your account number)
66
+ # * <tt>payor_country</tt> - the country code for the account number. (default: US)
67
+ #
68
+ # === Delivery options
69
+ #
70
+ # * <tt>ship_time</tt> - a Time object representing when you want to ship the package. (default: Time.now)
71
+ # * <tt>service_type</tt> - one of Enumerations::SERVICE_TYPES, this is optional, leave this blank if you want a list of all
72
+ # available services. (default: nil)
73
+ # * <tt>dropoff_type</tt> - one of Enumerations::DROP_OFF_TYPES. (default: REGULAR_PICKUP)
74
+ # * <tt>special_services_requested</tt> - any exceptions or special services FedEx needs to be aware of, this should be
75
+ # one or more of Enumerations::SPECIAL_SERVICES. (default: nil)
76
+ # * <tt>signature</tt> - one of Enumerations::SIGNATURE_OPTION_TYPES. (default: nil, which defaults to the service default)
77
+ #
78
+ # === Misc options
79
+ #
80
+ # * <tt>just_validate</tt> - will tell FedEx to ONLY validate the shipment, not actually create it. (default: false)
81
+ # * <tt>rate_request_types</tt> - one or more of Enumerations::RATE_REQUEST_TYPES. (default: ACCOUNT)
82
+ #
83
+ # == Simple Example
84
+ #
85
+ # Here is a very simple example. Mix and match the options above to get more accurate rates:
86
+ #
87
+ # fedex = Shippinglogic::FedEx.new(key, password, account, meter)
88
+ # shipment = fedex.ship(
89
+ # :shipper_postal_code => "10007",
90
+ # :shipper_country => "US",
91
+ # :recipient_postal_code => "75201",
92
+ # :recipient_country_code => "US",
93
+ # :package_weight => 24,
94
+ # :package_length => 12,
95
+ # :package_width => 12,
96
+ # :package_height => 12
97
+ # )
98
+ #
99
+ # shipment.inspect
100
+ # #<Shippinglogic::FedEx::Ship::Shipment rate:decimal, currency:string, delivery_date:date, tracking_number:string,
101
+ # label:string(base64 decoded), barcode:string(base64 decoded) >
102
+ #
103
+ # # to show accessor methods
104
+ # shipment.tracking_number
105
+ # # => "XXXXXXXXXXXXXX"
106
+ class Ship < Service
107
+ # The shipment result is an object of this class
108
+ class Shipment; attr_accessor :rate, :currency, :delivery_date, :tracking_number, :label, :barcode; end
109
+
110
+ VERSION = {:major => 6, :intermediate => 0, :minor => 0}
111
+
112
+ # shipper options
113
+ attribute :shipper_name, :string
114
+ attribute :shipper_title, :string
115
+ attribute :shipper_company_name, :string
116
+ attribute :shipper_phone_number, :string
117
+ attribute :shipper_email, :string
118
+ attribute :shipper_streets, :string
119
+ attribute :shipper_city, :string
120
+ attribute :shipper_state, :string
121
+ attribute :shipper_postal_code, :string
122
+ attribute :shipper_country, :string
123
+ attribute :shipper_residential, :boolean, :default => false
124
+
125
+ # recipient options
126
+ attribute :recipient_name, :string
127
+ attribute :recipient_title, :string
128
+ attribute :recipient_company_name, :string
129
+ attribute :recipient_phone_number, :string
130
+ attribute :recipient_email, :string
131
+ attribute :recipient_streets, :string
132
+ attribute :recipient_city, :string
133
+ attribute :recipient_state, :string
134
+ attribute :recipient_postal_code, :string
135
+ attribute :recipient_country, :string
136
+ attribute :recipient_residential, :boolean, :default => false
137
+
138
+ # label options
139
+ attribute :label_format, :string, :default => "COMMON2D"
140
+ attribute :label_file_type, :string, :default => "PDF"
141
+ attribute :label_stock_type, :string, :default => "PAPER_8.5X11_TOP_HALF_LABEL"
142
+
143
+ # packaging options
144
+ attribute :packaging_type, :string, :default => "YOUR_PACKAGING"
145
+ attribute :packaging_type, :string, :default => "YOUR_PACKAGING"
146
+ attribute :package_count, :integer, :default => 1
147
+ attribute :package_weight, :float
148
+ attribute :package_weight_units, :string, :default => "LB"
149
+ attribute :package_length, :integer
150
+ attribute :package_width, :integer
151
+ attribute :package_height, :integer
152
+ attribute :package_dimension_units, :string, :default => "IN"
153
+
154
+ # monetary options
155
+ attribute :currency_type, :string
156
+ attribute :insured_value, :decimal
157
+ attribute :payment_type, :string, :default => "SENDER"
158
+ attribute :payor_account_number, :string, :default => lambda { |shipment| shipment.base.account }
159
+ attribute :payor_country, :string
160
+
161
+ # delivery options
162
+ attribute :ship_time, :datetime, :default => lambda { |shipment| Time.now }
163
+ attribute :service_type, :string
164
+ attribute :dropoff_type, :string, :default => "REGULAR_PICKUP"
165
+ attribute :special_services_requested, :array
166
+ attribute :signature, :string
167
+
168
+ # misc options
169
+ attribute :just_validate, :boolean, :default => false
170
+ attribute :rate_request_types, :array, :default => ["ACCOUNT"]
171
+
172
+ private
173
+ def target
174
+ @target ||= parse_response(request(build_request))
175
+ end
176
+
177
+ # Just building some XML to send off to FedEx using our various options
178
+ def build_request
179
+ b = builder
180
+ xml = b.tag!(just_validate ? "ValidateShipmentRequest" : "ProcessShipmentRequest", :xmlns => "http://fedex.com/ws/ship/v#{VERSION[:major]}") do
181
+ build_authentication(b)
182
+ build_version(b, "ship", VERSION[:major], VERSION[:intermediate], VERSION[:minor])
183
+
184
+ b.RequestedShipment do
185
+ b.ShipTimestamp ship_time.xmlschema if ship_time
186
+ b.DropoffType dropoff_type if dropoff_type
187
+ b.ServiceType service_type if service_type
188
+ b.PackagingType packaging_type if packaging_type
189
+ build_insured_value(b)
190
+
191
+ b.Shipper do
192
+ build_contact(b, :shipper)
193
+ build_address(b, :shipper)
194
+ end
195
+
196
+ b.Recipient do
197
+ build_contact(b, :recipient)
198
+ build_address(b, :recipient)
199
+ end
200
+
201
+ b.ShippingChargesPayment do
202
+ b.PaymentType payment_type if payment_type
203
+ b.Payor do
204
+ b.AccountNumber payor_account_number if payor_account_number
205
+ b.CountryCode payor_country if payor_country
206
+ end
207
+ end
208
+
209
+ b.LabelSpecification do
210
+ b.LabelFormatType label_format if label_format
211
+ b.ImageType label_file_type if label_file_type
212
+ b.LabelStockType label_stock_type if label_stock_type
213
+ end
214
+
215
+ b.RateRequestTypes rate_request_types.join(",")
216
+ build_package(b)
217
+ end
218
+ end
219
+ end
220
+
221
+ # Making sense of the reponse and grabbing the information we need.
222
+ def parse_response(response)
223
+ details = response[:completed_shipment_detail]
224
+ rate = details[:shipment_rating][:shipment_rate_details].first[:total_net_charge]
225
+ package_details = details[:completed_package_details]
226
+
227
+ shipment = Shipment.new
228
+ shipment.rate = BigDecimal.new(rate[:amount])
229
+ shipment.currency = rate[:currency]
230
+ shipment.delivery_date = Date.parse(details[:routing_detail][:delivery_date])
231
+ shipment.tracking_number = package_details[:tracking_id][:tracking_number]
232
+ shipment.label = package_details[:label][:parts][:image] && Base64.decode64(package_details[:label][:parts][:image])
233
+ shipment.barcode = package_details[:barcodes][:common2_d_barcode] && Base64.decode64(package_details[:barcodes][:common2_d_barcode])
234
+ shipment
235
+ end
236
+ end
237
+ end
238
+ end
@@ -0,0 +1,68 @@
1
+ require "base64"
2
+
3
+ module Shippinglogic
4
+ class FedEx
5
+ # An interface to the signature proof of delivery services provided by FedEx. Allows you to get an image
6
+ # of the signature, or you can tell fedex to fax it to a fax number.
7
+ #
8
+ # == Accessor methods / options
9
+ #
10
+ # * <tt>tracking_number</tt> - the tracking number
11
+ # * <tt>image_type</tt> - one of Enumerations::SIGNATURE_IMAGE_TYPES. (default: LETTER)
12
+ # * <tt>image_file_type</tt> - one of Enumerations::LABEL_FILE_TYPES. (default: PDF)
13
+ # * <tt>fax_number</tt> - if image_type is set to FAX you must provide a fax number here. (default: nil)
14
+ #
15
+ # === Simple Example
16
+ #
17
+ # Here is a very simple example:
18
+ #
19
+ # fedex = Shippinglogic::FedEx.new(key, password, account, meter)
20
+ # signature = fedex.signature(:tracking_number => "my number")
21
+ #
22
+ # signature.inspect
23
+ # # => #<Shippinglogic::FedEx::Signature::Signature image:string(base64 decoded) >
24
+ #
25
+ # signature.image
26
+ # # => "a bunch of garble (write this to a file and save it)"
27
+ class Signature < Service
28
+ # Each tracking result is an object of this class
29
+ class Signature; attr_accessor :image; end
30
+
31
+ VERSION = {:major => 3, :intermediate => 0, :minor => 0}
32
+
33
+ attribute :image_type, :string, :default => "LETTER"
34
+ attribute :image_file_type, :string, :default => "PDF"
35
+ attribute :tracking_number, :string
36
+ attribute :fax_number, :string
37
+
38
+ private
39
+ # The parent class Service requires that we define this method. This is our kicker. This method is only
40
+ # called when we need to deal with information from FedEx. Notice the caching into the @target variable.
41
+ def target
42
+ @target ||= parse_response(request(build_request))
43
+ end
44
+
45
+ # Just building some XML to send off to FedEx. FedEx require this particualr format.
46
+ def build_request
47
+ b = builder
48
+ xml = b.SignatureProofOfDeliveryRequest(:xmlns => "http://fedex.com/ws/track/v#{VERSION[:major]}") do
49
+ build_authentication(b)
50
+ build_version(b, "trck", VERSION[:major], VERSION[:intermediate], VERSION[:minor])
51
+
52
+ b.Type image_type
53
+ b.TrackingNumber tracking_number
54
+ b.FaxDetail fax_number if fax_number
55
+ b.LetterFormat image_file_type
56
+ end
57
+ end
58
+
59
+ # Grabbing the response from FedEx and making sense of it. There is a lot of unneeded information
60
+ # in the response.
61
+ def parse_response(response)
62
+ signature = Signature.new
63
+ signature.image = response[:letter] && Base64.decode64(response[:letter])
64
+ signature
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,124 @@
1
+ module Shippinglogic
2
+ class FedEx
3
+ # An interface to the track services provided by FedEx. Allows you to get an array of events for a specific
4
+ # tracking number.
5
+ #
6
+ # == Accessor methods / options
7
+ #
8
+ # * <tt>tracking_number</tt> - the tracking number
9
+ #
10
+ # === Simple Example
11
+ #
12
+ # Here is a very simple example:
13
+ #
14
+ # fedex = Shippinglogic::FedEx.new(key, password, account, meter)
15
+ # tracking_details = fedex.track(:tracking_number => "my number")
16
+ #
17
+ # tracking.status
18
+ # # => "Delivered"
19
+ #
20
+ # tracking.signature_name
21
+ # # => "KKING"
22
+ #
23
+ # tracking.events.first
24
+ # # => #<Shippinglogic::FedEx::Track::Event @postal_code="95817", @name="Delivered", @state="CA", @residential=false,
25
+ # # @city="Sacramento", @type="DL", @country="US", @occured_at=Mon Dec 08 10:43:37 -0500 2008>
26
+ #
27
+ # tracking.events.first.name
28
+ # # => "Delivered"
29
+ #
30
+ # === Note
31
+ #
32
+ # FedEx does support locating packages through means other than a tracking number.
33
+ # These are not supported and probably won't be until someone needs them. It should
34
+ # be fairly simple to add, but I could not think of a reason why anyone would want to track
35
+ # a package with anything other than a tracking number.
36
+ class Track < Service
37
+ class Details
38
+ # Each tracking result is an object of this class
39
+ class Event; attr_accessor :name, :type, :occured_at, :city, :state, :postal_code, :country, :residential; end
40
+
41
+ attr_accessor :origin_city,
42
+ :origin_state,
43
+ :origin_country,
44
+ :origin_residential,
45
+ :destination_city,
46
+ :destination_state,
47
+ :destination_country,
48
+ :destination_residential,
49
+ :signature_name,
50
+ :service_type,
51
+ :status,
52
+ :delivery_at,
53
+ :events
54
+
55
+ def origin_residential?
56
+ origin_residential == true
57
+ end
58
+
59
+ def destination_residential?
60
+ destination_residential == true
61
+ end
62
+
63
+ def initialize(response)
64
+ details = response[:track_details]
65
+
66
+ self.origin_city = details[:origin_location_address][:city]
67
+ self.origin_state = details[:origin_location_address][:state_or_province_code]
68
+ self.origin_country = details[:origin_location_address][:country_code]
69
+ self.origin_residential = details[:origin_location_address][:residential] == "true"
70
+
71
+ self.destination_city = details[:destination_address][:city]
72
+ self.destination_state = details[:destination_address][:state_or_province_code]
73
+ self.destination_country = details[:destination_address][:country_code]
74
+ self.destination_residential = details[:destination_address][:residential] == "true"
75
+
76
+ self.signature_name = details[:delivery_signature_name]
77
+ self.service_type = details[:service_type]
78
+ self.status = details[:status_description]
79
+ self.delivery_at = Time.parse(details[:actual_delivery_timestamp])
80
+
81
+ self.events = response[:track_details][:events].collect do |details|
82
+ event = Event.new
83
+ event.name = details[:event_description]
84
+ event.type = details[:event_type]
85
+ event.occured_at = Time.parse(details[:timestamp])
86
+ event.city = details[:address][:city]
87
+ event.state = details[:address][:state_or_province_code]
88
+ event.postal_code = details[:address][:postal_code]
89
+ event.country = details[:address][:country_code]
90
+ event.residential = details[:address][:residential] == "true"
91
+ event
92
+ end
93
+ end
94
+ end
95
+
96
+ VERSION = {:major => 3, :intermediate => 0, :minor => 0}
97
+
98
+ attribute :tracking_number, :string
99
+
100
+ private
101
+ # The parent class Service requires that we define this method. This is our kicker. This method is only
102
+ # called when we need to deal with information from FedEx. Notice the caching into the @target variable.
103
+ def target
104
+ @target ||= Details.new(request(build_request))
105
+ end
106
+
107
+ # Just building some XML to send off to FedEx. FedEx require this particualr format.
108
+ def build_request
109
+ b = builder
110
+ xml = b.TrackRequest(:xmlns => "http://fedex.com/ws/track/v#{VERSION[:major]}") do
111
+ build_authentication(b)
112
+ build_version(b, "trck", VERSION[:major], VERSION[:intermediate], VERSION[:minor])
113
+
114
+ b.PackageIdentifier do
115
+ b.Value tracking_number
116
+ b.Type "TRACKING_NUMBER_OR_DOORTAG"
117
+ end
118
+
119
+ b.IncludeDetailedScans true
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,23 @@
1
+ module Shippinglogic
2
+ class Proxy
3
+ alias_method :real_class, :class
4
+ instance_methods.each do |m|
5
+ if (m =~ /^(__|respond_to_missing\?|real_class$|send$|object_id|respond_to\?$)/).nil?
6
+ undef_method(m)
7
+ end
8
+ end
9
+
10
+ attr_accessor :target
11
+
12
+ def initialize(target)
13
+ self.target = target
14
+ end
15
+
16
+ protected
17
+ # We undefined a lot of methods at the beginning of this class. The only methods present in this
18
+ # class are ones that we need, everything else is delegated to our target object.
19
+ def method_missing(name, *args, &block)
20
+ target.send(name, *args, &block)
21
+ end
22
+ end
23
+ end