easypost 1.1.3 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ module EasyPost
2
+ class CustomsInfo < Resource
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module EasyPost
2
+ class CustomsItem < Resource
3
+ end
4
+ end
@@ -1,15 +1,24 @@
1
1
  module EasyPost
2
- class EasyPostError < StandardError
2
+ class Error < StandardError
3
3
  attr_reader :message
4
4
  attr_reader :http_status
5
5
  attr_reader :http_body
6
6
  attr_reader :json_body
7
+ attr_reader :param
7
8
 
8
9
  def initialize(message=nil, http_status=nil, http_body=nil, json_body=nil)
9
10
  @message = message
10
11
  @http_status = http_status
11
12
  @http_body = http_body
12
13
  @json_body = json_body
14
+
15
+ begin
16
+ @param = @json_body[:error][:param]
17
+ rescue
18
+ @param = nil
19
+ end
20
+
21
+ super(message)
13
22
  end
14
23
 
15
24
  def to_s
@@ -0,0 +1,120 @@
1
+ module EasyPost
2
+ class EasyPostObject
3
+ include Enumerable
4
+
5
+ attr_accessor :api_key
6
+ @@immutable_values = Set.new([:api_key, :id])
7
+
8
+ def initialize(id=nil, api_key=nil)
9
+ @api_key = api_key
10
+ @values = {}
11
+ @unsaved_values = Set.new
12
+ @transient_values = Set.new
13
+ self.id = id if id
14
+ end
15
+
16
+ def self.construct_from(values, api_key=nil)
17
+ obj = self.new(values[:id], api_key)
18
+ obj.refresh_from(values, api_key)
19
+ obj
20
+ end
21
+
22
+ def to_s(*args)
23
+ MultiJson.dump(@values, :pretty => true)
24
+ end
25
+
26
+ def inspect()
27
+ id_string = (self.respond_to?(:id) && !self.id.nil?) ? " id=#{self.id}" : ""
28
+ "#<#{self.class}:#{id_string}> JSON: " + MultiJson.dump(@values, :pretty => true)
29
+ end
30
+
31
+ def refresh_from(values, api_key, partial=false)
32
+ @api_key = api_key
33
+
34
+ added = Set.new(values.keys - @values.keys)
35
+
36
+ instance_eval do
37
+ add_accessors(added)
38
+ end
39
+
40
+ values.each do |k, v|
41
+ @values[k] = Util.convert_to_easypost_object(v, api_key)
42
+ @transient_values.delete(k)
43
+ @unsaved_values.delete(k)
44
+ end
45
+ end
46
+
47
+ def [](k)
48
+ k = k.to_sym if k.is_a?(String)
49
+ @values[k]
50
+ end
51
+
52
+ def []=(k, v)
53
+ send(:"#{k}=", v)
54
+ end
55
+
56
+ def keys
57
+ @values.keys
58
+ end
59
+
60
+ def values
61
+ @values.values
62
+ end
63
+
64
+ def to_json(options = {})
65
+ MultiJson.dump(@values)
66
+ end
67
+
68
+ def as_json(options = {})
69
+ @values.as_json
70
+ end
71
+
72
+ def to_hash
73
+ @values
74
+ end
75
+
76
+ def each(&blk)
77
+ @values.each(&blk)
78
+ end
79
+
80
+ def id=(id)
81
+ @values[:id] = id
82
+ end
83
+
84
+ def id
85
+ @values[:id]
86
+ end
87
+
88
+ protected
89
+
90
+ def metaclass
91
+ class << self; self; end
92
+ end
93
+
94
+ def remove_accessors(keys)
95
+ metaclass.instance_eval do
96
+ keys.each do |k|
97
+ next if @@immutable_values.include?(k)
98
+ k_eq = :"#{k}="
99
+ remove_method(k) if method_defined?(k)
100
+ remove_method(k_eq) if method_defined?(k_eq)
101
+ end
102
+ end
103
+ end
104
+
105
+ def add_accessors(keys)
106
+ metaclass.instance_eval do
107
+ keys.each do |k|
108
+ next if @@immutable_values.include?(k)
109
+ k_eq = :"#{k}="
110
+ define_method(k) { @values[k] }
111
+ define_method(k_eq) do |v|
112
+ @values[k] = v
113
+ @unsaved_values.add(k)
114
+ end
115
+ end
116
+ end
117
+ end
118
+
119
+ end
120
+ end
@@ -0,0 +1,4 @@
1
+ module EasyPost
2
+ class Parcel < Resource
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module EasyPost
2
+ class PostageLabel < Resource
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module EasyPost
2
+ class Rate < Resource
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module EasyPost
2
+ class Refund < Resource
3
+ end
4
+ end
@@ -0,0 +1,67 @@
1
+ module EasyPost
2
+ class Resource < EasyPostObject
3
+ def self.class_name
4
+ camel = self.name.split('::')[-1]
5
+ snake = camel[0..0] + camel[1..-1].gsub(/([A-Z])/, '_\1')
6
+ return snake.downcase
7
+ end
8
+
9
+ def self.url
10
+ if self.class_name == 'resource'
11
+ raise NotImplementedError.new('Resource is an abstract class. You should perform actions on its subclasses (Address, Shipment, etc.)')
12
+ end
13
+ if(self.class_name[-1..-1] == 's' || self.class_name[-1..-1] == 'h')
14
+ return "/#{CGI.escape(self.class_name.downcase)}es"
15
+ else
16
+ return "/#{CGI.escape(class_name.downcase)}s"
17
+ end
18
+ end
19
+
20
+ def url
21
+ unless self.id
22
+ raise Error.new("Could not determine which URL to request: #{self.class} instance has invalid ID: #{self.id.inspect}")
23
+ end
24
+ return "#{self.class.url}/#{CGI.escape(id)}"
25
+ end
26
+
27
+ def refresh
28
+ response, api_key = EasyPost.request(:get, url, @api_key, @retrieve_options)
29
+ refresh_from(response, api_key)
30
+ return self
31
+ end
32
+
33
+ def self.all(filters={}, api_key=nil)
34
+ response, api_key = EasyPost.request(:get, url, api_key, filters)
35
+ return Util.convert_to_easypost_object(response, api_key)
36
+ end
37
+
38
+ def self.retrieve(id, api_key=nil)
39
+ instance = self.new(id, api_key)
40
+ instance.refresh
41
+ return instance
42
+ end
43
+
44
+ def self.create(params={}, api_key=nil)
45
+ wrapped_params = {}
46
+ wrapped_params[self.class_name().to_sym] = params
47
+ response, api_key = EasyPost.request(:post, self.url, api_key, wrapped_params)
48
+ return Util.convert_to_easypost_object(response, api_key)
49
+ end
50
+
51
+ def delete
52
+ response, api_key = EasyPost.request(:delete, url, @api_key)
53
+ refresh_from(response, api_key)
54
+ return self
55
+ end
56
+
57
+ def save
58
+ if @unsaved_values.length > 0
59
+ values = {}
60
+ @unsaved_values.each { |k| values[k] = @values[k] }
61
+ response, api_key = EasyPost.request(:post, url, @api_key, values)
62
+ refresh_from(response, api_key)
63
+ end
64
+ return self
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,4 @@
1
+ module EasyPost
2
+ class ScanForm < Resource
3
+ end
4
+ end
@@ -0,0 +1,82 @@
1
+ module EasyPost
2
+ class Shipment < Resource
3
+
4
+ def get_rates(params={})
5
+ response, api_key = EasyPost.request(:get, url + '/rates', @api_key, params)
6
+ self.refresh_from(response, @api_key, true)
7
+
8
+ return self
9
+ end
10
+
11
+ def buy(params={})
12
+ response, api_key = EasyPost.request(:post, url + '/buy', @api_key, params)
13
+ self.refresh_from(response, @api_key, true)
14
+
15
+ return self
16
+ end
17
+
18
+ def refund(params={})
19
+ response, api_key = EasyPost.request(:get, url + '/refund', @api_key, params)
20
+ self.refresh_from(response, @api_key, true)
21
+
22
+ return self
23
+ end
24
+
25
+ def track(params={})
26
+ response, api_key = EasyPost.request(:get, url + '/track', @api_key, params)
27
+ self.refresh_from(response, @api_key, true)
28
+
29
+ return self
30
+ end
31
+
32
+ def stamp(params={})
33
+ response, api_key = EasyPost.request(:get, url + '/stamp', @api_key, params)
34
+
35
+ return response[:stamp_url]
36
+ end
37
+
38
+ def barcode(params={})
39
+ response, api_key = EasyPost.request(:get, url + '/barcode', @api_key, params)
40
+
41
+ return response[:barcode_url]
42
+ end
43
+
44
+ def lowest_rate(carriers=[], services=[])
45
+ lowest = nil
46
+
47
+ self.get_rates unless self.rates
48
+
49
+ if !carriers.is_a?(Array)
50
+ carriers = carriers.split(',')
51
+ end
52
+ carriers.map!(&:downcase)
53
+
54
+ if !services.is_a?(Array)
55
+ services = services.split(',')
56
+ end
57
+ services.map!(&:downcase)
58
+
59
+ self.rates.each do |k|
60
+
61
+ rate_carrier = k.carrier.downcase
62
+ if carriers.size() > 0 && !carriers.include?(rate_carrier)
63
+ next
64
+ end
65
+
66
+ rate_service = k.service.downcase
67
+ if services.size() > 0 && !services.include?(rate_service)
68
+ next
69
+ end
70
+
71
+ if lowest == nil || k.rate.to_f < lowest.rate.to_f
72
+ lowest = k
73
+ end
74
+ end
75
+
76
+ raise Error.new('No rates found.') if lowest == nil
77
+
78
+ return lowest
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,102 @@
1
+ module EasyPost
2
+ module Util
3
+ def self.objects_to_ids(obj)
4
+ case obj
5
+ when Resource
6
+ return {:id => obj.id}
7
+ when Hash
8
+ result = {}
9
+ obj.each { |k, v| result[k] = objects_to_ids(v) unless v.nil? }
10
+ return result
11
+ when Array
12
+ return obj.map { |v| objects_to_ids(v) }
13
+ else
14
+ return obj
15
+ end
16
+ end
17
+
18
+ def self.convert_to_easypost_object(response, api_key)
19
+ types = { 'Address' => Address,
20
+ 'ScanForm' => ScanForm,
21
+ 'CustomsItem' => CustomsItem,
22
+ 'CustomsInfo' => CustomsInfo,
23
+ 'Parcel' => Parcel,
24
+ 'Shipment' => Shipment,
25
+ 'Rate' => Rate,
26
+ 'Refund' => Refund,
27
+ 'Batch' => Batch,
28
+ 'PostageLabel' => PostageLabel }
29
+
30
+ prefixes = { 'adr' => Address,
31
+ 'sf' => ScanForm,
32
+ 'cstitem' => CustomsItem,
33
+ 'cstinfo' => CustomsInfo,
34
+ 'prcl' => Parcel,
35
+ 'shp' => Shipment,
36
+ 'rate' => Rate,
37
+ 'rfnd' => Refund,
38
+ 'batch' => Batch,
39
+ 'pl' => PostageLabel }
40
+
41
+ case response
42
+ when Array
43
+ return response.map { |i| convert_to_easypost_object(i, api_key) }
44
+ when Hash
45
+ if cls_name = response[:object]
46
+ cls = types[cls_name]
47
+ elsif response[:id] && cls_prefix = response[:id][0..response[:id].index('_')]
48
+ cls = prefixes[cls_prefix[0..-2]]
49
+ end
50
+
51
+ cls ||= EasyPostObject
52
+ return cls.construct_from(response, api_key)
53
+ else
54
+ return response
55
+ end
56
+ end
57
+
58
+ def self.symbolize_names(obj)
59
+ case obj
60
+ when Hash
61
+ result = {}
62
+ obj.each do |k, v|
63
+ k = (k.to_sym rescue k) || k
64
+ obj[k] = symbolize_names(v)
65
+ end
66
+ return result
67
+ when Array
68
+ return obj.map { |v| symbolize_names(v) }
69
+ else
70
+ return obj
71
+ end
72
+ end
73
+
74
+ def self.url_encode(key)
75
+ URI.escape(key.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
76
+ end
77
+
78
+ def self.flatten_params(params, parent_key=nil)
79
+ result = []
80
+ if params.is_a?(Hash)
81
+ params.each do |k, v|
82
+ calculated_key = parent_key ? "#{parent_key}[#{url_encode(k)}]" : url_encode(k)
83
+ if v.is_a?(Hash) or v.is_a?(Array)
84
+ result += flatten_params(v, calculated_key)
85
+ else
86
+ result << [calculated_key, v]
87
+ end
88
+ end
89
+ elsif params.is_a?(Array)
90
+ params.each_with_index do |v, i|
91
+ calculated_key = parent_key ? "#{parent_key}[#{i}]" : i
92
+ if v.is_a?(Hash) or v.is_a?(Array)
93
+ result += flatten_params(v, calculated_key)
94
+ else
95
+ result << [calculated_key, v]
96
+ end
97
+ end
98
+ end
99
+ return result
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,3 @@
1
+ module EasyPost
2
+ VERSION = "2.0.0"
3
+ end