easypost 3.4.0 → 4.1.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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +19 -5
  3. data/.gitignore +2 -0
  4. data/.rubocop.yml +5 -0
  5. data/CHANGELOG.md +149 -138
  6. data/Gemfile +2 -0
  7. data/README.md +51 -8
  8. data/Rakefile +2 -1
  9. data/UPGRADE_GUIDE.md +62 -0
  10. data/VERSION +1 -1
  11. data/bin/easypost-irb +5 -3
  12. data/easycop.yml +180 -0
  13. data/easypost.gemspec +21 -19
  14. data/lib/easypost/address.rb +26 -26
  15. data/lib/easypost/api_key.rb +3 -0
  16. data/lib/easypost/batch.rb +31 -30
  17. data/lib/easypost/brand.rb +13 -0
  18. data/lib/easypost/carrier_account.rb +4 -0
  19. data/lib/easypost/carrier_type.rb +3 -0
  20. data/lib/easypost/connection.rb +67 -0
  21. data/lib/easypost/customs_info.rb +5 -1
  22. data/lib/easypost/customs_item.rb +5 -1
  23. data/lib/easypost/error.rb +7 -7
  24. data/lib/easypost/event.rb +5 -1
  25. data/lib/easypost/insurance.rb +4 -0
  26. data/lib/easypost/object.rb +44 -28
  27. data/lib/easypost/order.rb +15 -11
  28. data/lib/easypost/parcel.rb +7 -0
  29. data/lib/easypost/pickup.rb +15 -9
  30. data/lib/easypost/pickup_rate.rb +3 -1
  31. data/lib/easypost/postage_label.rb +3 -0
  32. data/lib/easypost/rate.rb +7 -0
  33. data/lib/easypost/refund.rb +3 -0
  34. data/lib/easypost/report.rb +9 -16
  35. data/lib/easypost/resource.rb +55 -25
  36. data/lib/easypost/scan_form.rb +8 -3
  37. data/lib/easypost/shipment.rb +47 -51
  38. data/lib/easypost/tax_identifier.rb +6 -0
  39. data/lib/easypost/tracker.rb +9 -4
  40. data/lib/easypost/user.rb +31 -10
  41. data/lib/easypost/util.rb +22 -17
  42. data/lib/easypost/version.rb +3 -1
  43. data/lib/easypost/webhook.rb +18 -12
  44. data/lib/easypost.rb +99 -107
  45. metadata +80 -22
  46. data/lib/easypost/print_job.rb +0 -2
  47. data/lib/easypost/printer.rb +0 -24
@@ -1,12 +1,17 @@
1
- require "set"
1
+ # frozen_string_literal: true
2
2
 
3
+ require 'set'
4
+
5
+ # The EasyPostObject is extended by the EasyPost Resource object.
3
6
  class EasyPost::EasyPostObject
4
7
  include Enumerable
5
8
 
6
9
  attr_accessor :parent, :name, :api_key, :unsaved_values
7
- @@immutable_values = Set.new([:api_key, :id])
8
10
 
9
- def initialize(id=nil, api_key=nil, parent=nil, name=nil)
11
+ @@immutable_values = Set.new([:api_key, :id]) # rubocop:disable Style/ClassVars
12
+
13
+ # Initialize an EasyPostObject.
14
+ def initialize(id = nil, api_key = nil, parent = nil, name = nil)
10
15
  @api_key = api_key
11
16
  @values = {}
12
17
  @unsaved_values = Set.new
@@ -16,22 +21,26 @@ class EasyPost::EasyPostObject
16
21
  self.id = id if id
17
22
  end
18
23
 
19
- def self.construct_from(values, api_key=nil, parent=nil, name=nil)
20
- obj = self.new(values[:id], api_key, parent, name)
24
+ # Construct an object from values.
25
+ def self.construct_from(values, api_key = nil, parent = nil, name = nil)
26
+ obj = new(values[:id], api_key, parent, name)
21
27
  obj.refresh_from(values, api_key)
22
28
  obj
23
29
  end
