shippo 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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,6 @@
1
+ module Shippo
2
+ class Address < Resource
3
+ include Shippo::Operations::List
4
+ include Shippo::Operations::Create
5
+ end
6
+ end
@@ -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
@@ -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
@@ -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
@@ -0,0 +1,6 @@
1
+ module Shippo
2
+ class Parcel < Resource
3
+ include Shippo::Operations::List
4
+ include Shippo::Operations::Create
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module Shippo
2
+ class Rate < Resource
3
+ include Shippo::Operations::List
4
+ end
5
+ end
@@ -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
@@ -0,0 +1,6 @@
1
+ module Shippo
2
+ class Transaction < Resource
3
+ include Shippo::Operations::List
4
+ include Shippo::Operations::Create
5
+ end
6
+ 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: []