shippo 0.0.1
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.
- checksums.yaml +7 -0
- data/example.rb +59 -0
- data/lib/shippo.rb +86 -0
- data/lib/shippo/address.rb +6 -0
- data/lib/shippo/api_object.rb +89 -0
- data/lib/shippo/container_object.rb +28 -0
- data/lib/shippo/create.rb +19 -0
- data/lib/shippo/error.rb +18 -0
- data/lib/shippo/list.rb +22 -0
- data/lib/shippo/parcel.rb +6 -0
- data/lib/shippo/rate.rb +5 -0
- data/lib/shippo/resource.rb +23 -0
- data/lib/shippo/shipment.rb +10 -0
- data/lib/shippo/transaction.rb +6 -0
- data/test/test.rb +26 -0
- metadata +57 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0e17e4581ec82ca7bb1242373d0f42045696f9a8
|
4
|
+
data.tar.gz: b159bf9011321abef4e546f7a60b276de4b09d93
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 48150a7adda38b277e70b3e031229456086a74472e5836892c3d42158445fe1e747e7bc3aef25de24c9a078354c424f53dae96de3b92671b3905180297a3436b
|
7
|
+
data.tar.gz: 5d2a381f23176b9c45a8c772fee6588facf4134e00e974581fb93edec09fa000d3b0b7d3b8b5d11ea9855e23505bcd207b1a4ca8af226ad99240bac15738db8d
|
data/example.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'shippo'
|
2
|
+
Shippo::api_user = 'YOUR_API_USER'
|
3
|
+
Shippo::api_pass = 'YOUR_API_PASS'
|
4
|
+
|
5
|
+
from = Shippo::Address.create(
|
6
|
+
:object_purchase => 'QUOTE',
|
7
|
+
:name => 'Laura Behrens Wu',
|
8
|
+
:company => 'Shippo',
|
9
|
+
:street1 => 'Clayton St.',
|
10
|
+
:street_no => '215',
|
11
|
+
:street2 => '',
|
12
|
+
:city => 'San Francisco',
|
13
|
+
:state => 'CA',
|
14
|
+
:zip => '94117',
|
15
|
+
:country => 'US',
|
16
|
+
:phone => '+1 555 341 9393',
|
17
|
+
:email => 'laura@goshippo.com',
|
18
|
+
:ip => '',
|
19
|
+
:metadata => 'Customer ID 123456'
|
20
|
+
)
|
21
|
+
puts from
|
22
|
+
to = Shippo::Address.create(
|
23
|
+
:object_purchase => 'QUOTE',
|
24
|
+
:name => 'Mr. John Doe',
|
25
|
+
:company => 'ACME Inc.',
|
26
|
+
:street1 => nil,
|
27
|
+
:street_no => '',
|
28
|
+
:street2 => '',
|
29
|
+
:city => 'Berlin',
|
30
|
+
:country => 'DE',
|
31
|
+
:ip => '',
|
32
|
+
:metadata => ''
|
33
|
+
)
|
34
|
+
puts to
|
35
|
+
parcel = Shippo::Parcel.create(
|
36
|
+
:length => 5,
|
37
|
+
:width => 1,
|
38
|
+
:height => 5.555,
|
39
|
+
:distance_unit => :cm,
|
40
|
+
:weight => '2.122',
|
41
|
+
:mass_unit => :lb,
|
42
|
+
:metadata => 'Customer ID 123456'
|
43
|
+
)
|
44
|
+
puts parcel
|
45
|
+
shipment = Shippo::Shipment.create(
|
46
|
+
:object_purpose => 'QUOTE',
|
47
|
+
# you can also put in the object_id directly, but this is more convenient
|
48
|
+
:address_from => from,
|
49
|
+
:address_to => to,
|
50
|
+
:parcel => parcel,
|
51
|
+
:metadata => 'Quote Shipment'
|
52
|
+
)
|
53
|
+
puts shipment
|
54
|
+
# never do this in real life
|
55
|
+
sleep(5)
|
56
|
+
|
57
|
+
rates = shipment.rates
|
58
|
+
|
59
|
+
puts "Shipment #{shipment[:object_id]} has the following rates:\n\n#{rates}"
|
data/lib/shippo.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'rest_client'
|
2
|
+
require 'json'
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
require 'shippo/error.rb'
|
6
|
+
require 'shippo/container_object.rb'
|
7
|
+
require 'shippo/api_object.rb'
|
8
|
+
require 'shippo/list.rb'
|
9
|
+
require 'shippo/create.rb'
|
10
|
+
require 'shippo/resource.rb'
|
11
|
+
require 'shippo/address.rb'
|
12
|
+
require 'shippo/parcel.rb'
|
13
|
+
require 'shippo/shipment.rb'
|
14
|
+
require 'shippo/transaction.rb'
|
15
|
+
require 'shippo/rate.rb'
|
16
|
+
|
17
|
+
module Shippo
|
18
|
+
@api_base = 'https://api.goshippo.com/v1'
|
19
|
+
@api_version = 1.0
|
20
|
+
@api_user = ''
|
21
|
+
@api_pass = ''
|
22
|
+
|
23
|
+
class << self
|
24
|
+
attr_accessor :api_base, :api_version, :api_user, :api_pass
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.api_url(url='')
|
28
|
+
@api_base + url
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.request(method, url, params = {}, headers = {})
|
32
|
+
unless @api_user && @api_pass
|
33
|
+
raise AuthError.new("API credentials missing! Make sure to set Shippo.api_user, Shippo.api_Pass")
|
34
|
+
end
|
35
|
+
begin
|
36
|
+
payload = {}
|
37
|
+
url = api_url(url)
|
38
|
+
case method
|
39
|
+
when :get
|
40
|
+
pairs = []
|
41
|
+
params.each { |k, v|
|
42
|
+
pairs.push "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}"
|
43
|
+
}
|
44
|
+
url += "?#{pairs.join('&')}" unless pairs.empty?
|
45
|
+
when :post
|
46
|
+
payload = params
|
47
|
+
end
|
48
|
+
opts = { :headers => headers,
|
49
|
+
:method => method,
|
50
|
+
:payload => payload,
|
51
|
+
:url => url,
|
52
|
+
:open_timeout => 15,
|
53
|
+
:timeout => 30,
|
54
|
+
:user => @api_user,
|
55
|
+
:password => @api_pass
|
56
|
+
}
|
57
|
+
res = make_request(opts)
|
58
|
+
rescue => e
|
59
|
+
case e
|
60
|
+
when RestClient::ServerBrokeConnection, RestClient::RequestTimeout
|
61
|
+
msg = "Could not connect to the Shippo API at #{@api_base}. " +
|
62
|
+
"Please proceed to check your connection, try again and " +
|
63
|
+
"contact Shippo support should the issue persist."
|
64
|
+
when SocketError
|
65
|
+
msg = "Unexpected error connecting to the Shippo API at #{@api_base}."
|
66
|
+
else
|
67
|
+
msg = "Connection error"
|
68
|
+
end
|
69
|
+
raise ConnectionError.new msg + "\n\n(e.message)"
|
70
|
+
end
|
71
|
+
parse(res)
|
72
|
+
end
|
73
|
+
def self.parse(response)
|
74
|
+
JSON::parse(response.body, { :symbolize_names => true })
|
75
|
+
end
|
76
|
+
end
|
77
|
+
def make_request(opts)
|
78
|
+
RestClient::Request.execute(opts){ |response, request, result, &block|
|
79
|
+
if [301, 302, 307].include? response.code
|
80
|
+
response.follow_redirection(request, result, &block)
|
81
|
+
else
|
82
|
+
response.return!(request, result, &block)
|
83
|
+
end
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module Shippo
|
2
|
+
class ApiObject < ContainerObject
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
def initialize(id=nil)
|
6
|
+
# parameter overloading!
|
7
|
+
if id.kind_of?(Hash)
|
8
|
+
id = id[:id]
|
9
|
+
end
|
10
|
+
|
11
|
+
@values = {}
|
12
|
+
@values[:id] = id if id
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.construct_from(values)
|
16
|
+
# recursive on arrays
|
17
|
+
case values
|
18
|
+
when Array
|
19
|
+
values.map { |v| self.construct_from(v) }
|
20
|
+
when Hash
|
21
|
+
obj = self.new(values[:id])
|
22
|
+
obj.refresh_from(values)
|
23
|
+
obj
|
24
|
+
else
|
25
|
+
# on scalar types, just identity
|
26
|
+
values
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s(*args)
|
31
|
+
JSON.pretty_generate @values
|
32
|
+
end
|
33
|
+
|
34
|
+
def inspect()
|
35
|
+
id_string = (self.respond_to?(:id) && !self.id.nil?) ? " id=#{self.id}" : ""
|
36
|
+
"#<#{self.class}:0x#{self.object_id.to_s(16)}#{id_string}> JSON: " + self.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
def refresh_from(values)
|
40
|
+
values.each do |k, v|
|
41
|
+
@values[k.to_sym] = v
|
42
|
+
end
|
43
|
+
instance_eval do
|
44
|
+
add_accessors(@values.keys)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
def [](k)
|
49
|
+
@values[k.to_sym]
|
50
|
+
end
|
51
|
+
|
52
|
+
def []=(k, v)
|
53
|
+
send(:"#{k}=", v)
|
54
|
+
end
|
55
|
+
def keys
|
56
|
+
@values.keys
|
57
|
+
end
|
58
|
+
|
59
|
+
def values
|
60
|
+
@values.values
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_json(*a)
|
64
|
+
JSON.dump(@values)
|
65
|
+
end
|
66
|
+
|
67
|
+
def as_json(*a)
|
68
|
+
@values.as_json(*a)
|
69
|
+
end
|
70
|
+
|
71
|
+
def to_hash
|
72
|
+
@values
|
73
|
+
end
|
74
|
+
|
75
|
+
def each(&blk)
|
76
|
+
@values.each(&blk)
|
77
|
+
end
|
78
|
+
|
79
|
+
if RUBY_VERSION < '1.9.2'
|
80
|
+
def respond_to?(symbol)
|
81
|
+
@values.has_key?(symbol) || super
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Shippo
|
2
|
+
class ContainerObject
|
3
|
+
protected
|
4
|
+
def create_accessor(k_name, k_index)
|
5
|
+
metaclass.instance_eval do
|
6
|
+
define_method(k_name) { @values[k_index] }
|
7
|
+
define_method(:"#{k_name}=") do |v|
|
8
|
+
@values[k_index] = v unless k_index == ''
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
def add_accessors(keys)
|
13
|
+
keys.each do |k|
|
14
|
+
#TODO raise something here, should filter this before
|
15
|
+
orig_k = k
|
16
|
+
while respond_to?(k) do
|
17
|
+
k = "_#{k}".to_sym
|
18
|
+
end
|
19
|
+
create_accessor(k, orig_k)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
def metaclass
|
23
|
+
class << self
|
24
|
+
self
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Shippo
|
2
|
+
module Operations
|
3
|
+
module Create
|
4
|
+
module ClassMethods
|
5
|
+
def create(params={})
|
6
|
+
params.each do |k, v|
|
7
|
+
params[k] = v[:object_id] if v.is_a?(ApiObject)
|
8
|
+
end
|
9
|
+
response = Shippo.request(:post, "#{self.url}/", params)
|
10
|
+
self.construct_from(response)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.included(base)
|
15
|
+
base.extend(ClassMethods)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/shippo/error.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Shippo
|
2
|
+
class APIError < StandardError
|
3
|
+
attr_reader :message
|
4
|
+
def initialize(message=nil)
|
5
|
+
@message = message
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_s
|
9
|
+
@message
|
10
|
+
end
|
11
|
+
end
|
12
|
+
class ConnectionError < APIError
|
13
|
+
end
|
14
|
+
class MissingDataError < APIError
|
15
|
+
end
|
16
|
+
class AuthError < APIError
|
17
|
+
end
|
18
|
+
end
|
data/lib/shippo/list.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module Shippo
|
2
|
+
module Operations
|
3
|
+
module List
|
4
|
+
module ClassMethods
|
5
|
+
# return all items
|
6
|
+
def all(params={})
|
7
|
+
response = Shippo.request(:get, "#{url}/", params)
|
8
|
+
self.construct_from(response[:results] || [])
|
9
|
+
end
|
10
|
+
# return a specific item
|
11
|
+
def get(id, params={})
|
12
|
+
response = Shippo.request(:get, "#{url}/#{CGI.escape(id)}/", params)
|
13
|
+
self.construct_from(response)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.included(base)
|
18
|
+
base.extend(ClassMethods)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/shippo/rate.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Shippo
|
2
|
+
class Resource < ApiObject
|
3
|
+
def self.class_name
|
4
|
+
self.name.split('::')[-1]
|
5
|
+
end
|
6
|
+
def self.url()
|
7
|
+
dc = class_name.downcase
|
8
|
+
"/" + dc + (dc[-1] == 's' ? 'es' : 's')
|
9
|
+
end
|
10
|
+
def url
|
11
|
+
unless id = self['object_id']
|
12
|
+
raise MissingDataError.new("#{self.class} has no object_id")
|
13
|
+
end
|
14
|
+
"#{self.class.url}/#{CGI.escape(id)}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def refresh
|
18
|
+
response, api_key = Shippo.request(:get, url, @retrieve_options)
|
19
|
+
refresh_from(response)
|
20
|
+
self
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module Shippo
|
2
|
+
class Shipment < Resource
|
3
|
+
include Shippo::Operations::List
|
4
|
+
include Shippo::Operations::Create
|
5
|
+
def rates(params={})
|
6
|
+
response = Shippo.request(:get, "#{url}/rates/", params)
|
7
|
+
Shippo::Rate.construct_from(response[:results])
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
data/test/test.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
gem 'mocha'
|
3
|
+
require 'test/unit'
|
4
|
+
require 'mocha/test_unit'
|
5
|
+
require 'shippo'
|
6
|
+
def parcel_list_result
|
7
|
+
JSON::parse File.open('./parcel_list.json').read
|
8
|
+
end
|
9
|
+
|
10
|
+
module Shippo
|
11
|
+
class ParcelTest < Test::Unit::TestCase
|
12
|
+
def test_import
|
13
|
+
# get an array of test parcels from JSON
|
14
|
+
ret = Shippo::Parcel.construct_from(parcel_list_result)
|
15
|
+
# test the various options of accessing the parcel data
|
16
|
+
assert_equal ret[:metadata], "Customer ID 123456"
|
17
|
+
ret["metadata"] = "Customer ID 007"
|
18
|
+
assert_equal ret.metadata, "Customer ID 007"
|
19
|
+
assert_equal ret.object_owner, "tobias.schottdorf@gmail.com"
|
20
|
+
ret[:object_owner] = "hans.wurst@gmail.com"
|
21
|
+
assert_equal ret["object_owner"], "hans.wurst@gmail.com"
|
22
|
+
assert_equal ret.object_state, "VALID"
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: shippo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Tobias Schottdorf
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-03 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Quick and easy access to the Shippo API
|
14
|
+
email: tobias.schottdorf@gmail.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- example.rb
|
20
|
+
- test/test.rb
|
21
|
+
- lib/shippo.rb
|
22
|
+
- ./lib/shippo/address.rb
|
23
|
+
- ./lib/shippo/api_object.rb
|
24
|
+
- ./lib/shippo/container_object.rb
|
25
|
+
- ./lib/shippo/create.rb
|
26
|
+
- ./lib/shippo/error.rb
|
27
|
+
- ./lib/shippo/list.rb
|
28
|
+
- ./lib/shippo/parcel.rb
|
29
|
+
- ./lib/shippo/rate.rb
|
30
|
+
- ./lib/shippo/resource.rb
|
31
|
+
- ./lib/shippo/shipment.rb
|
32
|
+
- ./lib/shippo/transaction.rb
|
33
|
+
homepage: http://goshippo.com
|
34
|
+
licenses:
|
35
|
+
- MIT
|
36
|
+
metadata: {}
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options: []
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - '>='
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
requirements: []
|
52
|
+
rubyforge_project:
|
53
|
+
rubygems_version: 2.0.14
|
54
|
+
signing_key:
|
55
|
+
specification_version: 4
|
56
|
+
summary: Shippo API
|
57
|
+
test_files: []
|