24
30
 
25
- def to_s(*args)
31
+ # Convert to a string.
32
+ def to_s(*_args)
26
33
  JSON.dump(@values)
27
34
  end
28
35
 
36
+ # Inspect JSON.
29
37
  def inspect
30
- id_string = (self.respond_to?(:id) && !self.id.nil?) ? " id=#{self.id}" : ""
38
+ id_string = respond_to?(:id) && !id.nil? ? " id=#{id}" : ''
31
39
  "#<#{self.class}:#{id_string}> JSON: " + to_json
32
40
  end
33
41
 
34
- def refresh_from(values, api_key, partial=false)
42
+ # Refresh an object from the API.
43
+ def refresh_from(values, api_key)
35
44
  @api_key = api_key
36
45
 
37
46
  added = Set.new(values.keys - @values.keys)
@@ -40,6 +49,9 @@ class EasyPost::EasyPostObject
40
49
  add_accessors(added)
41
50
  end
42
51
 
52
+ # IDs don't change, do not update it
53
+ @values.delete(:id)
54
+
43
55
  values.each do |k, v|
44
56
  @values[k.to_s] = EasyPost::Util.convert_to_easypost_object(v, api_key, self, k)
45
57
  @transient_values.delete(k)
@@ -47,55 +59,67 @@ class EasyPost::EasyPostObject
47
59
  end
48
60
  end
49
61
 
50
- def [](k)
51
- @values[k.to_s]
62
+ # Get element of an array.
63
+ def [](key)
64
+ @values[key.to_s]
52
65
  end
53
66
 
54
- def []=(k, v)
55
- send(:"#{k}=", v)
67
+ # Set the element of an array.
68
+ def []=(key, value)
69
+ send(:"#{key}=", value)
56
70
  end
57
71
 
72
+ # Keys of an object.
58
73
  def keys
59
74
  @values.keys
60
75
  end
61
76
 
77
+ # Values of an object.
62
78
  def values
63
79
  @values.values
64
80
  end
65
81
 
66
- def to_json(options = {})
82
+ # Make values JSON.
83
+ def to_json(_options = {})
67
84
  JSON.dump(@values)
68
85
  end
69
86
 
70
- def as_json(options = {})
87
+ # Get values as JSON.
88
+ def as_json(_options = {})
71
89
  @values.as_json
72
90
  end
73
91
 
92
+ # Make values a hash.
74
93
  def to_hash
75
94
  @values
76
95
  end
77
96
 
97
+ # Deconstruct the keys of an object.
78
98
  def deconstruct_keys(_keys)
79
99
  @values.transform_keys(&:to_sym)
80
100
  end
81
101
 
102
+ # Get each element of values.
82
103
  def each(&blk)
83
104
  @values.each(&blk)
84
105
  end
85
106
 
107
+ # Set the ID of an object.
86
108
  def id=(id)
87
109
  @values[:id] = id
88
110
  end
89
111
 
112
+ # Get the ID of an object.
90
113
  def id
91
114
  @values[:id]
92
115
  end
93
116
 
94
117
  protected
95
118
 
119
+ # Flatten the unsaved values of an object.
96
120
  def flatten_unsaved
97
121
  values = {}
98
- for key in @unsaved_values
122
+ @unsaved_values.each do |key|
99
123
  value = @values[key]
100
124
 
101
125
  values[key] = value
@@ -105,28 +129,20 @@ class EasyPost::EasyPostObject
105
129
  end
106
130
  end
107
131
 
108
- return values
132
+ values
109
133
  end
110
134
 
135
+ # The metaclass of an object.
111
136
  def metaclass
112
137
  class << self; self; end
113
138
  end
114
139
 
115
- def remove_accessors(keys)
116
- metaclass.instance_eval do
117
- keys.each do |k|
118
- next if @@immutable_values.include?(k)
119
- k_eq = :"#{k}="
120
- remove_method(k) if method_defined?(k)
121
- remove_method(k_eq) if method_defined?(k_eq)
122
- end
123
- end
124
- end
125
-
140
+ # Add accessors of an object.
126
141
  def add_accessors(keys)
