shippinglogic 1.2.3

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 (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