shirtsio 1.0.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.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/Gemfile +14 -0
- data/LICENSE.txt +22 -0
- data/README.md +163 -0
- data/Rakefile +8 -0
- data/e +0 -0
- data/lib/shirtsio.rb +36 -0
- data/lib/shirtsio/api.rb +16 -0
- data/lib/shirtsio/configuration.rb +53 -0
- data/lib/shirtsio/connection.rb +16 -0
- data/lib/shirtsio/dsl.rb +116 -0
- data/lib/shirtsio/endpoint.rb +14 -0
- data/lib/shirtsio/error.rb +13 -0
- data/lib/shirtsio/order.rb +63 -0
- data/lib/shirtsio/product.rb +46 -0
- data/lib/shirtsio/quote.rb +34 -0
- data/lib/shirtsio/request.rb +44 -0
- data/lib/shirtsio/status.rb +72 -0
- data/lib/shirtsio/utils.rb +39 -0
- data/lib/shirtsio/version.rb +3 -0
- data/shirtsio.gemspec +25 -0
- data/spec/dsl_spec.rb +35 -0
- data/spec/spec_helper.rb +11 -0
- metadata +112 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cb8da6ea02a157477414d05adb7c6b87a2870dcf
|
4
|
+
data.tar.gz: 51f822aa19b970e7531cfadd8a2dad55fc0487d8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a69d934ccba8b365b53d69d955b5883c29529fa2b320b3ed218c51cb5cf2ce44702adbf31fa2b985394127ac0892b4aa9c041e621ff8ef789d11812918984ab1
|
7
|
+
data.tar.gz: fd215fdf061db9e1516e6c2a07d2bc510b42237024a998aa2489c64b700390e28a0b7ef6875a37284ec0bbd32d925d6edb5a8870a62f187595613b5dc2551be1
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Anthony Smith
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
# Shirtsio
|
2
|
+
|
3
|
+
A Ruby wrapper around the shirts.io API
|
4
|
+
|
5
|
+
## Documentation
|
6
|
+
|
7
|
+
You can view detailed documentation of this library at http://rdoc.info/github/anthonator/shirtsio/frames. We try to make sure that our documentation is up-to-date and thorough. However, we do recommend keeping the [shirts.io API documentation](https://www.shirts.io/docs/overview/) handy.
|
8
|
+
|
9
|
+
If you find any discrepency in our documentation please [file an issue](https://github.com/anthonator/shirtsio/issues).
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
gem 'shirtsio'
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install shirtsio
|
24
|
+
|
25
|
+
## Quick Start Guide
|
26
|
+
|
27
|
+
Before you can start ordering some sweet shirts you'll need to tell shirts.io who you are.
|
28
|
+
|
29
|
+
Grab your super secret API key from the [shirts.io dashboard](https://www.shirts.io/accounts/dashboard/).
|
30
|
+
|
31
|
+
Sprinkle some pixie-dust...
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
Shirtsio.configure do |config|
|
35
|
+
config.api_key = YOUR_API_KEY
|
36
|
+
end
|
37
|
+
```
|
38
|
+
|
39
|
+
BAM! Print some shirts!
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
Shirtsio::Order.create do |order|
|
43
|
+
...
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
47
|
+
## Product API
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
# Return details about a specific product
|
51
|
+
product = Shirtsio::Product.find(3)
|
52
|
+
|
53
|
+
# Return a list of categories
|
54
|
+
categories = Shirtsio::Product::Category.list
|
55
|
+
|
56
|
+
# Return a list of products for a specific category
|
57
|
+
products = categories[0].products
|
58
|
+
|
59
|
+
# Since shirts.io doesn't return full product data when requesting from a category, return it now
|
60
|
+
product = products[0].full_product
|
61
|
+
```
|
62
|
+
|
63
|
+
## Quote API
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
# Assembling the parameters necessary to generate a quote is messy
|
67
|
+
# business. Luckily there's a DSL for that.
|
68
|
+
quote = Shirtsio::Quote.create do |quote|
|
69
|
+
quote.print_type 'Digital Print'
|
70
|
+
quote.garment do |garment|
|
71
|
+
garment.product_id 3
|
72
|
+
garment.color 'Black'
|
73
|
+
garment.sizes do |size|
|
74
|
+
size.med 1
|
75
|
+
end
|
76
|
+
end
|
77
|
+
quote.print do |print|
|
78
|
+
print.front do |front|
|
79
|
+
front.color_count 1
|
80
|
+
front.colors ['Black']
|
81
|
+
end
|
82
|
+
print.back do |back|
|
83
|
+
back.color_count 1
|
84
|
+
back.colors ['Black']
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
90
|
+
## Order API
|
91
|
+
```ruby
|
92
|
+
# Yep, there's one for orders too
|
93
|
+
order = Shirtsio::Order.create do |order|
|
94
|
+
order.test true
|
95
|
+
order.price 18.99
|
96
|
+
order.print_type 'Digital Print'
|
97
|
+
order.extra_screens 'None'
|
98
|
+
order.ship_type 'Standard'
|
99
|
+
order.garment do |garment|
|
100
|
+
garment.product_id 3
|
101
|
+
garment.color 'Black'
|
102
|
+
garment.sizes do |size|
|
103
|
+
size.med 1
|
104
|
+
end
|
105
|
+
end
|
106
|
+
order.print do |print|
|
107
|
+
print.front do |front|
|
108
|
+
front.artwork File.new('/path/to/file.png')
|
109
|
+
front.proof File.new('/path/to/file.jpg')
|
110
|
+
front.color_count 1
|
111
|
+
front.colors ['Black']
|
112
|
+
front.dimensions '5.0 inches wide'
|
113
|
+
front.placement '4.0 inches below bottom of collar'
|
114
|
+
end
|
115
|
+
end
|
116
|
+
order.personalization do |personalization|
|
117
|
+
personalization.size 'med'
|
118
|
+
personalization.batch 1
|
119
|
+
personalization.number 1
|
120
|
+
personalization.number_size 2
|
121
|
+
personalization.name 'Bob'
|
122
|
+
personalization.name_size 1
|
123
|
+
end
|
124
|
+
order.addresses do |address|
|
125
|
+
address.name 'Bob'
|
126
|
+
address.company 'Sticksnleaves'
|
127
|
+
address.address '1234 Hopes and Dreams Ln.'
|
128
|
+
address.address2 'Apt. <3'
|
129
|
+
address.city 'Indianapolis'
|
130
|
+
address.state 'IN'
|
131
|
+
address.country 'US'
|
132
|
+
address.batch 1
|
133
|
+
address.sizes do |size}
|
134
|
+
size.med 1
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
```
|
139
|
+
|
140
|
+
## Status API
|
141
|
+
```ruby
|
142
|
+
# Get an order's status
|
143
|
+
status = Shirtsio::Status.find(1234)
|
144
|
+
|
145
|
+
# Register a status webhook
|
146
|
+
Shirtsio::Status::Webhook.create('http://www.example.com') #returns true or false
|
147
|
+
|
148
|
+
# List webhooks
|
149
|
+
webhooks = Shirtsio::Status::Webhook.list
|
150
|
+
|
151
|
+
# Delete a webhook
|
152
|
+
Shirtsio::Status::Webhook.delete('http://www.example.com')
|
153
|
+
# or
|
154
|
+
webhooks[0].delete
|
155
|
+
```
|
156
|
+
|
157
|
+
## Contributing
|
158
|
+
|
159
|
+
1. Fork it
|
160
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
161
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
162
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
163
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/e
ADDED
File without changes
|
data/lib/shirtsio.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'hashie'
|
3
|
+
require 'multi_json'
|
4
|
+
|
5
|
+
require 'shirtsio/version'
|
6
|
+
require 'shirtsio/error'
|
7
|
+
require 'shirtsio/utils'
|
8
|
+
|
9
|
+
require 'shirtsio/configuration'
|
10
|
+
require 'shirtsio/connection'
|
11
|
+
require 'shirtsio/request'
|
12
|
+
require 'shirtsio/api'
|
13
|
+
require 'shirtsio/dsl'
|
14
|
+
require 'shirtsio/endpoint'
|
15
|
+
|
16
|
+
require 'shirtsio/product'
|
17
|
+
require 'shirtsio/quote'
|
18
|
+
require 'shirtsio/order'
|
19
|
+
require 'shirtsio/status'
|
20
|
+
|
21
|
+
module Shirtsio
|
22
|
+
extend Configuration
|
23
|
+
|
24
|
+
def self.api(options = {})
|
25
|
+
Shirtsio::API.new(options)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.method_missing(method, *args, &block)
|
29
|
+
return super unless api.respond_to?(method)
|
30
|
+
api.send(method, *args, &block)
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.respond_to?(method)
|
34
|
+
api.respond_to?(method) || super
|
35
|
+
end
|
36
|
+
end
|
data/lib/shirtsio/api.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module Shirtsio
|
2
|
+
# @private
|
3
|
+
class API
|
4
|
+
attr_accessor *Configuration::VALID_OPTIONS_KEYS
|
5
|
+
|
6
|
+
def initialize(options = {})
|
7
|
+
options = Shirtsio.options.merge(options)
|
8
|
+
Configuration::VALID_OPTIONS_KEYS.each do |key|
|
9
|
+
send("#{key}=", options[key])
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
include Connection
|
14
|
+
include Request
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Shirtsio
|
2
|
+
# Defines constants and methods related to configuration.
|
3
|
+
module Configuration
|
4
|
+
VALID_OPTIONS_KEYS = [
|
5
|
+
:api_key,
|
6
|
+
:endpoint,
|
7
|
+
:proxy,
|
8
|
+
:user_agent
|
9
|
+
].freeze
|
10
|
+
|
11
|
+
# By default, don't set API key.
|
12
|
+
DEFAULT_API_KEY = nil.freeze
|
13
|
+
|
14
|
+
# The endpoint that will be used to authorize a user if none is set.
|
15
|
+
DEFAULT_ENDPOINT = 'https://www.shirts.io/api/v1'.freeze
|
16
|
+
|
17
|
+
# By default, don't set a proxy server
|
18
|
+
DEFAULT_PROXY = nil.freeze
|
19
|
+
|
20
|
+
# The user agent that will be sent to the API endpoint if none is set.
|
21
|
+
DEFAULT_USER_AGENT = "shirtsio gem v#{Shirtsio::VERSION}".freeze
|
22
|
+
|
23
|
+
# @private
|
24
|
+
attr_accessor(*VALID_OPTIONS_KEYS)
|
25
|
+
|
26
|
+
# When this module is extended, set all configuration options to their
|
27
|
+
# default values.
|
28
|
+
def self.extended(base)
|
29
|
+
base.reset
|
30
|
+
end
|
31
|
+
|
32
|
+
# Convenience method to allow configuration options to be set in a
|
33
|
+
# block.
|
34
|
+
def configure
|
35
|
+
yield self
|
36
|
+
end
|
37
|
+
|
38
|
+
# Create a hash of options and their values.
|
39
|
+
def options
|
40
|
+
VALID_OPTIONS_KEYS.inject({}) do |option, key|
|
41
|
+
option.merge!(key => send(key))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Reset all configuration options to default.
|
46
|
+
def reset
|
47
|
+
self.api_key = DEFAULT_API_KEY
|
48
|
+
self.endpoint = DEFAULT_ENDPOINT
|
49
|
+
self.proxy = DEFAULT_PROXY
|
50
|
+
self.user_agent = DEFAULT_USER_AGENT
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Shirtsio
|
2
|
+
# @private
|
3
|
+
module Connection
|
4
|
+
private
|
5
|
+
def connection
|
6
|
+
options = {
|
7
|
+
:ssl => { :verify => true }
|
8
|
+
}
|
9
|
+
Faraday.new(endpoint, options) do |faraday|
|
10
|
+
faraday.request :multipart
|
11
|
+
faraday.request :url_encoded
|
12
|
+
faraday.adapter :net_http
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/shirtsio/dsl.rb
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
class Shirtsio::DSL
|
2
|
+
SIZES = [:xxsml, :xsml, :sml, :med, :lrg, :xlg, :xxl, :xxxl, :xxxxl, :xxxxxl, :xxxxxxl]
|
3
|
+
|
4
|
+
QUOTE = [
|
5
|
+
:print_type,
|
6
|
+
:personalization,
|
7
|
+
:address_count,
|
8
|
+
:extra_screens,
|
9
|
+
:ship_type,
|
10
|
+
:international_garment_count,
|
11
|
+
:garment => [
|
12
|
+
:product_id,
|
13
|
+
:color,
|
14
|
+
:sizes => SIZES
|
15
|
+
],
|
16
|
+
:print => [
|
17
|
+
:front => [:color_count, :colors],
|
18
|
+
:left => [:color_count, :colors],
|
19
|
+
:right => [:color_count, :colors],
|
20
|
+
:back => [:color_count, :colors]
|
21
|
+
]
|
22
|
+
]
|
23
|
+
|
24
|
+
ORDER = [
|
25
|
+
:test,
|
26
|
+
:price,
|
27
|
+
:print_type,
|
28
|
+
:extra_screens,
|
29
|
+
:ship_type,
|
30
|
+
:packing_slip,
|
31
|
+
:garment => [
|
32
|
+
:product_id,
|
33
|
+
:color,
|
34
|
+
:sizes => SIZES
|
35
|
+
],
|
36
|
+
:print => [
|
37
|
+
:front => [:artwork, :proof, :color_count, :colors, :dimensions, :placement],
|
38
|
+
:left => [:artwork, :proof, :color_count, :colors, :dimensions, :placement],
|
39
|
+
:right => [:artwork, :proof, :color_count, :colors, :dimensions, :placement],
|
40
|
+
:back => [:artwork, :proof, :color_count, :colors, :dimensions, :placement]
|
41
|
+
],
|
42
|
+
:personalization => [
|
43
|
+
:size,
|
44
|
+
:batch,
|
45
|
+
:number,
|
46
|
+
:number_size,
|
47
|
+
:name,
|
48
|
+
:name_size
|
49
|
+
],
|
50
|
+
:addresses => [
|
51
|
+
:name,
|
52
|
+
:company,
|
53
|
+
:address,
|
54
|
+
:address2,
|
55
|
+
:city,
|
56
|
+
:state,
|
57
|
+
:zipcode,
|
58
|
+
:country,
|
59
|
+
:batch,
|
60
|
+
:sizes => SIZES
|
61
|
+
]
|
62
|
+
]
|
63
|
+
|
64
|
+
class QueryBuilder
|
65
|
+
def initialize(dsl, prefixes_with_index = [], &block)
|
66
|
+
@dsl = dsl
|
67
|
+
@prefixes_with_index = []
|
68
|
+
@prefixes_with_index << prefixes_with_index
|
69
|
+
@prefixes_with_index.flatten!
|
70
|
+
@params = {}
|
71
|
+
yield self
|
72
|
+
end
|
73
|
+
|
74
|
+
def method_missing(method, *args, &block)
|
75
|
+
index = extract_index(method.to_sym)
|
76
|
+
return super unless index
|
77
|
+
params = {}
|
78
|
+
if index.kind_of?(Symbol)
|
79
|
+
if args[0].kind_of?(Array)
|
80
|
+
args[0].each_with_index do |v,i|
|
81
|
+
params[method] = { i => v }
|
82
|
+
end
|
83
|
+
elsif args[0].kind_of?(File)
|
84
|
+
params[method] = Faraday::UploadIO.new(args[0].path, Shirtsio::Utils.mime_type(args[0].path))
|
85
|
+
else
|
86
|
+
params[method] = args[0]
|
87
|
+
end
|
88
|
+
elsif index.kind_of?(Array)
|
89
|
+
params[method] = QueryBuilder.new(index, @prefixes_with_index, &block).to_hash
|
90
|
+
end
|
91
|
+
params.map do |k,v|
|
92
|
+
if @prefixes_with_index.include?(k)
|
93
|
+
@params[k] = {} if @params[k].nil?
|
94
|
+
@params[k].merge!({ @params[k].size => v })
|
95
|
+
else
|
96
|
+
@params.merge!({ k => v })
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def to_hash
|
102
|
+
@params
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
def extract_index(method)
|
107
|
+
return method if @dsl.include?(method)
|
108
|
+
@dsl.each do |i|
|
109
|
+
if i.kind_of?(Hash) && !i[method].nil?
|
110
|
+
return i[method]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
nil
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class Shirtsio::Endpoint
|
2
|
+
def initialize(json)
|
3
|
+
@mash = Hashie::Mash.new(json)
|
4
|
+
end
|
5
|
+
|
6
|
+
def method_missing(method, *args, &block)
|
7
|
+
return super unless @mash.respond_to?(method)
|
8
|
+
@mash.send(method, *args, &block)
|
9
|
+
end
|
10
|
+
|
11
|
+
def respond_to?(method)
|
12
|
+
@mash.respond_to?(method)
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Shirtsio
|
2
|
+
# Custom error class for rescuing from all known shirts.io errors
|
3
|
+
class Error < StandardError; attr_accessor :result, :error end
|
4
|
+
|
5
|
+
# Raised when shirts.io returns HTTP status code 400
|
6
|
+
class BadRequest < Error; end
|
7
|
+
|
8
|
+
# Raised when shirts.io returns HTTP status code 401
|
9
|
+
class Unauthorized < Error; end
|
10
|
+
|
11
|
+
# Raised when shirts.io returns HTTP status code 402
|
12
|
+
class RequestFailed < Error; end
|
13
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# Place an order.
|
2
|
+
class Shirtsio::Order < Shirtsio::Endpoint
|
3
|
+
# Create an order
|
4
|
+
#
|
5
|
+
# This method specifies a DSL for building the parameters necessary for
|
6
|
+
# creating an order.
|
7
|
+
#
|
8
|
+
# @note See documentation provided by shirts.io for a thorough description of all parameters supported by this endpoint.
|
9
|
+
#
|
10
|
+
# Example:
|
11
|
+
#
|
12
|
+
# Shirtsio::Order.create do |order|
|
13
|
+
# order.test true
|
14
|
+
# order.price 18.99
|
15
|
+
# order.print_type 'Digital Print'
|
16
|
+
# order.extra_screens 'None'
|
17
|
+
# order.ship_type 'Standard'
|
18
|
+
# order.garment do |garment|
|
19
|
+
# garment.product_id 1
|
20
|
+
# garment.color 'Black'
|
21
|
+
# garment.sizes do |size|
|
22
|
+
# size.med 1
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
# order.print do |print|
|
26
|
+
# print.front do |front|
|
27
|
+
# front.artwork ''
|
28
|
+
# front.proof ''
|
29
|
+
# front.color_count 1
|
30
|
+
# front.colors ['Black']
|
31
|
+
# front.dimensions '5.0 inches wide'
|
32
|
+
# front.placement '4.0 inches below bottom of collar'
|
33
|
+
# end
|
34
|
+
# end
|
35
|
+
# order.personalization do |personalization|
|
36
|
+
# personalization.size 'med'
|
37
|
+
# personalization.batch 1
|
38
|
+
# personalization.number 1
|
39
|
+
# personalization.number_size 2
|
40
|
+
# personalization.name 'Bob'
|
41
|
+
# personalization.name_size 1
|
42
|
+
# end
|
43
|
+
# order.addresses do |address|
|
44
|
+
# address.name 'Bob'
|
45
|
+
# address.company 'Sticksnleaves'
|
46
|
+
# address.address '1234 Hopes and Dreams Ln.'
|
47
|
+
# address.address2 'Apt. <3'
|
48
|
+
# address.city 'Indianapolis'
|
49
|
+
# address.state 'IN'
|
50
|
+
# address.country 'US'
|
51
|
+
# address.batch 1
|
52
|
+
# address.sizes do |size|
|
53
|
+
# size.med 1
|
54
|
+
# end
|
55
|
+
# end
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# @see https://www.shirts.io/docs/order_reference/
|
59
|
+
def self.create(&block)
|
60
|
+
query = Shirtsio::DSL::QueryBuilder.new(Shirtsio::DSL::ORDER, [:garment, :personalization, :addresses], &block).to_hash
|
61
|
+
new(Shirtsio.post('/order/', query))
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# Provides specifications, inventory data, and pictures of all products
|
2
|
+
# available before printing.
|
3
|
+
class Shirtsio::Product < Shirtsio::Endpoint
|
4
|
+
# Get product catalog information for a specific product id.
|
5
|
+
#
|
6
|
+
# @return [Shirtsio::Product] a complete product object
|
7
|
+
def self.find(id)
|
8
|
+
new(Shirtsio.get("/products/#{id}/"))
|
9
|
+
end
|
10
|
+
|
11
|
+
class Simple < Shirtsio::Endpoint
|
12
|
+
# Get the complete product object.
|
13
|
+
#
|
14
|
+
# @return [Shirtsio::Product] a complete product object
|
15
|
+
def full_product
|
16
|
+
Shirtsio::Product.find(product_id)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Category < Shirtsio::Endpoint
|
21
|
+
# Get a list of products in the current category.
|
22
|
+
#
|
23
|
+
# @note This endpoint does not return complete product objects
|
24
|
+
# @see {Shirtsio::Product::Simple#full_product}
|
25
|
+
# @return [Array] an array of simple product objects
|
26
|
+
def products
|
27
|
+
products = []
|
28
|
+
response = Shirtsio.get("/products/category/#{category_id}/")
|
29
|
+
response.each do |product|
|
30
|
+
products << Shirtsio::Product::Simple.new(product)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Get a list of all available product categories.
|
35
|
+
#
|
36
|
+
# @return [Array] an array of category objects
|
37
|
+
def self.list
|
38
|
+
categories = []
|
39
|
+
response = Shirtsio.get('/products/category/')
|
40
|
+
response.each do |category|
|
41
|
+
categories << new(category)
|
42
|
+
end
|
43
|
+
categories
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# Provides an exact quote before placing an order.
|
2
|
+
class Shirtsio::Quote < Shirtsio::Endpoint
|
3
|
+
# Get a quote for specified garments.
|
4
|
+
#
|
5
|
+
# This method specifies a DSL for building the parameters necessary for
|
6
|
+
# retrieving a quote.
|
7
|
+
#
|
8
|
+
# @note See documentation provided by shirts.io for a thorough description of all parameters supported by this endpoint.
|
9
|
+
#
|
10
|
+
# Example:
|
11
|
+
#
|
12
|
+
# Shirtsio::Quote.create do |quote|
|
13
|
+
# quote.garment do |garment|
|
14
|
+
# garment.product_id 1
|
15
|
+
# garment.color 'Grey'
|
16
|
+
# garment.sizes do |size|
|
17
|
+
# size.med 1
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
# quote.print do |print|
|
21
|
+
# print.front do |front|
|
22
|
+
# front.color_count 1
|
23
|
+
# front.colors ['Black']
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
# quote.ship_type 'Rush'
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# @see https://www.shirts.io/docs/quote_reference/
|
30
|
+
def self.create(&block)
|
31
|
+
query = Shirtsio::DSL::QueryBuilder.new(Shirtsio::DSL::QUOTE, :garment, &block).to_hash
|
32
|
+
new(Shirtsio.get('/quote/', query))
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Shirtsio
|
2
|
+
module Request
|
3
|
+
def get(path, options = {}, headers = {}, raw = false)
|
4
|
+
request(:get, path, options, headers, raw)
|
5
|
+
end
|
6
|
+
|
7
|
+
def post(path, options = {}, headers = {}, raw = false)
|
8
|
+
request(:post, path, options, headers, raw)
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
# Perform an HTTP request
|
13
|
+
def request(method, path, options, headers, raw)
|
14
|
+
headers.merge!({
|
15
|
+
'User-Agent' => user_agent
|
16
|
+
})
|
17
|
+
|
18
|
+
options.merge!({
|
19
|
+
:api_key => api_key
|
20
|
+
})
|
21
|
+
|
22
|
+
response = connection.send(method) do |request|
|
23
|
+
if method == :get
|
24
|
+
request.url "#{endpoint}#{path}", options
|
25
|
+
else
|
26
|
+
request.url "#{endpoint}#{path}"
|
27
|
+
request.body = options
|
28
|
+
end
|
29
|
+
request.headers = headers
|
30
|
+
end
|
31
|
+
Shirtsio::Utils.handle_api_error(response) if response.status != 200
|
32
|
+
|
33
|
+
if raw
|
34
|
+
result = response.body
|
35
|
+
else
|
36
|
+
# The API is returning the "result" encoded as a string rather than
|
37
|
+
# object notation so it requires a second pass of the JSON parser
|
38
|
+
result = Shirtsio::Utils.parse_json(response.body)[:result]
|
39
|
+
end
|
40
|
+
|
41
|
+
result
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# Retrieves the current state of any previously placed order.
|
2
|
+
class Shirtsio::Status < Shirtsio::Endpoint
|
3
|
+
# Retrieve an order's possible status.
|
4
|
+
#
|
5
|
+
# Possible statuses include:
|
6
|
+
# * Processing - Order was accepted by the API and is being processed
|
7
|
+
# before production.
|
8
|
+
# * Printing - Order is in the production process.
|
9
|
+
# * Shipped - Order has been shipped.
|
10
|
+
# * If an order is shipped or delivered, you will be given tracking
|
11
|
+
# numbers for each package.
|
12
|
+
# * Generally, larget orders are shipped via UPS and smaller orders
|
13
|
+
# are shipped via USPS.
|
14
|
+
# * Delivered - Order has been delivered.
|
15
|
+
# * Canceled - Order has been canceled.
|
16
|
+
# * If an order is canceled, you will be given a reason for
|
17
|
+
# cencellation.
|
18
|
+
# * Possible reasons include: incorrect color count, intellectual
|
19
|
+
# property infringement, out of stock, invalid printing
|
20
|
+
# specifications.
|
21
|
+
#
|
22
|
+
# @param [Integer] id Order identification number
|
23
|
+
# @return [Shirtsio::Status] the order's status
|
24
|
+
# @see https://www.shirts.io/docs/status_reference/
|
25
|
+
def self.find(id)
|
26
|
+
new(Shirtsio.get("/status/#{id}"))
|
27
|
+
end
|
28
|
+
|
29
|
+
# Provides the ability to have status updates pushed to a URL.
|
30
|
+
class Webhook < Shirtsio::Endpoint
|
31
|
+
# Delete the current webhook.
|
32
|
+
#
|
33
|
+
# @return [Boolean] true if successful; otherwise false;
|
34
|
+
# @see https://www.shirts.io/docs/status_reference/#webhooks_section
|
35
|
+
def delete
|
36
|
+
Webhook.delete(url)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Register a new webhook URL.
|
40
|
+
#
|
41
|
+
# @param [String] url URL status updates will be pushed to
|
42
|
+
# @return [Boolean] true if successful; otherwise false
|
43
|
+
# @see https://www.shirts.io/docs/status_reference/#webhooks_section
|
44
|
+
def self.create(url)
|
45
|
+
Shirtsio.post('/webhooks/register/', { :url => url })[:success]
|
46
|
+
end
|
47
|
+
|
48
|
+
# Retrieve all registered webhook URLs.
|
49
|
+
#
|
50
|
+
# @return [Shirtsio::Status::Webhook] a list of registered webhook URLs
|
51
|
+
# @see https://www.shirts.io/docs/status_reference/#webhooks_section
|
52
|
+
def self.list
|
53
|
+
webhooks = []
|
54
|
+
response = new(Shirtsio.get('/webhooks/list/'))
|
55
|
+
if response.respond_to?(:listener_url)
|
56
|
+
response.listener_url.each do |webhook|
|
57
|
+
webhooks << new({ :url => webhook })
|
58
|
+
end
|
59
|
+
end
|
60
|
+
webhooks
|
61
|
+
end
|
62
|
+
|
63
|
+
# Delete a registered webhook URL.
|
64
|
+
#
|
65
|
+
# @param [String] url URL of webhook to be removed
|
66
|
+
# @return [Boolean] true if successful; otherwise false
|
67
|
+
# @see https://www.shirts.io/docs/status_reference/#webhooks_section
|
68
|
+
def self.delete(url)
|
69
|
+
Shirtsio.post('/webhooks/delete/', { :url => url })[:success]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Shirtsio
|
2
|
+
# @private
|
3
|
+
module Utils
|
4
|
+
private
|
5
|
+
def self.handle_api_error(response)
|
6
|
+
result = parse_json(response.body)
|
7
|
+
error = case response.status
|
8
|
+
when 400 then BadRequest.new
|
9
|
+
when 401 then Unauthorized.new
|
10
|
+
when 402 then RequestFailed.new
|
11
|
+
else Error.new
|
12
|
+
end
|
13
|
+
error.result = result[:result]
|
14
|
+
error.error = result[:error]
|
15
|
+
raise error
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.parse_json(json)
|
19
|
+
MultiJson.load(json, :symbolize_keys => true)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.build_query(hash)
|
23
|
+
Faraday::Utils.build_nested_query(hash)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.mime_type(path)
|
27
|
+
case path
|
28
|
+
when /\.jpe?g/i
|
29
|
+
'image/jpeg'
|
30
|
+
when /\.eps$/i
|
31
|
+
'image/eps'
|
32
|
+
when /\.png$/i
|
33
|
+
'image/png'
|
34
|
+
else
|
35
|
+
'application/octet-stream'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/shirtsio.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'shirtsio/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "shirtsio"
|
8
|
+
spec.version = Shirtsio::VERSION
|
9
|
+
spec.authors = ["Anthony Smith"]
|
10
|
+
spec.email = ["anthony@sticksnleaves.com"]
|
11
|
+
spec.description = %q{A shirts.io API wrapper written in Ruby}
|
12
|
+
spec.summary = %q{shirts.io REST API client library for Ruby}
|
13
|
+
spec.homepage = "https://github.com/anthonator/shirtsio"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# Runtime dependencies
|
22
|
+
spec.add_dependency "faraday", "~> 0.8"
|
23
|
+
spec.add_dependency "hashie", "~> 2.0"
|
24
|
+
spec.add_dependency "multi_json", "~> 1.7"
|
25
|
+
end
|
data/spec/dsl_spec.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shirtsio::DSL::QueryBuilder do
|
4
|
+
it "should build a query without an index" do
|
5
|
+
query = Shirtsio::Utils.build_query(Shirtsio::DSL::QueryBuilder.new([:a_method], nil) do |builder|
|
6
|
+
builder.a_method 'value'
|
7
|
+
end.to_hash)
|
8
|
+
query.should == 'a_method=value'
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should build a query with an index" do
|
12
|
+
query = Shirtsio::Utils.build_query(Shirtsio::DSL::QueryBuilder.new([:a_method], :a_method) do |builder|
|
13
|
+
builder.a_method 'value'
|
14
|
+
end.to_hash)
|
15
|
+
URI::unescape(query).should == 'a_method[0]=value'
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should allow for nested methods" do
|
19
|
+
query = Shirtsio::Utils.build_query(Shirtsio::DSL::QueryBuilder.new([:a_method => [:b_method]]) do |builder|
|
20
|
+
builder.a_method do |builder|
|
21
|
+
builder.b_method 'value'
|
22
|
+
end
|
23
|
+
end.to_hash)
|
24
|
+
URI::unescape(query).should == 'a_method[b_method]=value'
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should allow for nested methods with arrays" do
|
28
|
+
query = Shirtsio::Utils.build_query(Shirtsio::DSL::QueryBuilder.new([:a_method => [:b_method]]) do |builder|
|
29
|
+
builder.a_method do |builder|
|
30
|
+
builder.b_method ['value']
|
31
|
+
end
|
32
|
+
end.to_hash)
|
33
|
+
URI::unescape(query).should == 'a_method[b_method][0]=value'
|
34
|
+
end
|
35
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
ENV['RAILS_ENV'] = 'test'
|
2
|
+
|
3
|
+
require 'shirtsio'
|
4
|
+
|
5
|
+
# Require supporting ruby files with custom matchers and macros, etc,
|
6
|
+
# in spec/support/ and its subdirectories.
|
7
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
8
|
+
|
9
|
+
RSpec.configure do |config|
|
10
|
+
|
11
|
+
end
|
metadata
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: shirtsio
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Anthony Smith
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-05-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: faraday
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.8'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.8'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: hashie
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: multi_json
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.7'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.7'
|
55
|
+
description: A shirts.io API wrapper written in Ruby
|
56
|
+
email:
|
57
|
+
- anthony@sticksnleaves.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- .gitignore
|
63
|
+
- Gemfile
|
64
|
+
- LICENSE.txt
|
65
|
+
- README.md
|
66
|
+
- Rakefile
|
67
|
+
- e
|
68
|
+
- lib/shirtsio.rb
|
69
|
+
- lib/shirtsio/api.rb
|
70
|
+
- lib/shirtsio/configuration.rb
|
71
|
+
- lib/shirtsio/connection.rb
|
72
|
+
- lib/shirtsio/dsl.rb
|
73
|
+
- lib/shirtsio/endpoint.rb
|
74
|
+
- lib/shirtsio/error.rb
|
75
|
+
- lib/shirtsio/order.rb
|
76
|
+
- lib/shirtsio/product.rb
|
77
|
+
- lib/shirtsio/quote.rb
|
78
|
+
- lib/shirtsio/request.rb
|
79
|
+
- lib/shirtsio/status.rb
|
80
|
+
- lib/shirtsio/utils.rb
|
81
|
+
- lib/shirtsio/version.rb
|
82
|
+
- shirtsio.gemspec
|
83
|
+
- spec/dsl_spec.rb
|
84
|
+
- spec/spec_helper.rb
|
85
|
+
homepage: https://github.com/anthonator/shirtsio
|
86
|
+
licenses:
|
87
|
+
- MIT
|
88
|
+
metadata: {}
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options: []
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - '>='
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - '>='
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
requirements: []
|
104
|
+
rubyforge_project:
|
105
|
+
rubygems_version: 2.0.0
|
106
|
+
signing_key:
|
107
|
+
specification_version: 4
|
108
|
+
summary: shirts.io REST API client library for Ruby
|
109
|
+
test_files:
|
110
|
+
- spec/dsl_spec.rb
|
111
|
+
- spec/spec_helper.rb
|
112
|
+
has_rdoc:
|