127
142
  metaclass.instance_eval do
128
143
  keys.each do |k|
129
144
  next if @@immutable_values.include?(k)
145
+
130
146
  k = k.to_s
131
147
  k_eq = :"#{k}="
132
148
  define_method(k) { @values[k] }
@@ -135,7 +151,7 @@ class EasyPost::EasyPostObject
135
151
  @unsaved_values.add(k)
136
152
 
137
153
  cur = self
138
- cur_parent = self.parent
154
+ cur_parent = parent
139
155
  while cur_parent
140
156
  if cur.name
141
157
  cur_parent.unsaved_values.add(cur.name)
@@ -1,13 +1,17 @@
1
- class EasyPost::Order < EasyPost::Resource
1
+ # frozen_string_literal: true
2
2
 
3
- def get_rates(params={})
4
- response = EasyPost.make_request(:get, url + '/rates', @api_key, params)
5
- self.refresh_from(response, @api_key, true)
3
+ # The Order object represents a collection of packages and can be used for Multi-Piece Shipments.
4
+ class EasyPost::Order < EasyPost::Resource
5
+ # Get the rates of an Order.
6
+ def get_rates(params = {})
7
+ response = EasyPost.make_request(:get, "#{url}/rates", @api_key, params)
8
+ refresh_from(response, @api_key)
6
9
 
7
- return self
10
+ self
8
11
  end
9
12
 
10
- def buy(params={})
13
+ # Buy an Order.
14
+ def buy(params = {})
11
15
  if params.instance_of?(EasyPost::Rate)
12
16
  temp = params.clone
13
17
  params = {}
@@ -15,14 +19,14 @@ class EasyPost::Order < EasyPost::Resource
15
19
  params[:service] = temp.service
16
20
  end
17
21
 
18
- response = EasyPost.make_request(:post, url + '/buy', @api_key, params)
19
- self.refresh_from(response, @api_key, true)
22
+ response = EasyPost.make_request(:post, "#{url}/buy", @api_key, params)
23
+ refresh_from(response, @api_key)
20
24
 
21
- return self
25
+ self
22
26
  end
23
27
 
24
- def self.all(filters={}, api_key=nil)
28
+ # Retrieve a list of Order objects.
29
+ def self.all
25
30
  raise NotImplementedError.new('Order.all not implemented.')
26
31
  end
27
-
28
32
  end
@@ -1,2 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Parcel objects represent the physical container being shipped.
1
4
  class EasyPost::Parcel < EasyPost::Resource
5
+ # Retrieving all Parcel objects is not supported.
6
+ def self.all
7
+ raise NotImplementedError.new('Parcel.all not implemented.')
8
+ end
2
9
  end
@@ -1,5 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The Pickup object allows you to schedule a pickup from your carrier from your customer's residence or place of business.
1
4
  class EasyPost::Pickup < EasyPost::Resource
2
- def buy(params={})
5
+ # Buy a Pickup.
6
+ def buy(params = {})
3
7
  if params.instance_of?(EasyPost::PickupRate)
4
8
  temp = params.clone
5
9
  params = {}
@@ -7,20 +11,22 @@ class EasyPost::Pickup < EasyPost::Resource
7
11
  params[:service] = temp.service
8
12
  end
9
13
 
10
- response = EasyPost.make_request(:post, url + '/buy', @api_key, params)
11
- self.refresh_from(response, @api_key, true)
14
+ response = EasyPost.make_request(:post, "#{url}/buy", @api_key, params)
15
+ refresh_from(response, @api_key)
12
16
 
13
- return self
17
+ self
14
18
  end
15
19
 
16
- def cancel(params={})
17
- response = EasyPost.make_request(:post, url + '/cancel', @api_key, params)
18
- self.refresh_from(response, @api_key, true)
20
+ # Cancel a Pickup.
21
+ def cancel(params = {})
22
+ response = EasyPost.make_request(:post, "#{url}/cancel", @api_key, params)
23
+ refresh_from(response, @api_key)
19
24
 
