printfection 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 988cf5fbd90dab60a47312201529a4a7c2b4c8db
4
+ data.tar.gz: 1ad04c530a77b106a8e0fe8c9a834d8eda1e4a48
5
+ SHA512:
6
+ metadata.gz: e609441046a5bd41cfbce861c1c296257104b3ce6b1c233f40fb59125794b8dc8cf7f89c108f0e350df301b8695bd0b770ae8b97f1055555bc036a54cf120730
7
+ data.tar.gz: a79796194853ee8cedfa0bdf06f06e4f348dc03fa73b64d2132fea0372a68028556bab67d8710ba5a3983183885953c99aa3600e20a8c3a537b16c1be7b4571b
data/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ .DS_Store
16
+
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,14 @@
1
+ language: ruby
2
+ rvm:
3
+ - ruby-head
4
+ - ruby-2.0.0-p598
5
+ - ruby-1.9.3-p551
6
+ - jruby-head
7
+ - jruby-19mode
8
+ notifications:
9
+ recipients:
10
+ - rubygems@printfection.com
11
+ addons:
12
+ code_climate:
13
+ repo_token: f5302e71ac67e807b7762e7ac743d2779841a422ab5c2cf1e7c7c34b6c080881
14
+
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Printfection LLC
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,247 @@
1
+ # Printfection Ruby API [![Build Status](https://travis-ci.org/Printfection/printfection-ruby.png?branch=prerelease)](https://travis-ci.org/Printfection/printfection-ruby) [![Code Climate](https://codeclimate.com/github/Printfection/printfection-ruby/badges/gpa.svg)](https://codeclimate.com/github/Printfection/printfection-ruby) [![Test Coverage](https://codeclimate.com/github/Printfection/printfection-ruby/badges/coverage.svg)](https://codeclimate.com/github/Printfection/printfection-ruby)
2
+
3
+ Implementation of the [Printfection API](http://printfection.github.io/API-Documentation) for Ruby.
4
+
5
+ At a high level, the Printfection API can be used to create, modify, place, and cancel orders. `Orders` are made up of a set of line items and a shipping address, but orders also expose detailed information about their products, sizes, assets, quantities, and availability.
6
+
7
+ `Campaigns` are logical groups of items used to organize your orders. Orders are always associated to exactly one campaign, and only items associated to a given campaign can be placed in an order in the same campaign. For example, your company's marketing department might have a Giveaway campaign with coffee mugs to reward loyal customers, and your engineering department might have a Purchase campaign with nerdy swag to outfit new hires.
8
+
9
+ Some campaigns have special abilities. Orders in `giveaway` and `freeforall` campaigns have a code and a web URL that can be used to redeem (i.e. place) that order. Orders in `freeforall` campaigns can be a gift and include a gift message.
10
+
11
+ You can read the full API documentation and object reference [here](http://printfection.github.io/API-Documentation/#campaigns).
12
+
13
+
14
+ ## Installation
15
+
16
+ Add this line to your application's Gemfile:
17
+
18
+ ```ruby
19
+ gem 'printfection'
20
+ ```
21
+
22
+ And then execute:
23
+
24
+ $ bundle
25
+
26
+ Or install it yourself as:
27
+
28
+ $ gem install printfection
29
+
30
+
31
+ ## Usage
32
+
33
+ First, configure your API token. This can be found in your account on [printfection.com](http://printfection.com).
34
+
35
+ ```ruby
36
+ require "printfection"
37
+
38
+ Printfection.api_token = "e3ce1ddf152d5533ca4a3d3543006bac6d57b2ac"
39
+ ```
40
+
41
+ If you're using Rails, `config/initializers/printfection.rb` is a good place for this.
42
+
43
+ ### Retrieving an order
44
+
45
+ ```ruby
46
+ order = Printfection::Order.retrieve(5)
47
+ ```
48
+
49
+ ### Listing all orders
50
+
51
+ ```ruby
52
+ orders = Printfection::Order.all
53
+ orders = Printfection::Order.all limit: 5, offset: 10
54
+ ```
55
+
56
+ By default, list calls are automatically paginated and limited to 100 objects per request.
57
+
58
+
59
+ ### Creating an order
60
+
61
+ At a minimum, a new order can be created with just a `campaign_id`:
62
+
63
+ ```ruby
64
+ order = Printfection::Order.create(campaign_id: 1)
65
+ #=> #<Printfection::Order id: 1, campaign_id: 1>
66
+ ```
67
+
68
+ Once you have created an order, you can then begin adding line items. A line item requires an `item_id`, `quantity`, and a `size_id` if the item has sizes.
69
+
70
+ ```ruby
71
+ # Creating a line item with a size.
72
+ order.line_items.create(
73
+ item_id: 1,
74
+ size_id: 2,
75
+ quantity: 3
76
+ )
77
+ #=> #<Printfection::LineItem id: 1, order_id: 1, item_id: 1, size_id: 2, quantity: 3>
78
+
79
+ # Creating a line item without a size.
80
+ order.line_items.create(
81
+ item_id: 2,
82
+ quantity: 6
83
+ )
84
+ #=> #<Printfection::LineItem id: 2, order_id: 1, item_id: 2, quantity: 6>
85
+
86
+ ```
87
+
88
+ You can retrieve existing line items to update them:
89
+
90
+ ```ruby
91
+ line_item = order.line_items.retrieve(1)
92
+ #=> #<Printfection::LineItem id: 1, order_id: 1, item_id: 1, quantity: 3>
93
+
94
+ line_item.quantity = 12
95
+ line_item.save
96
+ #=> true
97
+
98
+ line_item.quantity
99
+ #=> 12
100
+ ```
101
+
102
+ And delete them:
103
+
104
+ ```ruby
105
+ line_item = order.line_items.retrieve(2)
106
+ #=> #<Printfection::LineItem id: 2, order_id: 1, item_id: 2, quantity: 6>
107
+
108
+ line_item.delete
109
+ #=> true
110
+ ```
111
+
112
+ Provide a shipping address for the order.
113
+
114
+ ```ruby
115
+ order = Printfection::Order.retrieve(1)
116
+ #=> #<Printfection::Order id: 1 ...>
117
+
118
+ order.ship_to = {
119
+ name: "Joseph Schmo",
120
+ address: "123 Main Street",
121
+ address2: "Suite 101",
122
+ company: "ACME Inc.",
123
+ city: "Denver",
124
+ state: "Colorado",
125
+ zip: "80202",
126
+ country: "United States"
127
+ }
128
+
129
+ order.save
130
+ #=> true
131
+ ```
132
+
133
+ Whoops, that should be shipped to Sally.
134
+
135
+ ```ruby
136
+ order.ship_to.name = "Sally Schmo"
137
+ order.save
138
+ #=> true
139
+ ```
140
+
141
+ Finally, when you are finished building the order, place it:
142
+
143
+ ```ruby
144
+ order = Printfection::Order.retrieve(1)
145
+ order.place
146
+ #=> true
147
+ ```
148
+
149
+ Or cancel it:
150
+
151
+ ```ruby
152
+ order = Printfection::Order.retrieve(1)
153
+ order.cancel
154
+ #=> true
155
+ ```
156
+
157
+
158
+ ### Retrieving an item
159
+
160
+ ```ruby
161
+ item = Printfection::Item.retrieve(1)
162
+ #=> #<Printfection::Item id: 1 ...>
163
+
164
+ item.name #=> "My Awesome T-Shirt"
165
+ item.color #=> "Green"
166
+ item.product.name #=> "American Apparel 50/50 T-Shirt"
167
+
168
+ item.campaigns
169
+ #=> [#<Printfection::Campaign id: 1 ...>, #<Printfection::Campaign id: 2 ...>]
170
+
171
+ item.sizes
172
+ #=> [#<Printfection::Size id: 1 ...>, #<Printfection::Size id: 2 ...>]
173
+
174
+ item.assets
175
+ #=> [#<Printfection::Asset id: 1 ...>, #<Printfection::Asset id: 2 ...>]
176
+
177
+ ```
178
+
179
+ ### Listing all items
180
+
181
+ ```ruby
182
+ items = Printfection::Items.all
183
+ #=> [#<Printfection::Item id: 1 ...>, #<Printfection::Item id: 2 ...>]
184
+ ```
185
+
186
+ ### Retrieving a campaign
187
+
188
+ ```ruby
189
+ campaign = Printfection::Campaign.retrieve(1)
190
+ #=> #<Printfection::Campaign id: 1 ...>
191
+
192
+ campaign.name #=> "My Awesome T-Shirt"
193
+ campaign.type #=> "giveaway"
194
+ campaign.name #=> "My Awesome Giveaway Campaign"
195
+ campaign.active #=> true
196
+
197
+ ```
198
+
199
+ ### Listing all campaigns
200
+
201
+ ```ruby
202
+ campaigns = Printfection::Campaign.all
203
+ #=> [#<Printfection::Campaign id: 1 ...>, #<Printfection::Campaign id: 2 ...>]
204
+ ```
205
+
206
+ Printfection objects expose all JSON data from the API responses as accessor methods. The full API documentation can be [found here](http://printfection.github.io/API-Documentation).
207
+
208
+ For additional examples, check out out the [examples directory](examples).
209
+
210
+ ## Errors
211
+
212
+ Our API bindings can raise exceptions for many reasons, such as a trying to place an incomplete order, invalid parameters, authentication errors, and network unavailability.
213
+
214
+ Most API errors are captured and raised as a `Printfection::Error`. This makes it easy to gracefully handle exceptions.
215
+
216
+ ```ruby
217
+ begin
218
+ order = Printfection::Order.create(campaign_id: 1)
219
+ # This order does not have any line items and
220
+ # does not have a shipping address,
221
+ # so trying to place this order will raise.
222
+ order.place
223
+ rescue Printfection::Error => e
224
+ # Something went wrong placing this order.
225
+ puts e.message
226
+ rescue StandardError => e
227
+ # Something else went wrong.
228
+ puts e.message
229
+ end
230
+ ```
231
+
232
+ ## License
233
+
234
+ [MIT](LICENCE.txt)
235
+
236
+ ## Issues & Support
237
+
238
+ [casey.ohara@printfection.com](mailto:casey.ohara@printfection.com)
239
+
240
+ ## Contributing
241
+
242
+ 1. Fork it ( https://github.com/printfection/printfection-ruby/fork )
243
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
244
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
245
+ 4. Push to the branch (`git push origin my-new-feature`)
246
+ 5. Create a new Pull Request
247
+
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ task :test do
4
+ sh "rspec spec"
5
+ end
6
+
7
+ task :default => :test
8
+
@@ -0,0 +1,40 @@
1
+ module Printfection
2
+ module Actions
3
+
4
+ module Retrieve
5
+ def retrieve(id)
6
+ new Printfection.get Util.join_uri(self.uri, id)
7
+ end
8
+ end
9
+
10
+ module List
11
+ def all(params={})
12
+ Printfection.get(self.uri, params).map do |response|
13
+ new response
14
+ end
15
+ end
16
+ end
17
+
18
+ module Create
19
+ def create(params)
20
+ new Printfection.post self.uri, params
21
+ end
22
+ end
23
+
24
+ module Update
25
+ def save
26
+ Printfection.patch self.uri, changes
27
+ true
28
+ end
29
+ end
30
+
31
+ module Delete
32
+ def delete
33
+ Printfection.delete self.uri
34
+ true
35
+ end
36
+ end
37
+
38
+ end
39
+ end
40
+
@@ -0,0 +1,15 @@
1
+ module Printfection
2
+ class Address < Resource
3
+ property :name
4
+ property :address
5
+ property :address2
6
+ property :company
7
+ property :city
8
+ property :state
9
+ property :zip_code, from: :zip
10
+ property :country
11
+ property :email
12
+ property :phone
13
+ end
14
+ end
15
+
@@ -0,0 +1,87 @@
1
+ module Printfection
2
+ module API
3
+ ENDPOINT = "api.printfection.com/v2/"
4
+
5
+ attr_accessor :api_token, :debug_mode
6
+
7
+ def get(uri="/", params={})
8
+ request :get, uri, params
9
+ end
10
+
11
+ def post(uri, data={})
12
+ request :post, uri, data
13
+ end
14
+
15
+ def patch(uri, data={})
16
+ request :patch, uri, data
17
+ end
18
+
19
+ def delete(uri)
20
+ request :delete, uri
21
+ end
22
+
23
+ def request(verb, uri, params={})
24
+ perform_request do
25
+ uri = Util.join_uri(ENDPOINT, uri)
26
+ url = "https://#{api_token}:@#{uri}"
27
+
28
+ response = case verb
29
+ when :get; RestClient.get url, :params => params, :accept => :json
30
+ when :post; RestClient.post url, params.to_json, :accept => :json, :content_type => :json
31
+ when :patch; RestClient.patch url, params.to_json, :accept => :json, :content_type => :json
32
+ when :delete; RestClient.delete url
33
+ end
34
+
35
+ json = JSON.parse(response.body)
36
+
37
+ if json["object"] == "list" and json.has_key? "data"
38
+ json["data"]
39
+ else
40
+ json
41
+ end
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def perform_request(&block)
48
+ return yield if debug_mode
49
+
50
+ begin
51
+ yield
52
+
53
+ # At this point, some exception has been raised either
54
+ # during the request or parsing the response.
55
+ #
56
+ # We determine the type of error, and re-raise
57
+ # our own error from the message in the response body.
58
+ rescue RestClient::Exception => e
59
+ # We likely got a http status code outside the 200-399 range.
60
+ # If this is a GET or DELETE request, it is likely the resource is not owned by the client.
61
+ # If this is a POST, PUT, or PATCH, the data might be invalid.
62
+
63
+ # Handle 400, 401, and 404 errors.
64
+ # 400 Bad Request - Invalid or missing request parameters.
65
+ # 401 Unauthorized - Invalid API key provided.
66
+ # 404 Not Found - The requested item doesn't exist or the client doesn't own it.
67
+ if [400, 401, 404].include?(e.http_code)
68
+ raise Error, JSON.parse(e.http_body)["message"]
69
+ end
70
+
71
+ # Handle any other http error (i.e. 5xx+), or other RestClient exceptions.
72
+ # Re-raise a generic error.
73
+ raise Error, "Something went wrong with the request. Please try again."
74
+ rescue JSON::ParserError => e
75
+ # We received the data fine, but we're unable to parse it.
76
+ # Re-raise a generic error.
77
+ raise Error, "Something went wrong parsing the response. Please try again."
78
+ rescue StandardError => e
79
+ # Something else went wrong.
80
+ # Re-raise a generic error.
81
+ raise Error, "Something went wrong. Please try again."
82
+ end
83
+ end
84
+
85
+ end
86
+ end
87
+
@@ -0,0 +1,11 @@
1
+ module Printfection
2
+ class Asset < Resource
3
+ property :id, transform_with: Transforms::Integer
4
+ property :type
5
+ property :name
6
+ property :perspective
7
+ property :url
8
+ property :notes
9
+ end
10
+ end
11
+
@@ -0,0 +1,20 @@
1
+ module Printfection
2
+ class Campaign < Resource
3
+ include Hashie::Extensions::Coercion
4
+ extend Actions::Retrieve
5
+ extend Actions::List
6
+
7
+ property :id, transform_with: Transforms::Integer
8
+ property :name
9
+ property :type
10
+ property :active
11
+ property :archived
12
+ property :url
13
+ property :created_at, transform_with: Transforms::Date
14
+
15
+ def self.uri
16
+ "/campaigns"
17
+ end
18
+ end
19
+ end
20
+
@@ -0,0 +1,8 @@
1
+ module Printfection
2
+ class Error < StandardError
3
+ end
4
+
5
+ class RequestError < Error
6
+ end
7
+ end
8
+
@@ -0,0 +1,29 @@
1
+ module Printfection
2
+ class Item < Resource
3
+ extend Actions::Retrieve
4
+ extend Actions::List
5
+
6
+ property :id, transform_with: Transforms::Integer
7
+ property :type
8
+ property :name
9
+ property :color
10
+ property :created_at, transform_with: Transforms::Date
11
+
12
+ property :product
13
+ coerce_key :product, Product
14
+
15
+ property :campaigns
16
+ coerce_key :campaigns, Array[Campaign]
17
+
18
+ property :sizes
19
+ coerce_key :sizes, Array[Size]
20
+
21
+ property :assets
22
+ coerce_key :assets, Array[Asset]
23
+
24
+ def self.uri
25
+ "/items"
26
+ end
27
+ end
28
+ end
29
+
@@ -0,0 +1,21 @@
1
+ module Printfection
2
+ class LineItem < Resource
3
+ extend Actions::Retrieve
4
+ extend Actions::Create
5
+ include Actions::Update
6
+ include Actions::Delete
7
+
8
+ property :id, transform_with: Transforms::Integer
9
+ property :order_id, transform_with: Transforms::Integer
10
+ property :item_id, transform_with: Transforms::Integer
11
+ property :size_id, transform_with: Transforms::Integer
12
+ property :quantity, transform_with: Transforms::Integer
13
+ property :created_at, transform_with: Transforms::Date
14
+
15
+ def self.uri
16
+ "/lineitems"
17
+ end
18
+
19
+ end
20
+ end
21
+
@@ -0,0 +1,22 @@
1
+ module Printfection
2
+ class Manifest < Resource
3
+ property :subtotal, transform_with: Transforms::Float
4
+ property :tax, transform_with: Transforms::Float
5
+ property :shipping, transform_with: Transforms::Float
6
+ property :fulfillment, transform_with: Transforms::Float
7
+ property :total, transform_with: Transforms::Float
8
+ property :created_at, transform_with: Transforms::Date
9
+ property :received_at, transform_with: Transforms::Date
10
+ property :approved_at, transform_with: Transforms::Date
11
+ property :processed_at, transform_with: Transforms::Date
12
+ property :shipped_at, transform_with: Transforms::Date
13
+ property :completed_at, transform_with: Transforms::Date
14
+
15
+ property :line_items, from: :lineitems
16
+ coerce_key :line_items, Array[LineItem]
17
+
18
+ property :shipments
19
+ coerce_key :shipments, Array[Hashie::Mash]
20
+ end
21
+ end
22
+
@@ -0,0 +1,99 @@
1
+ module Printfection
2
+ class Order < Resource
3
+ extend Actions::Retrieve
4
+ extend Actions::List
5
+ extend Actions::Create
6
+ include Actions::Update
7
+ include Actions::Delete
8
+
9
+ property :id, transform_with: Transforms::Integer
10
+ property :campaign_id, transform_with: Transforms::Integer
11
+ property :created_at, transform_with: Transforms::Date
12
+ property :status, transform_with: lambda { |v| v.downcase }
13
+ property :code
14
+ property :url
15
+ property :gift
16
+ property :gift_message
17
+
18
+ property :line_items, from: :lineitems
19
+ coerce_key :line_items, Array[LineItem]
20
+
21
+ property :ship_to
22
+ coerce_key :ship_to, Address
23
+
24
+ property :manifest
25
+ coerce_key :manifest, Manifest
26
+
27
+ def self.uri
28
+ "/orders"
29
+ end
30
+
31
+ def line_items
32
+ Relation.new(
33
+ parent: self,
34
+ children: self[:line_items],
35
+ klass: LineItem,
36
+ path: '/lineitems',
37
+ keys: {:id => :order_id},
38
+ actions: [Actions::Retrieve, Actions::Create]
39
+ )
40
+ end
41
+
42
+ def campaign
43
+ Campaign.retrieve(campaign_id)
44
+ end
45
+
46
+ def place
47
+ Printfection.post Util.join_uri(uri, "/place")
48
+ end
49
+
50
+ def cancel
51
+ delete
52
+ end
53
+
54
+ STATUS_CODES = {
55
+ "unknown" => -2,
56
+ "cancelled" => -1,
57
+ "open" => 0,
58
+ "received" => 1,
59
+ "approved" => 2,
60
+ "processed" => 3,
61
+ "shipped" => 4,
62
+ "completed" => 5
63
+ }
64
+
65
+ def status_code
66
+ STATUS_CODES[status]
67
+ end
68
+
69
+ def open?
70
+ status_code == 0
71
+ end
72
+
73
+ def cancelled?
74
+ status_code == -1
75
+ end
76
+
77
+ def received?
78
+ status_code >= 1
79
+ end
80
+
81
+ def approved?
82
+ status_code >= 2
83
+ end
84
+
85
+ def processed?
86
+ status_code >= 3
87
+ end
88
+
89
+ def shipped?
90
+ status_code >= 4
91
+ end
92
+
93
+ def completed?
94
+ status_code == 5
95
+ end
96
+
97
+ end
98
+ end
99
+
@@ -0,0 +1,7 @@
1
+ module Printfection
2
+ class Product < Resource
3
+ property :id, transform_with: Transforms::Integer
4
+ property :name
5
+ end
6
+ end
7
+