simple_shipping 0.4.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.metrics +6 -0
- data/.rspec +4 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.simplecov +43 -0
- data/Gemfile +26 -0
- data/Gemfile.lock +201 -0
- data/LICENSE.txt +21 -0
- data/README.markdown +207 -0
- data/Rakefile +68 -0
- data/VERSION +1 -0
- data/coverage/.resultset.json +1579 -0
- data/lib/colorized_text.rb +34 -0
- data/lib/simple_shipping.rb +27 -0
- data/lib/simple_shipping/abstract.rb +11 -0
- data/lib/simple_shipping/abstract/builder.rb +47 -0
- data/lib/simple_shipping/abstract/client.rb +111 -0
- data/lib/simple_shipping/abstract/model.rb +40 -0
- data/lib/simple_shipping/abstract/request.rb +27 -0
- data/lib/simple_shipping/abstract/response.rb +26 -0
- data/lib/simple_shipping/address.rb +22 -0
- data/lib/simple_shipping/contact.rb +24 -0
- data/lib/simple_shipping/demo.rb +9 -0
- data/lib/simple_shipping/demo/base.rb +71 -0
- data/lib/simple_shipping/demo/fedex.rb +46 -0
- data/lib/simple_shipping/demo/ups.rb +68 -0
- data/lib/simple_shipping/exceptions.rb +40 -0
- data/lib/simple_shipping/fedex.rb +14 -0
- data/lib/simple_shipping/fedex/client.rb +41 -0
- data/lib/simple_shipping/fedex/package_builder.rb +24 -0
- data/lib/simple_shipping/fedex/party_builder.rb +50 -0
- data/lib/simple_shipping/fedex/request.rb +54 -0
- data/lib/simple_shipping/fedex/response.rb +5 -0
- data/lib/simple_shipping/fedex/shipment_builder.rb +123 -0
- data/lib/simple_shipping/fedex/shipment_request.rb +14 -0
- data/lib/simple_shipping/fedex/shipment_response.rb +12 -0
- data/lib/simple_shipping/package.rb +43 -0
- data/lib/simple_shipping/party.rb +21 -0
- data/lib/simple_shipping/shipment.rb +42 -0
- data/lib/simple_shipping/ups.rb +24 -0
- data/lib/simple_shipping/ups/client.rb +46 -0
- data/lib/simple_shipping/ups/package_builder.rb +101 -0
- data/lib/simple_shipping/ups/party_builder.rb +38 -0
- data/lib/simple_shipping/ups/request.rb +27 -0
- data/lib/simple_shipping/ups/response.rb +63 -0
- data/lib/simple_shipping/ups/ship_accept_request.rb +21 -0
- data/lib/simple_shipping/ups/ship_accept_response.rb +6 -0
- data/lib/simple_shipping/ups/ship_client.rb +70 -0
- data/lib/simple_shipping/ups/ship_confirm_request.rb +22 -0
- data/lib/simple_shipping/ups/ship_confirm_response.rb +6 -0
- data/lib/simple_shipping/ups/shipment_builder.rb +66 -0
- data/lib/simple_shipping/ups/shipment_request.rb +22 -0
- data/lib/simple_shipping/ups/shipment_response.rb +6 -0
- data/lib/simple_shipping/ups/void_client.rb +50 -0
- data/lib/simple_shipping/ups/void_request.rb +42 -0
- data/lib/simple_shipping/ups/void_response.rb +6 -0
- data/lib/tasks/demo.rake +58 -0
- data/script/ups_certification.rb +140 -0
- data/simple_shipping.gemspec +168 -0
- data/spec/fixtures/fedex_shipment_request.soap.xml.erb +85 -0
- data/spec/fixtures/fedex_shipment_response.soap.xml.erb +182 -0
- data/spec/fixtures/ups_shipment_request.soap.xml.erb +88 -0
- data/spec/fixtures/ups_shipment_response.soap.xml.erb +58 -0
- data/spec/fixtures/ups_shipment_response_with_faked_label_data.soap.xml.erb +54 -0
- data/spec/fixtures/ups_void_request.soap.xml.erb +29 -0
- data/spec/fixtures/ups_void_response.soap.xml.erb +21 -0
- data/spec/lib/simple_shipping/address_spec.rb +19 -0
- data/spec/lib/simple_shipping/contact_spec.rb +28 -0
- data/spec/lib/simple_shipping/exceptions_spec.rb +58 -0
- data/spec/lib/simple_shipping/fedex/package_builder_spec.rb +5 -0
- data/spec/lib/simple_shipping/fedex/party_builder_spec.rb +5 -0
- data/spec/lib/simple_shipping/fedex/response/shipment_reponse_spec.rb +5 -0
- data/spec/lib/simple_shipping/fedex/response_spec.rb +5 -0
- data/spec/lib/simple_shipping/fedex/shipment_builder_spec.rb +23 -0
- data/spec/lib/simple_shipping/package_spec.rb +32 -0
- data/spec/lib/simple_shipping/party_spec.rb +18 -0
- data/spec/lib/simple_shipping/shipment_spec.rb +35 -0
- data/spec/lib/simple_shipping/ups/package_builder_spec.rb +26 -0
- data/spec/lib/simple_shipping/ups/party_builder_spec.rb +47 -0
- data/spec/lib/simple_shipping/ups/response/shipment_response_spec.rb +5 -0
- data/spec/lib/simple_shipping/ups/response_spec.rb +33 -0
- data/spec/lib/simple_shipping/ups/shipment_builder_spec.rb +19 -0
- data/spec/requests/fedex_spec.rb +47 -0
- data/spec/requests/ups_spec.rb +75 -0
- data/spec/spec_helper.rb +47 -0
- data/spec/support/custom_matchers/basic_matcher.rb +13 -0
- data/spec/support/custom_matchers/have_attribute_matcher.rb +22 -0
- data/spec/support/custom_matchers/have_default_value_matcher.rb +26 -0
- data/spec/support/custom_matchers/have_errors_on_matcher.rb +23 -0
- data/spec/support/custom_matchers/validate_inclusion_of_matcher.rb +37 -0
- data/spec/support/custom_matchers/validate_presence_of_matcher.rb +24 -0
- data/spec/support/custom_matchers/validate_submodel_matcher.rb +44 -0
- data/spec/support/shared_behaviours/builders_behaviour.rb +9 -0
- data/spec/support/shared_behaviours/responses_behaviour.rb +10 -0
- data/tmp/metric_fu/_data/20131210.yml +9964 -0
- data/wsdl/fedex/ship_service_v10.wsdl +5566 -0
- data/wsdl/ups/Ship.wsdl +120 -0
- data/wsdl/ups/Void.wsdl +58 -0
- metadata +308 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
# Colorizes text with ASCII colors.
|
2
|
+
#
|
3
|
+
# @example
|
4
|
+
# include ColorizedText
|
5
|
+
#
|
6
|
+
# puts green "OK" # => green output
|
7
|
+
# puts bold "Running... # => bold output
|
8
|
+
# puts bold green "OK!!!" # => bold green output
|
9
|
+
module ColorizedText
|
10
|
+
# Colorize text using ASCII color code
|
11
|
+
def colorize(text, code)
|
12
|
+
"\033[#{code}m#{text}\033[0m"
|
13
|
+
end
|
14
|
+
|
15
|
+
# :nodoc:
|
16
|
+
def yellow(text)
|
17
|
+
colorize(text, 33)
|
18
|
+
end
|
19
|
+
|
20
|
+
# :nodoc:
|
21
|
+
def green(text)
|
22
|
+
colorize(text, 32)
|
23
|
+
end
|
24
|
+
|
25
|
+
# :nodoc:
|
26
|
+
def red(text)
|
27
|
+
colorize(text, 31)
|
28
|
+
end
|
29
|
+
|
30
|
+
# :nodoc:
|
31
|
+
def bold(text)
|
32
|
+
colorize(text, 1)
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'active_support/core_ext'
|
2
|
+
require 'active_model'
|
3
|
+
require 'savon'
|
4
|
+
require 'ostruct'
|
5
|
+
|
6
|
+
|
7
|
+
# Namespace for SimpleShipping library.
|
8
|
+
module SimpleShipping
|
9
|
+
extend ActiveSupport::Autoload
|
10
|
+
|
11
|
+
# Path to the directory with WDSL files.
|
12
|
+
WSDL_DIR = File.expand_path("../../wsdl", __FILE__)
|
13
|
+
|
14
|
+
autoload :Abstract
|
15
|
+
autoload :Address
|
16
|
+
autoload :Contact
|
17
|
+
autoload :Demo
|
18
|
+
autoload :Package
|
19
|
+
autoload :Party
|
20
|
+
autoload :Shipment
|
21
|
+
|
22
|
+
autoload :Ups
|
23
|
+
autoload :Fedex
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
require 'simple_shipping/exceptions'
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Namespace for the abstract classes that define common interface for all
|
2
|
+
# shipping providers.
|
3
|
+
module SimpleShipping::Abstract
|
4
|
+
extend ActiveSupport::Autoload
|
5
|
+
|
6
|
+
autoload :Response
|
7
|
+
autoload :Model
|
8
|
+
autoload :Builder
|
9
|
+
autoload :Client
|
10
|
+
autoload :Request
|
11
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module SimpleShipping
|
2
|
+
# Kind of an abstract class which should be used to create model builders.
|
3
|
+
# Model builder "knows" how to represent its model for a its service.
|
4
|
+
# This class provides only common skeleton for subclasses.
|
5
|
+
class Abstract::Builder
|
6
|
+
class_attribute :default_opts
|
7
|
+
|
8
|
+
# == Parameters:
|
9
|
+
# model - kind of {Abstract::Model}
|
10
|
+
# opts - hash of options. Every builder can have its own specific set of options
|
11
|
+
# == Returns:
|
12
|
+
# Hash which can be used by Savon to build a part of SOAP request.
|
13
|
+
def self.build(model, opts = {})
|
14
|
+
raise(ValidationError.new(model)) unless model.valid?
|
15
|
+
|
16
|
+
builder = self.new(model, opts)
|
17
|
+
builder.validate
|
18
|
+
builder.build
|
19
|
+
end
|
20
|
+
|
21
|
+
# Allows to set default option values is subclasses.
|
22
|
+
def self.set_default_opts(opts = {})
|
23
|
+
self.default_opts = opts
|
24
|
+
end
|
25
|
+
|
26
|
+
# Should be implemented by subclasses. But by default returns empty hash.
|
27
|
+
def build; {}; end
|
28
|
+
|
29
|
+
# Should be implemented by subclass if subclass needs to do some validation.
|
30
|
+
def validate; end
|
31
|
+
|
32
|
+
def initialize(model = nil, opts = {})
|
33
|
+
self.default_opts ||= {}
|
34
|
+
@opts = default_opts.merge(opts)
|
35
|
+
@model = model
|
36
|
+
end
|
37
|
+
private :initialize
|
38
|
+
|
39
|
+
# Raises {ValidationError} if option has invalid value.
|
40
|
+
def validate_inclusion_of(option, enumeration)
|
41
|
+
unless enumeration.has_key?(@opts[option])
|
42
|
+
raise ValidationError.new("#{option} has an unavailable value(#{@opts[option]}). Available values are #{enumeration.keys.inspect}")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
private :validate_inclusion_of
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module SimpleShipping
|
2
|
+
# Abstract class which provides common interfaces for the next concrete clients:
|
3
|
+
# * {Fedex::Client}
|
4
|
+
# * {Ups::Client}
|
5
|
+
class Abstract::Client
|
6
|
+
class_attribute :required_credentials,
|
7
|
+
:wsdl_document,
|
8
|
+
:production_address,
|
9
|
+
:testing_address
|
10
|
+
|
11
|
+
# Set credentials which should be validated.
|
12
|
+
def self.set_required_credentials(*args)
|
13
|
+
self.required_credentials = args
|
14
|
+
end
|
15
|
+
|
16
|
+
# Set the WSDL document used by Savon.
|
17
|
+
def self.set_wsdl_document(wsdl_path)
|
18
|
+
self.wsdl_document = wsdl_path
|
19
|
+
end
|
20
|
+
|
21
|
+
# Set the production endpoint.
|
22
|
+
#
|
23
|
+
# @param address [String]
|
24
|
+
def self.set_production_address(address)
|
25
|
+
self.production_address = address
|
26
|
+
end
|
27
|
+
|
28
|
+
# Set the testing endpoint.
|
29
|
+
#
|
30
|
+
# @param address [String]
|
31
|
+
def self.set_testing_address(address)
|
32
|
+
self.testing_address = address
|
33
|
+
end
|
34
|
+
|
35
|
+
# Create an instance of a client.
|
36
|
+
# == Parameters:
|
37
|
+
# * credentials - a hash with credentials.
|
38
|
+
def initialize(options)
|
39
|
+
@options = options.dup
|
40
|
+
@live = options.delete(:live)
|
41
|
+
@debug = options.delete(:debug)
|
42
|
+
@debug_path = options.delete(:debug_path)
|
43
|
+
credentials = options.delete(:credentials)
|
44
|
+
|
45
|
+
validate_credentials(credentials)
|
46
|
+
@credentials = OpenStruct.new(credentials)
|
47
|
+
|
48
|
+
@client = Savon.client(client_options(options))
|
49
|
+
end
|
50
|
+
|
51
|
+
# @param [Hash] options Savon client options
|
52
|
+
# @return [Hash{Symbol => Object}] Savon client options
|
53
|
+
def client_options(options = {})
|
54
|
+
endpoint = @live ? self.class.production_address : self.class.testing_address
|
55
|
+
|
56
|
+
options.symbolize_keys.reverse_merge(
|
57
|
+
:wsdl => wsdl_document,
|
58
|
+
:endpoint => endpoint
|
59
|
+
)
|
60
|
+
end
|
61
|
+
protected :client_options
|
62
|
+
|
63
|
+
|
64
|
+
# Validate that all required credentials are passed.
|
65
|
+
def validate_credentials(credentials)
|
66
|
+
credentials.assert_valid_keys(required_credentials)
|
67
|
+
missing = required_credentials - credentials.keys
|
68
|
+
raise(Error.new "The next credentials are missing for #{self}: #{missing.join(', ')}") unless missing.empty?
|
69
|
+
end
|
70
|
+
private :validate_credentials
|
71
|
+
|
72
|
+
# Build the {Shipment shipment} model.
|
73
|
+
def create_shipment(shipper, recipient, package, opts = {})
|
74
|
+
shipment = SimpleShipping::Shipment.new(
|
75
|
+
:shipper => shipper,
|
76
|
+
:recipient => recipient,
|
77
|
+
:package => package)
|
78
|
+
shipment.payor = opts[:payor] if opts[:payor]
|
79
|
+
shipment
|
80
|
+
end
|
81
|
+
private :create_shipment
|
82
|
+
|
83
|
+
# Write the request information to request.xml.
|
84
|
+
#
|
85
|
+
# @param soap [Savon::HTTPRequest]
|
86
|
+
def log_request(soap)
|
87
|
+
log_soap("request", soap)
|
88
|
+
end
|
89
|
+
private :log_request
|
90
|
+
|
91
|
+
# Write the response information to response.xml.
|
92
|
+
#
|
93
|
+
# @param [Savon::Response] soap
|
94
|
+
def log_response(soap)
|
95
|
+
log_soap("response", soap)
|
96
|
+
end
|
97
|
+
private :log_response
|
98
|
+
|
99
|
+
# Write the request/response to .xml file.
|
100
|
+
#
|
101
|
+
# @param name [String] file name without .xml
|
102
|
+
# @param soap [Savon::HTTPRequest, Savon::Response]
|
103
|
+
def log_soap(name, soap)
|
104
|
+
if @debug
|
105
|
+
path = File.join(@debug_path, "#{name}.xml")
|
106
|
+
File.open(path, 'w') {|f| f.write soap.to_xml}
|
107
|
+
end
|
108
|
+
end
|
109
|
+
private :log_soap
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module SimpleShipping
|
2
|
+
# Base class for all simple shipping models.
|
3
|
+
class Abstract::Model
|
4
|
+
include ActiveModel::Validations
|
5
|
+
|
6
|
+
# hash with default attribute values
|
7
|
+
class_attribute :default_values
|
8
|
+
|
9
|
+
# Define the default values of the attributes which should be set when the model is created.
|
10
|
+
def self.set_default_values(values = {})
|
11
|
+
self.default_values = values
|
12
|
+
end
|
13
|
+
|
14
|
+
# Add a validation callback to validate the submodel. Submodel is a model
|
15
|
+
# which belongs to current model.
|
16
|
+
# == Parameters:
|
17
|
+
# * name - name of attribute which is submodel
|
18
|
+
# * opts - hash with only on key :as. It should points to class of submodel.
|
19
|
+
def self.validates_submodel(name, opts = {})
|
20
|
+
validate do
|
21
|
+
klass = opts[:as] || raise(":as option should be passed")
|
22
|
+
submodel = send(name)
|
23
|
+
if !submodel.instance_of?(klass)
|
24
|
+
errors.add(name.to_sym, "must be an instance of #{klass.inspect}")
|
25
|
+
elsif submodel.invalid?
|
26
|
+
errors.add(name.to_sym, "is invalid")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Create a new model and set the default and passed values.
|
32
|
+
def initialize(values = {})
|
33
|
+
values.reverse_merge!(default_values || {})
|
34
|
+
values.each do |attribute, value|
|
35
|
+
raise("Undefined attribute `#{attribute}` for #{self}") unless respond_to?(attribute)
|
36
|
+
send("#{attribute}=", value)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module SimpleShipping
|
2
|
+
# Base class for request builders. Every service has its own implementation.
|
3
|
+
class Abstract::Request
|
4
|
+
attr_reader :credentials
|
5
|
+
attr_reader :type
|
6
|
+
|
7
|
+
def initialize(credentials)
|
8
|
+
@credentials = credentials
|
9
|
+
end
|
10
|
+
|
11
|
+
# Wrap the Savon response with specific response for shipment provider.
|
12
|
+
#
|
13
|
+
# @param savon_response [Savon::Response]
|
14
|
+
#
|
15
|
+
# @return [SimpleShipping::Abstract::Response]
|
16
|
+
def response(savon_response)
|
17
|
+
response_class.new(savon_response)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Response class to wrap Savon response.
|
21
|
+
#
|
22
|
+
# @return [Class]
|
23
|
+
def response_class
|
24
|
+
Response
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module SimpleShipping
|
2
|
+
# Represents a response returned by the remote service for a request initiated
|
3
|
+
# by {SimpleShipping::Abstract::Client client}.
|
4
|
+
#
|
5
|
+
# An abstract class which provides a common interface.
|
6
|
+
# In the real world, you will deal with its subclasses:
|
7
|
+
# * {SimpleShipping::Fedex::Response}
|
8
|
+
# * {SimpleShipping::Ups::Response}
|
9
|
+
#
|
10
|
+
# == Example:
|
11
|
+
# response = client.request(shipper, recipient, package)
|
12
|
+
# response.response # => #<Savon::SOAP::Response ...>
|
13
|
+
class Abstract::Response
|
14
|
+
attr_reader :response
|
15
|
+
|
16
|
+
def initialize(savon_resp = nil)
|
17
|
+
@response = savon_resp
|
18
|
+
end
|
19
|
+
|
20
|
+
# Fetch the value of an XML attribute at the path specified as an array.
|
21
|
+
# of node names
|
22
|
+
def value_of(*path)
|
23
|
+
@response.to_array(*path).first
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module SimpleShipping
|
2
|
+
# Represents an address information of {SimpleShipping::Party party}.
|
3
|
+
# == Attributes:
|
4
|
+
# * _country_code_
|
5
|
+
# * _state_code_
|
6
|
+
# * _city_
|
7
|
+
# * _street_line_
|
8
|
+
# * _street_line_2_
|
9
|
+
# * _street_line_3_
|
10
|
+
# * _postal_code_
|
11
|
+
class Address < Abstract::Model
|
12
|
+
attr_accessor :country_code,
|
13
|
+
:state_code,
|
14
|
+
:city,
|
15
|
+
:street_line,
|
16
|
+
:street_line_2,
|
17
|
+
:street_line_3,
|
18
|
+
:postal_code
|
19
|
+
|
20
|
+
validates_presence_of :country_code, :state_code, :city, :street_line, :postal_code
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module SimpleShipping
|
2
|
+
# Represents the contact information of the {SimpleShipping::Party party} who takes
|
3
|
+
# part in shipment process.
|
4
|
+
#
|
5
|
+
# == Attributes
|
6
|
+
# * _person_name_ (optional if company_name is provided)
|
7
|
+
# * _company_name_ (optional if person_name is provided)
|
8
|
+
# * _phone_number_
|
9
|
+
# * _email_ (optional)
|
10
|
+
class Contact < Abstract::Model
|
11
|
+
attr_accessor :person_name,
|
12
|
+
:company_name,
|
13
|
+
:phone_number,
|
14
|
+
:email
|
15
|
+
|
16
|
+
validates_presence_of :phone_number
|
17
|
+
validate :validate_name
|
18
|
+
|
19
|
+
# Validate presence of person or company name.
|
20
|
+
def validate_name
|
21
|
+
errors.add(:abstract, "person_name or company_name must be present") unless (person_name || company_name)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# Namespace for demo rake tasks used to test real remote requests by sending
|
2
|
+
# test requests to verify credentials. Not intended for runtime use.
|
3
|
+
class SimpleShipping::Demo
|
4
|
+
extend ActiveSupport::Autoload
|
5
|
+
|
6
|
+
autoload :Fedex
|
7
|
+
autoload :Ups
|
8
|
+
autoload :Base
|
9
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# Base class for UPS and FedEx demos.
|
2
|
+
class SimpleShipping::Demo::Base
|
3
|
+
attr_reader :options
|
4
|
+
|
5
|
+
# Build the shipper address with random attributes.
|
6
|
+
#
|
7
|
+
# @return [SimpleShipping::Address]
|
8
|
+
def shipper_address
|
9
|
+
@shipper_address ||= SimpleShipping::Address.new(
|
10
|
+
:country_code => 'US',
|
11
|
+
:state_code => 'TX',
|
12
|
+
:city => 'Texas',
|
13
|
+
:street_line => 'SN2000 Test Meter 8',
|
14
|
+
:postal_code => '73301'
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Build the shipper contact object.
|
19
|
+
#
|
20
|
+
# @return [SimpleShipping::Contact]
|
21
|
+
def shipper_contact
|
22
|
+
@shipper_contact ||= SimpleShipping::Contact.new(
|
23
|
+
:person_name => 'Mister Someone',
|
24
|
+
:phone_number => '1234567890'
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Build the shipper object.
|
29
|
+
#
|
30
|
+
# @return [SimpleShipping::Party]
|
31
|
+
def shipper
|
32
|
+
@shipper ||= SimpleShipping::Party.new(
|
33
|
+
:address => shipper_address,
|
34
|
+
:contact => shipper_contact,
|
35
|
+
:account_number => options[:account_number]
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Build the recipient address with random attributes.
|
40
|
+
#
|
41
|
+
# @return [SimpleShipping::Address]
|
42
|
+
def recipient_address
|
43
|
+
@recipient_address ||= SimpleShipping::Address.new(
|
44
|
+
:country_code => 'US',
|
45
|
+
:state_code => 'MN',
|
46
|
+
:city => 'Minneapolis',
|
47
|
+
:street_line => 'Nightmare Avenue 13',
|
48
|
+
:postal_code => '55411'
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Build the recipient contact.
|
53
|
+
#
|
54
|
+
# @return [SimpleShipping::Contact]
|
55
|
+
def recipient_contact
|
56
|
+
@recipient_contact ||= SimpleShipping::Contact.new(
|
57
|
+
:person_name => "John Recipient Smith",
|
58
|
+
:phone_number => "1234567890"
|
59
|
+
)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Build the recipient object.
|
63
|
+
#
|
64
|
+
# @return [SimpleShipping::Party]
|
65
|
+
def recipient
|
66
|
+
@recipient ||= SimpleShipping::Party.new(
|
67
|
+
:address => recipient_address,
|
68
|
+
:contact => recipient_contact
|
69
|
+
)
|
70
|
+
end
|
71
|
+
end
|