20
- return self
25
+ self
21
26
  end
22
27
 
23
- def self.all(filters={}, api_key=nil)
28
+ # Retrieve a list of all Pickup objects.
29
+ def self.all
24
30
  raise NotImplementedError.new('Pickup.all not implemented.')
25
31
  end
26
32
  end
@@ -1,3 +1,5 @@
1
- class EasyPost::PickupRate < EasyPost::Resource
1
+ # frozen_string_literal: true
2
2
 
3
+ # A PickupRate is the rate available for a Pickup.
4
+ class EasyPost::PickupRate < EasyPost::Resource
3
5
  end
@@ -1,2 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # PostageLabel is the object containing details about the shipping label.
1
4
  class EasyPost::PostageLabel < EasyPost::Resource
2
5
  end
data/lib/easypost/rate.rb CHANGED
@@ -1,2 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A Rate object contains all the details about the rate of a Shipment.
1
4
  class EasyPost::Rate < EasyPost::Resource
5
+ # Retrieving all Rate objects is not supported.
6
+ def self.all
7
+ raise NotImplementedError.new('Rate.all not implemented.')
8
+ end
2
9
  end
@@ -1,2 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The Refund object contains details about the Refund of a Shipment.
1
4
  class EasyPost::Refund < EasyPost::Resource
2
5
  end
@@ -1,29 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A Report contains a csv that is a log of all the objects created within a certain time frame.
1
4
  class EasyPost::Report < EasyPost::Resource
2
- def self.create(params={}, api_key=nil)
5
+ # Create a Report.
6
+ def self.create(params = {}, api_key = nil)
3
7
  url = "#{self.url}/#{params[:type]}"
4
8
  wrapped_params = {}
5
9
  wrapped_params[class_name.to_sym] = params
6
10
 
7
11
  response = EasyPost.make_request(:post, url, api_key, params)
8
- return EasyPost::Util.convert_to_easypost_object(response, api_key)
9
- end
10
-
11
- def self.retrieve(params, api_key=nil)
12
- id = if params.is_a?(String)
13
- params
14
- else
15
- params[:id]
16
- end
17
-
18
- instance = self.new(id, api_key)
19
- instance.refresh
20
- return instance
12
+ EasyPost::Util.convert_to_easypost_object(response, api_key)
21
13
  end
22
14
 
23
- def self.all(filters={}, api_key=nil)
15
+ # Retrieve a list of Report objects.
16
+ def self.all(filters = {}, api_key = nil)
24
17
  url = "#{self.url}/#{filters[:type]}"
25
18
 
26
19
  response = EasyPost.make_request(:get, url, api_key, filters)
27
- return EasyPost::Util::convert_to_easypost_object(response, api_key) if response
20
+ EasyPost::Util.convert_to_easypost_object(response, api_key)
28
21
  end
29
22
  end
@@ -1,75 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The Resource object is extended by each EasyPost object.
1
4
  class EasyPost::Resource < EasyPost::EasyPostObject
5
+ extend Enumerable
6
+
7
+ # The class name of an EasyPost object.
2
8
  def self.class_name
3
- camel = self.name.split('::')[-1]
9
+ camel = name.split('::')[-1]
4
10
  snake = camel[0..0] + camel[1..-1].gsub(/([A-Z])/, '_\1')
5
- return snake.downcase
11
+ snake.downcase
6
12
  end
7
13
 
14
+ # The instance url of the Resource.
8
15
  def self.url
9
- if self.class_name == 'resource'
10
- raise NotImplementedError.new('Resource is an abstract class. You should perform actions on its subclasses (Address, Shipment, etc.)')
16
+ if class_name == 'resource'
17
+ raise NotImplementedError.new(
18
+ 'Resource is an abstract class. You should perform actions on its subclasses (Address, Shipment, etc.)',
19
+ )
11
20
  end
