printful_api 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/Gemfile +6 -0
- data/LICENSE +21 -0
- data/README.md +211 -0
- data/VERSION +1 -0
- data/lib/printful_api.rb +65 -0
- data/lib/printful_api/address.rb +9 -0
- data/lib/printful_api/api_operations/create.rb +27 -0
- data/lib/printful_api/api_operations/delete.rb +29 -0
- data/lib/printful_api/api_operations/get.rb +30 -0
- data/lib/printful_api/api_operations/list.rb +35 -0
- data/lib/printful_api/api_operations/save.rb +25 -0
- data/lib/printful_api/api_operations/update.rb +24 -0
- data/lib/printful_api/api_resource.rb +104 -0
- data/lib/printful_api/card_info.rb +9 -0
- data/lib/printful_api/cost.rb +9 -0
- data/lib/printful_api/country.rb +34 -0
- data/lib/printful_api/file.rb +17 -0
- data/lib/printful_api/file_type.rb +9 -0
- data/lib/printful_api/gift_data.rb +9 -0
- data/lib/printful_api/item.rb +14 -0
- data/lib/printful_api/item_option.rb +11 -0
- data/lib/printful_api/option_type.rb +9 -0
- data/lib/printful_api/order.rb +39 -0
- data/lib/printful_api/packing_slip.rb +22 -0
- data/lib/printful_api/product.rb +48 -0
- data/lib/printful_api/product_variant.rb +14 -0
- data/lib/printful_api/shipment.rb +10 -0
- data/lib/printful_api/shipping_rate.rb +29 -0
- data/lib/printful_api/state.rb +9 -0
- data/lib/printful_api/store.rb +29 -0
- data/lib/printful_api/tax_rate.rb +21 -0
- data/lib/printful_api/variant.rb +16 -0
- data/lib/printful_api/version.rb +3 -0
- data/lib/printful_api/webhooks.rb +35 -0
- data/lib/printful_client.rb +144 -0
- data/printful_api.gemspec +18 -0
- metadata +81 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ab40c8602c1fed1d573a8fa4d72a4f30142534df
|
4
|
+
data.tar.gz: c5f7c5ba10a4096a227fb446dd4977dd1dc2ea08
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 255311dbf606b5cf05ddb6b3b5a22dc2fd1854491bc57332952dfa5f78b80d8bb540cd65db6764a06daa72df963ea50bbc21eea5e390758fb6e2fe85d3120375
|
7
|
+
data.tar.gz: 294b885561272ac8aa28ea013baef04f7c006aaf2357629a292d6752b7f02495483c1af97eba857a224b022160eec61e0c0f149647b41db3b2d992068bc43371
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.gem
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2017- Groundswell Enterprises (http://www.groundswellenterprises.com)
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,211 @@
|
|
1
|
+
# Printful API Ruby Bindings
|
2
|
+
|
3
|
+
The Printful API gem provides a ruby bindings SDK for quick and easy access to
|
4
|
+
the Printful service. Printful is a online company that will print custom
|
5
|
+
designs onto a variety of different apparel/accessories, then ship that item
|
6
|
+
with custom packaging directly to your customer. Printful make custom:
|
7
|
+
|
8
|
+
* T-shirts
|
9
|
+
* Sweatshirts
|
10
|
+
* Wall art (prints, posters, canvas, ...)
|
11
|
+
* Mugs
|
12
|
+
* Pillows
|
13
|
+
* Totes
|
14
|
+
* Hats
|
15
|
+
* Leggings
|
16
|
+
* Phone Cases
|
17
|
+
* Socks
|
18
|
+
* Dresses
|
19
|
+
* Skirts
|
20
|
+
* and more
|
21
|
+
|
22
|
+
[Sign up here](https://printful.com/a/amrap) to explore the full list of products, start creating,
|
23
|
+
previewing, and selling your designs.
|
24
|
+
|
25
|
+
We provide a comprehensive list of classes which map to the Printful data model,
|
26
|
+
allowing developers to pull and manipulate data with ease. This gem wraps
|
27
|
+
[the official Printful client library](https://www.printful.com/docs/libraries).
|
28
|
+
|
29
|
+
|
30
|
+
## Installation
|
31
|
+
|
32
|
+
You don't need this source code unless you want to modify the gem. If you just
|
33
|
+
want to use the Printful API Ruby bindings, you should run:
|
34
|
+
|
35
|
+
gem install printful_api
|
36
|
+
|
37
|
+
If you want to build the gem from source:
|
38
|
+
|
39
|
+
gem build printful_api.gemspec
|
40
|
+
|
41
|
+
### Requirements
|
42
|
+
|
43
|
+
* Ruby 1.9.3 or above.
|
44
|
+
* A Printful account, and api key. [Sign up here](https://printful.com/a/amrap)
|
45
|
+
|
46
|
+
### Bundler
|
47
|
+
|
48
|
+
If you are installing via bundler, you should be sure to use the https rubygems
|
49
|
+
source in your Gemfile, as any gems fetched over http could potentially be
|
50
|
+
compromised in transit and alter the code of gems fetched securely over https:
|
51
|
+
|
52
|
+
``` ruby
|
53
|
+
source 'https://rubygems.org'
|
54
|
+
|
55
|
+
gem 'rails'
|
56
|
+
gem 'printful_api'
|
57
|
+
```
|
58
|
+
|
59
|
+
## Usage
|
60
|
+
|
61
|
+
In order to access the Printful API you must first have an api key, which get
|
62
|
+
after creating [a Printful account](https://printful.com/a/amrap). After signing in, go to your
|
63
|
+
[store dashboard](https://www.printful.com/dashboard/store). If you haven't yet
|
64
|
+
create a store, otherwise click on the store to get to the "Update Store" screen.
|
65
|
+
Click on the "API" tab, to get to the "API Access" view. In a box below, there
|
66
|
+
will be a random set of letters and numbers, this is your api key. You will
|
67
|
+
need to assign the api to `PrintfulAPI.api_key` so the gem can give you access
|
68
|
+
to your store.
|
69
|
+
|
70
|
+
Or you can set the api key into the `PRINTFUL_API_KEY` environment variable.
|
71
|
+
|
72
|
+
``` ruby
|
73
|
+
require "printful_api"
|
74
|
+
PrintfulAPI.api_key = "g1n1h..."
|
75
|
+
|
76
|
+
# list all products
|
77
|
+
PrintfulAPI::Product.all
|
78
|
+
|
79
|
+
# get a single order by external ID (your order id)
|
80
|
+
PrintfulAPI::Order.get( '@YOUR_ORDER_ID' )
|
81
|
+
|
82
|
+
|
83
|
+
# get a single order by Printful's order ID
|
84
|
+
PrintfulAPI::Order.get( 342342 )
|
85
|
+
```
|
86
|
+
|
87
|
+
Once assigned, the gem will use it as necessary to authenticate requests for your
|
88
|
+
store.
|
89
|
+
|
90
|
+
## Products / Variations
|
91
|
+
|
92
|
+
``` ruby
|
93
|
+
|
94
|
+
# get a single product, in this case a T-SHIRT
|
95
|
+
product = PrintfulAPI::Product.get(5)
|
96
|
+
|
97
|
+
product.type # "T-SHIRT"
|
98
|
+
product.brand # "American Apparel"
|
99
|
+
product.model # "2001 Fine Jersey Short Sleeve Men T-Shirt"
|
100
|
+
product.image # "https://d1yg28hrivmbqm.cloudfront.net/products/5/product_1483514498.jpg"
|
101
|
+
product.variant_count # 270
|
102
|
+
|
103
|
+
# a list of different file types you can provide for printing, and the cost for using them
|
104
|
+
product.files # FileType[]
|
105
|
+
|
106
|
+
# list the various, some 260+ variations, cut, color, etc
|
107
|
+
product.variants # Variant[]
|
108
|
+
|
109
|
+
# list the different options, options for configuring the process
|
110
|
+
product.options # OptionType[]
|
111
|
+
|
112
|
+
# a list of dimensions for the product
|
113
|
+
product.dimensions # Hash
|
114
|
+
|
115
|
+
```
|
116
|
+
|
117
|
+
|
118
|
+
## Orders
|
119
|
+
|
120
|
+
``` ruby
|
121
|
+
|
122
|
+
order = PrintfulAPI::Order.create( {
|
123
|
+
"recipient": {
|
124
|
+
"name": "John Doe",
|
125
|
+
"address1": "19749 Dearborn St",
|
126
|
+
"city": "Chatsworth",
|
127
|
+
"state_code": "CA",
|
128
|
+
"country_code": "US",
|
129
|
+
"zip": "91311"
|
130
|
+
},
|
131
|
+
"external_id": 'order_1112',
|
132
|
+
"items": [{
|
133
|
+
"variant_id": 1,
|
134
|
+
"quantity": 1,
|
135
|
+
"files": [{
|
136
|
+
"url": "http://example.com/files/posters/poster_1.jpg"
|
137
|
+
}]
|
138
|
+
}]
|
139
|
+
} )
|
140
|
+
|
141
|
+
order.id # 2071687
|
142
|
+
order.external_id # "order_1112"
|
143
|
+
order.status # "draft"
|
144
|
+
order.shipping # "FEDEX_SMART_POST"
|
145
|
+
order.created # 1485550869
|
146
|
+
order.updated # 1485550869
|
147
|
+
order.recipient # PrintfulAPI::Address
|
148
|
+
order.items # PrintfulAPI::Item[]
|
149
|
+
order.costs # PrintfulAPI::Cost
|
150
|
+
order.retail_costs # PrintfulAPI::Cost
|
151
|
+
order.shipments # []
|
152
|
+
order.gift # nil
|
153
|
+
order.packing_slip # nil
|
154
|
+
|
155
|
+
# once all order information is confirmed and correct, run the confirm command
|
156
|
+
# and the store owner will be charged, and the printing begins.
|
157
|
+
order.confirm_for_fulfillment()
|
158
|
+
|
159
|
+
# didn't mean to process the order? delete it and the order will be canceled,
|
160
|
+
# and money returned to the store owner.
|
161
|
+
order.delete()
|
162
|
+
|
163
|
+
```
|
164
|
+
|
165
|
+
## Shipping and Tax Rates
|
166
|
+
|
167
|
+
``` ruby
|
168
|
+
|
169
|
+
# shipping options available for a set of items
|
170
|
+
shipping_rates = PrintfulAPI::ShippingRate.list( { address1: '12372 Carmel Country Rd', city: 'San Diego', country_code: 'US', state_code: 'CA', zip: 92130}, [{quantity: 2, variant_id: PrintfulAPI::Product.get(1).variants.first.id}], 'USD' )
|
171
|
+
|
172
|
+
shipping_rate = shipping_rates.first
|
173
|
+
|
174
|
+
shipping_rate.id # "USPS_FIRST"
|
175
|
+
shipping_rate.name # "USPS First Class Mail (3-5 business days after fulfillment)"
|
176
|
+
shipping_rate.rate # "3.05"
|
177
|
+
shipping_rate.currency # "USD"
|
178
|
+
|
179
|
+
```
|
180
|
+
|
181
|
+
``` ruby
|
182
|
+
|
183
|
+
# tax rates Printful will charge on orders to a specific location
|
184
|
+
tax_rate = PrintfulAPI::TaxRate.get( country_code: 'US', state_code: 'CA', city: 'San Diego', zip: 92130 )
|
185
|
+
tax_rate.required # true
|
186
|
+
tax_rate.rate # 0.775
|
187
|
+
tax_rate.shipping_taxable # false
|
188
|
+
|
189
|
+
```
|
190
|
+
|
191
|
+
## Country/State Lists
|
192
|
+
|
193
|
+
``` ruby
|
194
|
+
|
195
|
+
# list all countries that are valid for Printful shipping. A country and State
|
196
|
+
# core a required for orders, when available from this api.
|
197
|
+
countries = PrintfulAPI::Country.list()
|
198
|
+
country = countries.find{|country| country.code == 'US' }
|
199
|
+
|
200
|
+
# use the code values when referencing a country or state in an order
|
201
|
+
|
202
|
+
country.code # "US"
|
203
|
+
country.name # "United States"
|
204
|
+
|
205
|
+
# a list of states/provinces/regions for that country
|
206
|
+
country.states # State[]
|
207
|
+
|
208
|
+
country.states.first.code # "AA"
|
209
|
+
country.states.first.name # "Armed Forces Americas (except Canada)"
|
210
|
+
|
211
|
+
```
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.0.1
|
data/lib/printful_api.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# Printful Ruby bindings
|
2
|
+
# API spec at https://www.printful.com/docs
|
3
|
+
|
4
|
+
require 'printful_api/version'
|
5
|
+
|
6
|
+
require 'printful_client'
|
7
|
+
|
8
|
+
require 'printful_api/api_resource'
|
9
|
+
require 'printful_api/api_operations/create'
|
10
|
+
require 'printful_api/api_operations/delete'
|
11
|
+
require 'printful_api/api_operations/get'
|
12
|
+
require 'printful_api/api_operations/list'
|
13
|
+
require 'printful_api/api_operations/save'
|
14
|
+
require 'printful_api/api_operations/update'
|
15
|
+
require 'printful_api/address'
|
16
|
+
require 'printful_api/card_info'
|
17
|
+
require 'printful_api/country'
|
18
|
+
require 'printful_api/cost'
|
19
|
+
require 'printful_api/file'
|
20
|
+
require 'printful_api/file_type'
|
21
|
+
require 'printful_api/gift_data'
|
22
|
+
require 'printful_api/item'
|
23
|
+
require 'printful_api/item_option'
|
24
|
+
require 'printful_api/option_type'
|
25
|
+
require 'printful_api/order'
|
26
|
+
require 'printful_api/packing_slip'
|
27
|
+
require 'printful_api/product'
|
28
|
+
require 'printful_api/product_variant'
|
29
|
+
require 'printful_api/shipping_rate'
|
30
|
+
require 'printful_api/state'
|
31
|
+
require 'printful_api/store'
|
32
|
+
require 'printful_api/tax_rate'
|
33
|
+
require 'printful_api/variant'
|
34
|
+
require 'printful_api/webhooks'
|
35
|
+
|
36
|
+
|
37
|
+
|
38
|
+
module PrintfulAPI
|
39
|
+
|
40
|
+
@@client = PrintfulClient.new( ENV['PRINTFUL_API_KEY'] )
|
41
|
+
|
42
|
+
def self.api_key=( api_key )
|
43
|
+
@@client = PrintfulClient.new( api_key )
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.request( method, path, opts = {} )
|
47
|
+
|
48
|
+
# puts "#{method}, #{path}, #{opts}"
|
49
|
+
|
50
|
+
case method.to_s.upcase
|
51
|
+
when "GET"
|
52
|
+
@@client.get(path, opts[:params])
|
53
|
+
when "DELETE"
|
54
|
+
@@client.delete(path, opts[:params])
|
55
|
+
when "POST"
|
56
|
+
@@client.post(path, opts[:data], opts[:params])
|
57
|
+
when "PUT"
|
58
|
+
@@client.put(path, opts[:data], opts[:params])
|
59
|
+
else
|
60
|
+
die()
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module PrintfulAPI
|
2
|
+
|
3
|
+
module APIOperations
|
4
|
+
|
5
|
+
module Create
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.extend(ClassMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
|
13
|
+
def create( data={}, params={} )
|
14
|
+
|
15
|
+
result = PrintfulAPI.request( :POST, params.delete(:resource_path) || self.resource_path, params: params, data: data )
|
16
|
+
|
17
|
+
self.new.load_data( result )
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module PrintfulAPI
|
2
|
+
|
3
|
+
module APIOperations
|
4
|
+
|
5
|
+
module Delete
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.extend(ClassMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
|
13
|
+
def delete( id, opts={} )
|
14
|
+
|
15
|
+
PrintfulAPI.request( :DELETE, "#{opts.delete(:resource_path) || self.resource_path}/#{id}" )
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def delete()
|
22
|
+
self.class.delete( self.id )
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module PrintfulAPI
|
2
|
+
|
3
|
+
module APIOperations
|
4
|
+
|
5
|
+
module Get
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.extend(ClassMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
|
13
|
+
def get( id, opts={} )
|
14
|
+
|
15
|
+
data = PrintfulAPI.request( :GET, "#{opts.delete(:resource_path) || self.resource_path}/#{id}" )
|
16
|
+
|
17
|
+
model = self.new
|
18
|
+
model.load_data( data )
|
19
|
+
|
20
|
+
model
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module PrintfulAPI
|
2
|
+
|
3
|
+
module APIOperations
|
4
|
+
|
5
|
+
module List
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.extend(ClassMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
|
13
|
+
def list( filters={}, opts={} )
|
14
|
+
|
15
|
+
data_list = PrintfulAPI.request( :GET, opts.delete(:resource_path) || self.resource_path, params: filters )
|
16
|
+
|
17
|
+
data_list.collect do |data|
|
18
|
+
|
19
|
+
model = self.new
|
20
|
+
model.load_data( data )
|
21
|
+
|
22
|
+
model
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
alias :all :list
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module PrintfulAPI
|
2
|
+
|
3
|
+
module APIOperations
|
4
|
+
|
5
|
+
module Save
|
6
|
+
|
7
|
+
def save( opts = {} )
|
8
|
+
|
9
|
+
if self.id.present?
|
10
|
+
|
11
|
+
self.class.update( self.to_h, opts )
|
12
|
+
|
13
|
+
else
|
14
|
+
|
15
|
+
self.class.create( self.to_h, opts )
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module PrintfulAPI
|
2
|
+
|
3
|
+
module APIOperations
|
4
|
+
|
5
|
+
module Update
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.extend(ClassMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
|
13
|
+
def update( id, data={}, params={} )
|
14
|
+
|
15
|
+
PrintfulAPI.request( :PUT, "#{self.resource_path}/#{id}", params: params, data: data )
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module PrintfulAPI
|
2
|
+
class APIResource
|
3
|
+
|
4
|
+
attr_accessor :raw_data
|
5
|
+
|
6
|
+
class << self; attr_accessor :api_attribute_list end
|
7
|
+
|
8
|
+
|
9
|
+
def self.api_attributes( *args )
|
10
|
+
self.api_attribute_list = (self.api_attribute_list || []).concat(args)
|
11
|
+
|
12
|
+
attr_accessor *args
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.has_many( attribute_name, args = {} )
|
16
|
+
args[:class] = args[:class] if args[:class].is_a? String
|
17
|
+
args[:class] ||= "PrintfulAPI::#{APIResource.singularize( APIResource.camelize(attribute_name.to_s ) )}"
|
18
|
+
|
19
|
+
self.api_attributes *[attribute_name.to_sym]
|
20
|
+
|
21
|
+
define_method("#{attribute_name}=") do |array|
|
22
|
+
if array.present?
|
23
|
+
array = array.collect do |data|
|
24
|
+
args[:class].constantize.new.load_data(data)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
self.instance_variable_set("@#{attribute_name}", array)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.belongs_to( attribute_name, args = {} )
|
32
|
+
args[:class] = args[:class] if args[:class].is_a? String
|
33
|
+
args[:class] ||= "PrintfulAPI::#{APIResource.camelize( attribute_name.to_s )}"
|
34
|
+
args[:foreign_key] ||= "#{attribute_name}_id"
|
35
|
+
|
36
|
+
self.api_attributes *[attribute_name.to_sym]
|
37
|
+
|
38
|
+
define_method("#{attribute_name}") do
|
39
|
+
attribute_value = self.instance_variable_get( "@#{attribute_name}" )
|
40
|
+
attribute_value ||= args[:class].new.get( args[:foreign_key] ) if self.respond_to?( args[:foreign_key] )
|
41
|
+
self.instance_variable_set( "@#{attribute_name}", attribute_value )
|
42
|
+
end
|
43
|
+
|
44
|
+
define_method("#{attribute_name}=") do |data|
|
45
|
+
if data.is_a?(PrintfulAPI::APIResource)
|
46
|
+
self.instance_variable_set("@#{attribute_name}", data)
|
47
|
+
else
|
48
|
+
model = args[:class].constantize.new.load_data(data) if data.present?
|
49
|
+
self.instance_variable_set( "@#{attribute_name}", model )
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def load_data( data )
|
55
|
+
self.raw_data = data
|
56
|
+
data.each do |key,value|
|
57
|
+
|
58
|
+
if self.respond_to? "#{key}="
|
59
|
+
self.send("#{key}=", value)
|
60
|
+
else
|
61
|
+
puts "Accessor doesn't exist #{self.class.name}\##{"#{key}="}"
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
self
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
def to_h()
|
71
|
+
hash = {}
|
72
|
+
self.class.api_attribute_list.each do |attribute_name|
|
73
|
+
value = self.send(attribute_name)
|
74
|
+
if value.is_a? Array
|
75
|
+
|
76
|
+
hash[attribute_name] = value.collect do |array_item|
|
77
|
+
if array_item.is_a? APIResource
|
78
|
+
hash[attribute_name] = array_item.to_h
|
79
|
+
else
|
80
|
+
hash[attribute_name] = array_item
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
elsif value.is_a? APIResource
|
85
|
+
hash[attribute_name] = value.to_h
|
86
|
+
else
|
87
|
+
hash[attribute_name] = value
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
hash
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.camelize( str )
|
95
|
+
str.split('_').map {|w| w.capitalize}.join
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.singularize( str )
|
99
|
+
str = str[0..-2] if str[-1] == 's'
|
100
|
+
str
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module PrintfulAPI
|
2
|
+
|
3
|
+
class Country < APIResource
|
4
|
+
include PrintfulAPI::APIOperations::List
|
5
|
+
|
6
|
+
api_attributes :code, :name
|
7
|
+
has_many :states
|
8
|
+
|
9
|
+
def self.list( filters={}, opts={} )
|
10
|
+
taxable = filters.delete(:taxable)
|
11
|
+
|
12
|
+
puts "Country.list taxable: #{taxable}, #{filters}, #{opts}"
|
13
|
+
|
14
|
+
if taxable
|
15
|
+
super( filters, opts.merge( resource_path: '/tax/countries' ) )
|
16
|
+
else
|
17
|
+
super( filters, opts )
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def states
|
22
|
+
@states
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.resource_path
|
26
|
+
'/countries'
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module PrintfulAPI
|
2
|
+
|
3
|
+
class File < APIResource
|
4
|
+
include PrintfulAPI::APIOperations::List
|
5
|
+
include PrintfulAPI::APIOperations::Create
|
6
|
+
include PrintfulAPI::APIOperations::Get
|
7
|
+
|
8
|
+
api_attributes :id, :type, :hash, :url, :filename, :mime_type, :size, :width, :height, :dpi, :status, :created, :thumbnail_url, :preview_url, :visible
|
9
|
+
|
10
|
+
|
11
|
+
def self.resource_path
|
12
|
+
'/files'
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module PrintfulAPI
|
2
|
+
|
3
|
+
class Item < APIResource
|
4
|
+
|
5
|
+
|
6
|
+
api_attributes :id, :external_id, :variant_id, :quantity, :price, :retail_price, :name, :sku
|
7
|
+
has_many :files
|
8
|
+
has_many :options, class: 'PrintfulAPI::ItemOption'
|
9
|
+
belongs_to :product, class: 'PrintfulAPI::ProductVariant'
|
10
|
+
# belongs_to :variant
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module PrintfulAPI
|
2
|
+
|
3
|
+
class Order < APIResource
|
4
|
+
include PrintfulAPI::APIOperations::Create
|
5
|
+
include PrintfulAPI::APIOperations::Delete
|
6
|
+
include PrintfulAPI::APIOperations::Get
|
7
|
+
include PrintfulAPI::APIOperations::List
|
8
|
+
include PrintfulAPI::APIOperations::Update
|
9
|
+
include PrintfulAPI::APIOperations::Save
|
10
|
+
|
11
|
+
api_attributes :id, :external_id, :status, :created, :updated, :costs, :shipping, :currency
|
12
|
+
belongs_to :recipient, class: 'PrintfulAPI::Address'
|
13
|
+
has_many :items
|
14
|
+
belongs_to :costs, class: 'PrintfulAPI::Cost'
|
15
|
+
belongs_to :retail_costs, class: 'PrintfulAPI::Cost'
|
16
|
+
belongs_to :gift, class: 'PrintfulAPI::GiftData'
|
17
|
+
belongs_to :packing_slip
|
18
|
+
has_many :shipments
|
19
|
+
|
20
|
+
|
21
|
+
def self.resource_path
|
22
|
+
'/orders'
|
23
|
+
end
|
24
|
+
|
25
|
+
# Confirm draft for fulfillment
|
26
|
+
# Approves for fulfillment an order that was saved as a draft. Store owner's credit card is charged when the order is submitted for fulfillment.
|
27
|
+
def confirm_for_fulfillment
|
28
|
+
|
29
|
+
result = PrintfulAPI.request( :POST, "/orders/#{self.id}/confirm", {} )
|
30
|
+
|
31
|
+
self.load_data( result )
|
32
|
+
|
33
|
+
return true
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module PrintfulAPI
|
2
|
+
|
3
|
+
class PackingSlip < APIResource
|
4
|
+
include APIOperations::Create
|
5
|
+
|
6
|
+
api_attributes :email, :phone, :message
|
7
|
+
|
8
|
+
def self.get( opts={} )
|
9
|
+
|
10
|
+
store = Store.get()
|
11
|
+
|
12
|
+
store.packing_slip
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.resource_path
|
17
|
+
'/store/packing-slip'
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module PrintfulAPI
|
2
|
+
|
3
|
+
class Product < APIResource
|
4
|
+
include PrintfulAPI::APIOperations::List
|
5
|
+
include PrintfulAPI::APIOperations::Get
|
6
|
+
|
7
|
+
api_attributes :id, :type, :brand, :model, :image, :variant_count, :dimensions
|
8
|
+
|
9
|
+
# has_many :allowed_files, class: 'PrintfulAPI::FileType'
|
10
|
+
has_many :files, class: 'PrintfulAPI::FileType'
|
11
|
+
# has_many :allowed_options, class: 'PrintfulAPI::OptionType'
|
12
|
+
has_many :options, class: 'PrintfulAPI::OptionType'
|
13
|
+
|
14
|
+
def variants
|
15
|
+
@variants ||= PrintfulAPI::Variant.list( product_id: self.id )
|
16
|
+
@variants
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.resource_path
|
20
|
+
'/products'
|
21
|
+
end
|
22
|
+
|
23
|
+
def load_data( data )
|
24
|
+
|
25
|
+
if data['product'].present?
|
26
|
+
|
27
|
+
super(data['product'])
|
28
|
+
|
29
|
+
@variants = data['variants'].collect do |variant_data|
|
30
|
+
variant = PrintfulAPI::Variant.new.load_data( variant_data )
|
31
|
+
variant.product = self
|
32
|
+
variant
|
33
|
+
end
|
34
|
+
|
35
|
+
else
|
36
|
+
|
37
|
+
super( data )
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module PrintfulAPI
|
2
|
+
|
3
|
+
class ShippingRate < APIResource
|
4
|
+
|
5
|
+
api_attributes :id, :name, :rate, :currency
|
6
|
+
|
7
|
+
# PrintfulAPI::ShippingRate.list( { address1: '12372 Carmel Country Rd', city: 'San Diego', country_code: 'US', state_code: 'CA', zip: 92130}, [{quantity: 2, variant_id: PrintfulAPI::Product.get(1).variants.first.id}], 'USD' )
|
8
|
+
def self.list( recipient = {}, items = [], currency = 'USD', opts = {} )
|
9
|
+
|
10
|
+
request_data = {
|
11
|
+
recipient: recipient,
|
12
|
+
items: items,
|
13
|
+
currency: currency
|
14
|
+
}
|
15
|
+
|
16
|
+
results = PrintfulAPI.request( :POST, "/shipping/rates", data: request_data, params: opts )
|
17
|
+
|
18
|
+
results.collect do |data|
|
19
|
+
model = self.new
|
20
|
+
model.load_data( data )
|
21
|
+
|
22
|
+
model
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module PrintfulAPI
|
2
|
+
|
3
|
+
class Store < APIResource
|
4
|
+
|
5
|
+
api_attributes :id, :name, :website, :created
|
6
|
+
belongs_to :packing_slip
|
7
|
+
belongs_to :return_address, class: 'PrintfulAPI::Address'
|
8
|
+
belongs_to :billing_address, class: 'PrintfulAPI::Address'
|
9
|
+
belongs_to :payment_card, class: 'PrintfulAPI::CardInfo'
|
10
|
+
|
11
|
+
|
12
|
+
def self.get( opts={} )
|
13
|
+
|
14
|
+
data = PrintfulAPI.request( :GET, self.resource_path )
|
15
|
+
|
16
|
+
model = self.new
|
17
|
+
model.load_data( data )
|
18
|
+
|
19
|
+
model
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.resource_path
|
24
|
+
'/store'
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module PrintfulAPI
|
2
|
+
|
3
|
+
class TaxRate < APIResource
|
4
|
+
|
5
|
+
api_attributes :required, :rate, :shipping_taxable
|
6
|
+
|
7
|
+
# PrintfulAPI::TaxRate.get( country_code: 'US', state_code: 'CA', city: 'San Diego', zip: 92130 )
|
8
|
+
def self.get( recipient = {}, opts = {} )
|
9
|
+
|
10
|
+
data = PrintfulAPI.request( :POST, "/tax/rates", data: { recipient: recipient }, params: opts )
|
11
|
+
|
12
|
+
model = self.new
|
13
|
+
model.load_data( data )
|
14
|
+
|
15
|
+
model
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module PrintfulAPI
|
2
|
+
|
3
|
+
class Variant < APIResource
|
4
|
+
include PrintfulAPI::APIOperations::Get
|
5
|
+
|
6
|
+
api_attributes :id, :product_id, :name, :size, :color, :color_code, :image, :price, :in_stock
|
7
|
+
|
8
|
+
belongs_to :product
|
9
|
+
|
10
|
+
def self.resource_path
|
11
|
+
'/products/variant'
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module PrintfulAPI
|
2
|
+
|
3
|
+
class Webhook < APIResource
|
4
|
+
include PrintfulAPI::APIOperations::Create
|
5
|
+
|
6
|
+
api_attributes :url, :types, :params
|
7
|
+
|
8
|
+
def self.get( opts={} )
|
9
|
+
|
10
|
+
data = PrintfulAPI.request( :GET, self.resource_path )
|
11
|
+
|
12
|
+
model = self.new
|
13
|
+
model.load_data( data )
|
14
|
+
|
15
|
+
model
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.delete( opts={} )
|
20
|
+
|
21
|
+
PrintfulAPI.request( :DELETE, self.resource_path )
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
def delete
|
26
|
+
self.class.delete()
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.resource_path
|
30
|
+
'/webhooks'
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
##
|
2
|
+
#
|
3
|
+
# This class helps to use the Printful API
|
4
|
+
#
|
5
|
+
# version 1.0
|
6
|
+
# copyright 2014 Idea Bits LLC
|
7
|
+
#
|
8
|
+
##
|
9
|
+
|
10
|
+
require 'net/http'
|
11
|
+
require 'json'
|
12
|
+
require 'uri'
|
13
|
+
|
14
|
+
module PrintfulClientModule
|
15
|
+
|
16
|
+
API_URL = 'https://api.theprintful.com/'
|
17
|
+
USER_AGENT = 'Printful API Ruby Library 1.0'
|
18
|
+
|
19
|
+
@api_key
|
20
|
+
@last_response_raw
|
21
|
+
@last_response
|
22
|
+
|
23
|
+
|
24
|
+
# Initialize API library
|
25
|
+
# key - Printful Store API key
|
26
|
+
def initialize(key)
|
27
|
+
@api_key = key
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
# Returns total available item count from the last request if it supports paging (e.g order list) or nil otherwise
|
32
|
+
def item_count
|
33
|
+
return last_response && last_response.key?('paging') ? last_response['paging']['total'] : nil
|
34
|
+
end
|
35
|
+
|
36
|
+
# Perform a GET request to the API
|
37
|
+
# path - Request path (e.g. 'orders' or 'orders/123')
|
38
|
+
# params - Additional GET parameters as a hash
|
39
|
+
def get(path, params=nil)
|
40
|
+
request('GET', path, params)
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
# Perform a DELETE request to the API
|
45
|
+
# path - Request path (e.g. 'orders' or 'orders/123')
|
46
|
+
# params - Additional GET parameters as a hash
|
47
|
+
def delete(path, params=nil)
|
48
|
+
request('DELETE', path, params)
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
# Perform a POST request to the API
|
53
|
+
# path - Request path (e.g. 'orders' or 'orders/123')
|
54
|
+
# data - Request body data as a hash
|
55
|
+
# params - Additional GET parameters as a hash
|
56
|
+
def post(path, data=nil, params=nil)
|
57
|
+
request('POST', path, params, data)
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
# Perform a PUT request to the API
|
62
|
+
# path - Request path (e.g. 'orders' or 'orders/123')
|
63
|
+
# data - Request body data as a hash
|
64
|
+
# params - Additional GET parameters as a hash
|
65
|
+
def put(path, data=nil, params=nil)
|
66
|
+
request('PUT', path, params, data)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Internal generic request wrapper
|
70
|
+
def request (method, path, params=nil, data=nil)
|
71
|
+
|
72
|
+
@last_response_raw = nil
|
73
|
+
@last_response = nil
|
74
|
+
|
75
|
+
uri = URI.join(API_URL, path)
|
76
|
+
if params
|
77
|
+
query = URI.encode_www_form(params)
|
78
|
+
uri.query = query
|
79
|
+
end
|
80
|
+
|
81
|
+
body = data ? JSON.generate(data) : nil
|
82
|
+
|
83
|
+
headers = {
|
84
|
+
'User-Agent' => USER_AGENT
|
85
|
+
}
|
86
|
+
begin
|
87
|
+
http = Net::HTTP.start(
|
88
|
+
uri.host,
|
89
|
+
uri.port,
|
90
|
+
:use_ssl => uri.scheme=='https',
|
91
|
+
:open_timeout => 10,
|
92
|
+
:read_timeout => 20
|
93
|
+
) do |http|
|
94
|
+
|
95
|
+
request = Net::HTTPGenericRequest.new(method,(body ? true : false), true, uri.request_uri ,headers)
|
96
|
+
request.basic_auth @api_key, ''
|
97
|
+
response = http.request(request, body)
|
98
|
+
|
99
|
+
@last_response_raw = response.body
|
100
|
+
|
101
|
+
begin
|
102
|
+
result = JSON.parse(response.body)
|
103
|
+
@last_response = result
|
104
|
+
rescue JSON::ParserError
|
105
|
+
raise PrintfulException, "API response was not valid JSON"
|
106
|
+
end
|
107
|
+
|
108
|
+
if !result.key?('code') || !result.key?('result')
|
109
|
+
raise PrintfulException, "Invalid API response"
|
110
|
+
end
|
111
|
+
|
112
|
+
status = result['code']
|
113
|
+
if status<200 || status >=300
|
114
|
+
raise PrintfulApiException.new(status), result['result']
|
115
|
+
end
|
116
|
+
|
117
|
+
result['result']
|
118
|
+
end
|
119
|
+
rescue PrintfulException
|
120
|
+
raise
|
121
|
+
rescue Exception => e
|
122
|
+
raise PrintfulException, 'API request failed: ' + e.message
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
private :request
|
127
|
+
attr_accessor :last_response, :last_response_raw
|
128
|
+
end
|
129
|
+
|
130
|
+
class PrintfulClient
|
131
|
+
include PrintfulClientModule
|
132
|
+
end
|
133
|
+
|
134
|
+
# Generic Printful exception
|
135
|
+
class PrintfulException < RuntimeError
|
136
|
+
end
|
137
|
+
|
138
|
+
# Printful exception returned from the API
|
139
|
+
class PrintfulApiException < PrintfulException
|
140
|
+
def initialize(code)
|
141
|
+
@code = code
|
142
|
+
end
|
143
|
+
attr_accessor :code
|
144
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
$:.unshift(File.join(File.dirname(__FILE__), 'lib'))
|
2
|
+
|
3
|
+
require 'printful_api/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'printful_api'
|
7
|
+
s.version = PrintfulAPI::VERSION
|
8
|
+
s.date = '2017-01-25'
|
9
|
+
s.summary = "Ruby bindings for the Printful API"
|
10
|
+
s.description = "Printful is the easiest way to sell, print and ship custom posters, shirts, mugs, pillows, leggings, totes ..."
|
11
|
+
s.authors = ["Michael Ferguson"]
|
12
|
+
s.email = 'meister@spacekace.com'
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
s.require_paths = ['lib']
|
15
|
+
s.homepage = 'https://github.com/Groundswell/printful-ruby'
|
16
|
+
s.license = 'MIT'
|
17
|
+
s.required_ruby_version = '>= 1.9.3'
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: printful_api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Michael Ferguson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-01-25 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Printful is the easiest way to sell, print and ship custom posters, shirts,
|
14
|
+
mugs, pillows, leggings, totes ...
|
15
|
+
email: meister@spacekace.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- ".gitignore"
|
21
|
+
- Gemfile
|
22
|
+
- LICENSE
|
23
|
+
- README.md
|
24
|
+
- VERSION
|
25
|
+
- lib/printful_api.rb
|
26
|
+
- lib/printful_api/address.rb
|
27
|
+
- lib/printful_api/api_operations/create.rb
|
28
|
+
- lib/printful_api/api_operations/delete.rb
|
29
|
+
- lib/printful_api/api_operations/get.rb
|
30
|
+
- lib/printful_api/api_operations/list.rb
|
31
|
+
- lib/printful_api/api_operations/save.rb
|
32
|
+
- lib/printful_api/api_operations/update.rb
|
33
|
+
- lib/printful_api/api_resource.rb
|
34
|
+
- lib/printful_api/card_info.rb
|
35
|
+
- lib/printful_api/cost.rb
|
36
|
+
- lib/printful_api/country.rb
|
37
|
+
- lib/printful_api/file.rb
|
38
|
+
- lib/printful_api/file_type.rb
|
39
|
+
- lib/printful_api/gift_data.rb
|
40
|
+
- lib/printful_api/item.rb
|
41
|
+
- lib/printful_api/item_option.rb
|
42
|
+
- lib/printful_api/option_type.rb
|
43
|
+
- lib/printful_api/order.rb
|
44
|
+
- lib/printful_api/packing_slip.rb
|
45
|
+
- lib/printful_api/product.rb
|
46
|
+
- lib/printful_api/product_variant.rb
|
47
|
+
- lib/printful_api/shipment.rb
|
48
|
+
- lib/printful_api/shipping_rate.rb
|
49
|
+
- lib/printful_api/state.rb
|
50
|
+
- lib/printful_api/store.rb
|
51
|
+
- lib/printful_api/tax_rate.rb
|
52
|
+
- lib/printful_api/variant.rb
|
53
|
+
- lib/printful_api/version.rb
|
54
|
+
- lib/printful_api/webhooks.rb
|
55
|
+
- lib/printful_client.rb
|
56
|
+
- printful_api.gemspec
|
57
|
+
homepage: https://github.com/Groundswell/printful-ruby
|
58
|
+
licenses:
|
59
|
+
- MIT
|
60
|
+
metadata: {}
|
61
|
+
post_install_message:
|
62
|
+
rdoc_options: []
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 1.9.3
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
requirements: []
|
76
|
+
rubyforge_project:
|
77
|
+
rubygems_version: 2.5.2
|
78
|
+
signing_key:
|
79
|
+
specification_version: 4
|
80
|
+
summary: Ruby bindings for the Printful API
|
81
|
+
test_files: []
|