12
- if(self.class_name[-1..-1] == 's' || self.class_name[-1..-1] == 'h')
13
- return "/v2/#{CGI.escape(self.class_name.downcase)}es"
21
+
22
+ if class_name[-1..-1] == 's' || class_name[-1..-1] == 'h'
23
+ "/v2/#{CGI.escape(class_name.downcase)}es"
14
24
  else
15
- return "/v2/#{CGI.escape(class_name.downcase)}s"
25
+ "/v2/#{CGI.escape(class_name.downcase)}s"
16
26
  end
17
27
  end
18
28
 
29
+ # The url of the Resource.
19
30
  def url
20
- unless self.id
21
- raise EasyPost::Error.new("Could not determine which URL to request: #{self.class} instance has invalid ID: #{self.id.inspect}")
31
+ unless id
32
+ raise EasyPost::Error.new("Could not determine which URL to request: #{self.class} instance has invalid ID: #{id.inspect}")
22
33
  end
23
- return "#{self.class.url}/#{CGI.escape(id)}"
34
+
35
+ "#{self.class.url}/#{CGI.escape(id)}"
24
36
  end
25
37
 
38
+ # Refresh an object from the API response.
26
39
  def refresh
27
40
  response = EasyPost.make_request(:get, url, @api_key, @retrieve_options)
28
41
  refresh_from(response, api_key)
29
- return self
42
+ self
30
43
  end
31
44
 
32
- def self.all(filters={}, api_key=nil)
45
+ # Retrieve a list of EasyPost objects.
46
+ def self.all(filters = {}, api_key = nil)
33
47
  response = EasyPost.make_request(:get, url, api_key, filters)
34
- return EasyPost::Util.convert_to_easypost_object(response, api_key)
48
+ EasyPost::Util.convert_to_easypost_object(response, api_key)
49
+ end
50
+
51
+ def self.each(filters = {}, api_key = EasyPost.api_key, &block)
52
+ return to_enum(:each, filters, api_key) unless block_given?
53
+
54
+ loop do
55
+ page, has_more = all(filters, api_key).values
56
+ last = page.each(&block).last
57
+ break if page.empty? || !has_more
58
+
59
+ filters[:before_id] = last.id
60
+ end
35
61
  end
36
62
 
37
- def self.retrieve(id, api_key=nil)
38
- instance = self.new(id, api_key)
63
+ # Retrieve an EasyPost object.
64
+ def self.retrieve(id, api_key = nil)
65
+ instance = new(id, api_key)
39
66
  instance.refresh
40
- return instance
67
+ instance
41
68
  end
42
69
 
43
- def self.create(params={}, api_key=nil)
70
+ # Create an EasyPost object.
71
+ def self.create(params = {}, api_key = nil)
44
72
  wrapped_params = {}
45
- wrapped_params[self.class_name().to_sym] = params
46
- response = EasyPost.make_request(:post, self.url, api_key, wrapped_params)
47
- return EasyPost::Util.convert_to_easypost_object(response, api_key)
73
+ wrapped_params[class_name.to_sym] = params
74
+ response = EasyPost.make_request(:post, url, api_key, wrapped_params)
75
+ EasyPost::Util.convert_to_easypost_object(response, api_key)
48
76
  end
49
77
 
78
+ # Delete an EasyPost object.
50
79
  def delete
51
80
  response = EasyPost.make_request(:delete, url, @api_key)
52
81
  refresh_from(response, api_key)
53
- return self
82
+ self
54
83
  end
55
84
 
85
+ # Save (update) and EasyPost object.
56
86
  def save
57
- if @unsaved_values.length > 0
87
+ if @unsaved_values.length.positive?
58
88
  values = {}
59
89
  @unsaved_values.each { |k| values[k] = @values[k] }
60
90
 
61
- for key in @unsaved_values
91
+ @unsaved_values.each do |key| # rubocop:disable Style/CombinableLoops
62
92
  value = values[key]
63
93
  if value.is_a?(EasyPost::EasyPostObject)
64
94
  values[key] = value.flatten_unsaved
65
95
  end
66
96
  end
67
97
 
68
- wrapped_params = {self.class.class_name => values}
98
+ wrapped_params = { self.class.class_name => values }
69
99
 
70
100
  response = EasyPost.make_request(:put, url, @api_key, wrapped_params)
71
101
  refresh_from(response, api_key)
72
102
  end
73
- return self
103
+ self
74
104
  end
75
105
  end
@@ -1,6 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A ScanForm can be created to speed up and simplify the carrier pickup process. The ScanForm is one document that can
4
+ # be scanned to mark all included tracking codes as "Accepted for Shipment" by the carrier.
1
5
  class EasyPost::ScanForm < EasyPost::Resource
2
- def self.create(params={}, api_key=nil)
3
- response = EasyPost.make_request(:post, self.url, api_key, params)
4
- return EasyPost::Util.convert_to_easypost_object(response, api_key)
6
+ # Create a ScanForm.
7
+ def self.create(params = {}, api_key = nil)
8
+ response = EasyPost.make_request(:post, url, api_key, params)
9
+ EasyPost::Util.convert_to_easypost_object(response, api_key)
5
10
  end
6
11
  end
@@ -1,88 +1,85 @@
1
- class EasyPost::Shipment < EasyPost::Resource
2
- def get_rates(params={})
3
- response = EasyPost.make_request(:get, url + '/rates', @api_key, params)
4
- self.refresh_from(response, @api_key, true)
5
-
6
- return self
7
- end
1
+ # frozen_string_literal: true
8
2
 
9
- def regenerate_rates(params={})
10
- response = EasyPost.make_request(:post, url + '/rerate', @api_key, params)
11
- self.refresh_from(response, @api_key, true)
3
+ # The workhorse of the EasyPost API, a Shipment is made up of a "to" and "from" Address, the Parcel
4
+ # being shipped, and any customs forms required for international deliveries.
5
+ class EasyPost::Shipment < EasyPost::Resource
6
+ # Regenerate the rates of a Shipment.
7
+ def regenerate_rates(params = {})
8
+ response = EasyPost.make_request(:post, "#{url}/rerate", @api_key, params)
9
+ refresh_from(response, @api_key)
12
10
 
13
- return self
11
+ self
14
12
  end
15
13
 
16
- def get_smartrates
17
- response = EasyPost.make_request(:get, url + '/smartrate', @api_key)
14
+ # Get the SmartRates of a Shipment.
15
+ def get_smartrates # rubocop:disable Naming/AccessorMethodName
16
+ response = EasyPost.make_request(:get, "#{url}/smartrate", @api_key)
18
17
 
19
- return response.fetch('result', [])
18
+ response.fetch('result', [])
20
19
  end
21
20
 
22
- def buy(params={})
21
+ # Buy a Shipment.
22
+ def buy(params = {})
23
23
  if params.instance_of?(EasyPost::Rate)
24
24
  temp = params.clone
25
25
  params = {}
26
26
  params[:rate] = temp
27
27
  end
28
28
 
29
- response = EasyPost.make_request(:post, url + '/buy', @api_key, params)
30
- self.refresh_from(response, @api_key, true)
29
+ response = EasyPost.make_request(:post, "#{url}/buy", @api_key, params)
30
+ refresh_from(response, @api_key)
31
31
 
32
- return self
32
+ self
33
33
  end
34
34
 
35
- def insure(params={})
35
+ # Insure a Shipment.
36
+ def insure(params = {})
36
37
  if params.is_a?(Integer) || params.is_a?(Float)
37
38
  temp = params.clone
38
39
  params = {}
39
40
  params[:amount] = temp
40
41
  end
41
42
 
42
- response = EasyPost.make_request(:post, url + '/insure', @api_key, params)
43
- self.refresh_from(response, @api_key, true)
43
+ response = EasyPost.make_request(:post, "#{url}/insure", @api_key, params)
44
+ refresh_from(response, @api_key)
44
45
 
45
- return self
46
+ self
46
47
  end
47
48
 
48
- def refund(params={})
49
- response = EasyPost.make_request(:get, url + '/refund', @api_key, params)
50
- self.refresh_from(response, @api_key, true)
49
+ # Refund a Shipment.
50
+ def refund(params = {})
51
+ response = EasyPost.make_request(:get, "#{url}/refund", @api_key, params)
52
+ refresh_from(response, @api_key)
51
53
 
52
- return self
54
+ self
53
55
  end
54
56
 
55
- def print(params={})
56
- if params.instance_of?(EasyPost::Printer)
57
- return params.print(self.postage_label)
58
- end
59
- return false
60
- end
61
-
62
- def label(params={})
57
+ # Convert the label format of a Shipment.
58
+ def label(params = {})
63
59
  if params.is_a?(String)
64
60
  temp = params.clone
65
61
  params = {}
66
62
  params[:file_format] = temp
67
63
  end
68
64
 
69
- response = EasyPost.make_request(:get, url + '/label', @api_key, params)
70
- self.refresh_from(response, @api_key, true)
65
+ response = EasyPost.make_request(:get, "#{url}/label", @api_key, params)
66
+ refresh_from(response, @api_key)
71
67
 
72
- return self
68
+ self
73
69
  end
74
70
 
75
- def lowest_rate(carriers=[], services=[])
71
+ # Get the lowest rate of a Shipment.
72
+ def lowest_rate(carriers = [], services = [])
76
73
  lowest = nil
77
74
 
78
- self.get_rates unless self.rates
75
+ get_rates unless rates
79
76
 
80
77
  carriers = EasyPost::Util.normalize_string_list(carriers)
81
78
 
82
79
  negative_carriers = []
83
80
  carriers_copy = carriers.clone
84
81
  carriers_copy.each do |carrier|
85
- if carrier[0,1] == '!'
82
+ if carrier[0, 1] == '!'
86
83
  negative_carriers << carrier[1..-1]
87
84
  carriers.delete(carrier)
88
85
  end
@@ -93,37 +90,36 @@ class EasyPost::Shipment < EasyPost::Resource
93
90
  negative_services = []
94
91
  services_copy = services.clone
95
92
  services_copy.each do |service|
96
- if service[0,1] == '!'
93
+ if service[0, 1] == '!'
97
94
  negative_services << service[1..-1]
98
95
  services.delete(service)
99
96
  end
100
97
  end
101
98
 
102
- self.rates.each do |k|
103
-
99
+ rates.each do |k|
104
100
  rate_carrier = k.carrier.downcase
105
- if carriers.size() > 0 && !carriers.include?(rate_carrier)
101
+ if carriers.size.positive? && !carriers.include?(rate_carrier)
106
102
  next
107
103
  end
108
- if negative_carriers.size() > 0 && negative_carriers.include?(rate_carrier)
104
+ if negative_carriers.size.positive? && negative_carriers.include?(rate_carrier)
109
105
  next
110
106
  end
111
107
 
112
108
  rate_service = k.service.downcase
113
- if services.size() > 0 && !services.include?(rate_service)
109
+ if services.size.positive? && !services.include?(rate_service)
114
110
  next
115
111
  end
116
- if negative_services.size() > 0 && negative_services.include?(rate_service)
112
+ if negative_services.size.positive? && negative_services.include?(rate_service)
117
113
  next
118
114
  end
119
115
 
120
- if lowest == nil || k.rate.to_f < lowest.rate.to_f
121
- lowest = k
116
+ if lowest.nil? || k.rate.to_f < lowest.rate.to_f
117
+ lowest = k
122
118
  end
123
119
  end
124
120
 
125
- raise EasyPost::Error.new('No rates found.') if lowest == nil
121
+ raise EasyPost::Error.new('No rates found.') if lowest.nil?
126
122
 
127
- return lowest
123
+ lowest
128
124
  end
129
125
  end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # TaxIdentifiers are identifying numbers or IDs that are used to charge a specific party when
4
+ # dealing with the importing or exporting of good across international borders.
5
+ class EasyPost::TaxIdentifier < EasyPost::Resource
6
+ end