shirtsio-ruby 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8d328158b57485ebd7629ac0520fb6331b5023de
4
+ data.tar.gz: 50d4414935fa2579e02368026ebb79796e8ef982
5
+ SHA512:
6
+ metadata.gz: 1538b7d50d959b701b122c4658e7d088a22a7f3554cffa696bea9672d4992262469d7348efb148099c03be4075b34b14437a52cc2178af06faf83f5b95c33034
7
+ data.tar.gz: be241d7db0373ebded0a34b62fffc664052f9c6f16aa85de3880662c79e678c3868687fe93af2b3587119aa349c8e4f6e81328cc0ed504b3d7741566ecd875cf
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
@@ -0,0 +1,7 @@
1
+ <component name="ProjectDictionaryState">
2
+ <dictionary name="dean">
3
+ <words>
4
+ <w>webhook</w>
5
+ </words>
6
+ </dictionary>
7
+ </component>
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in shirtsio.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Dean Hailin Song
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.
@@ -0,0 +1,29 @@
1
+ # Shirtsio
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'shirtsio'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install shirtsio
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,232 @@
1
+ require 'cgi'
2
+ require 'set'
3
+ require 'openssl'
4
+ require 'rest_client'
5
+ require 'multi_json'
6
+
7
+ # Version
8
+ require "shirtsio/version"
9
+
10
+ # Resources
11
+ require "shirtsio/util"
12
+ require "shirtsio/json"
13
+ require "shirtsio/shirtsio_object"
14
+ require "shirtsio/api_resource"
15
+ require "shirtsio/category"
16
+ require "shirtsio/product"
17
+ require "shirtsio/quote"
18
+ require "shirtsio/authentication"
19
+ require "shirtsio/webhooks"
20
+ require "shirtsio/status"
21
+ require "shirtsio/order"
22
+
23
+ # Error
24
+ require "shirtsio/errors/shirtsio_error"
25
+ require "shirtsio/errors/api_error"
26
+ require "shirtsio/errors/api_connection_error"
27
+ require "shirtsio/errors/invalid_request_error"
28
+ require "shirtsio/errors/authentication_error"
29
+
30
+ module Shirtsio
31
+ @api_base = 'https://www.shirts.io/api/v1/'
32
+ #put @api_base
33
+
34
+ class << self
35
+ attr_accessor :api_key, :api_base, :api_version
36
+ end
37
+
38
+ def self.api_url(url='')
39
+ @api_base + url
40
+ end
41
+
42
+ def self.request(method, url, api_key, params={}, headers={})
43
+ unless api_key ||= @api_key
44
+ raise AuthenticationError.new('No API key provided. ' +
45
+ 'Set your API key using "Shirtsio.api_key = <API-KEY>". ' +
46
+ 'You can generate API keys from the Shirts.io web interface. ' +
47
+ 'See https://www.shirts.io for details.')
48
+ end
49
+
50
+ if api_key =~ /\s/
51
+ raise AuthenticationError.new('Your API key is invalid, as it contains ' +
52
+ 'whitespace. (HINT: You can double-check your API key from the ' +
53
+ 'Shirts.io web interface. See https://www.shirts.io for details.)')
54
+ end
55
+
56
+ request_opts = { :verify_ssl => false }
57
+
58
+ params = Util.objects_to_ids(params)
59
+ params.update(:api_key => @api_key)
60
+ url = api_url(url)
61
+
62
+ case method.to_s.downcase.to_sym
63
+ when :get, :head, :delete
64
+ # Make params into GET parameters
65
+ url += "#{URI.parse(url).query ? '&' : '?'}#{uri_encode(params)}" if params && params.any?
66
+ payload = nil
67
+ else
68
+ #payload = uri_encode(params)
69
+ payload = params
70
+ end
71
+
72
+ request_opts.update(:method => method, :open_timeout => 30,
73
+ :payload => payload, :url => url, :timeout => 80)
74
+
75
+ begin
76
+ #puts "in shirtsio.rb"
77
+ #puts request_opts
78
+ response = execute_request(request_opts)
79
+ rescue SocketError => e
80
+ handle_restclient_error(e)
81
+ rescue NoMethodError => e
82
+ # Work around RestClient bug
83
+ if e.message =~ /\WRequestFailed\W/
84
+ e = APIConnectionError.new('Unexpected HTTP response code')
85
+ handle_restclient_error(e)
86
+ else
87
+ raise
88
+ end
89
+ rescue RestClient::ExceptionWithResponse => e
90
+ if rcode = e.http_code and rbody = e.http_body
91
+ handle_api_error(rcode, rbody)
92
+ else
93
+ handle_restclient_error(e)
94
+ end
95
+ rescue RestClient::Exception, Errno::ECONNREFUSED => e
96
+ handle_restclient_error(e)
97
+ end
98
+
99
+ [parse(response), api_key]
100
+ end
101
+
102
+ private
103
+
104
+ def self.user_agent
105
+ @uname ||= get_uname
106
+ lang_version = "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})"
107
+
108
+ {
109
+ :bindings_version => Shirtsio::VERSION,
110
+ :lang => 'ruby',
111
+ :lang_version => lang_version,
112
+ :platform => RUBY_PLATFORM,
113
+ :publisher => 'shirtsio',
114
+ :uname => @uname
115
+ }
116
+
117
+ end
118
+
119
+ def self.get_uname
120
+ `uname -a 2>/dev/null`.strip if RUBY_PLATFORM =~ /linux|darwin/i
121
+ rescue Errno::ENOMEM => ex # couldn't create subprocess
122
+ "uname lookup failed"
123
+ end
124
+
125
+ def self.uri_encode(params)
126
+ Util.flatten_params(params).
127
+ map { |k,v| "#{k}=#{Util.url_encode(v)}" }.join('&')
128
+ end
129
+
130
+ def self.request_headers(api_key)
131
+ headers = {
132
+ :user_agent => "Stripe/v1 RubyBindings/#{Shirtsio::VERSION}",
133
+ :authorization => "Bearer #{api_key}",
134
+ :content_type => 'application/x-www-form-urlencoded'
135
+ }
136
+
137
+ headers[:stripe_version] = api_version if api_version
138
+
139
+ begin
140
+ headers.update(:x_stripe_client_user_agent => Shirtsio::JSON.dump(user_agent))
141
+ rescue => e
142
+ headers.update(:x_stripe_client_raw_user_agent => user_agent.inspect,
143
+ :error => "#{e} (#{e.class})")
144
+ end
145
+ end
146
+
147
+ def self.execute_request(opts)
148
+ RestClient::Request.execute(opts)
149
+ end
150
+
151
+ def self.parse(response)
152
+ begin
153
+ # Would use :symbolize_names => true, but apparently there is
154
+ # some library out there that makes symbolize_names not work.
155
+ response = Shirtsio::JSON.load(response.body)
156
+ rescue MultiJson::DecodeError
157
+ raise general_api_error(response.code, response.body)
158
+ end
159
+
160
+ Util.symbolize_names(response)
161
+ end
162
+
163
+ def self.general_api_error(rcode, rbody)
164
+ APIError.new("Invalid response object from API: #{rbody.inspect} " +
165
+ "(HTTP response code was #{rcode})", rcode, rbody)
166
+ end
167
+
168
+ def self.handle_api_error(rcode, rbody)
169
+ begin
170
+ error_obj = Shirtsio::JSON.load(rbody)
171
+ error_obj = Util.symbolize_names(error_obj)
172
+ error = error_obj[:error] or raise Shirtsio.new # escape from parsing
173
+
174
+ rescue MultiJson::DecodeError, Shirtsio
175
+ raise general_api_error(rcode, rbody)
176
+ end
177
+
178
+ case rcode
179
+ when 400, 404
180
+ raise invalid_request_error error, rcode, rbody, error_obj
181
+ when 401
182
+ raise authentication_error error, rcode, rbody, error_obj
183
+ when 402
184
+ raise card_error error, rcode, rbody, error_obj
185
+ else
186
+ raise api_error error, rcode, rbody, error_obj
187
+ end
188
+
189
+ end
190
+
191
+ def self.invalid_request_error(error, rcode, rbody, error_obj)
192
+ InvalidRequestError.new(error, nil, rcode,
193
+ rbody, error_obj)
194
+ end
195
+
196
+ def self.authentication_error(error, rcode, rbody, error_obj)
197
+ AuthenticationError.new(error[:message], rcode, rbody, error_obj)
198
+ end
199
+
200
+ def self.card_error(error, rcode, rbody, error_obj)
201
+ CardError.new(error[:message], error[:param], error[:code],
202
+ rcode, rbody, error_obj)
203
+ end
204
+
205
+ def self.api_error(error, rcode, rbody, error_obj)
206
+ APIError.new(error[:message], rcode, rbody, error_obj)
207
+ end
208
+
209
+ def self.handle_restclient_error(e)
210
+ case e
211
+ when RestClient::ServerBrokeConnection, RestClient::RequestTimeout
212
+ message = "Could not connect to Shirts.io (#{@api_base}). " +
213
+ "Please check your internet connection and try again. "
214
+
215
+ when RestClient::SSLCertificateNotVerified
216
+ message = "Could not verify Stripe's SSL certificate. " +
217
+ "Please make sure that your network is not intercepting certificates. "
218
+
219
+ when SocketError
220
+ message = "Unexpected error communicating when trying to connect to Stripe. " +
221
+ "You may be seeing this message because your DNS is not working. " +
222
+ "To check, try running 'host www.shirts.io' from the command line."
223
+
224
+ else
225
+ message = "Unexpected error communicating with Stripe. " +
226
+ "If this problem persists, let us know at jerry@ooshirts.com."
227
+
228
+ end
229
+
230
+ raise APIConnectionError.new(message + "\n\n(Network error: #{e.message})")
231
+ end
232
+ end
@@ -0,0 +1,35 @@
1
+ module Shirtsio
2
+ class APIResource < ShirtsioObject
3
+ def self.class_name
4
+ self.name.split('::')[-1]
5
+ end
6
+
7
+ def self.url()
8
+ if self == APIResource
9
+ raise NotImplementedError.new('APIResource is an abstract class. You should perform actions on its subclasses (Charge, Customer, etc.)')
10
+ end
11
+ "/v1/#{CGI.escape(class_name.downcase)}s"
12
+ end
13
+
14
+ def url
15
+ unless id = self['id']
16
+ raise InvalidRequestError.new("Could not determine which URL to request: #{self.class} instance has invalid ID: #{id.inspect}", 'id')
17
+ end
18
+ "#{self.class.url}/#{CGI.escape(id)}"
19
+ end
20
+
21
+ def refresh
22
+ puts "in api_resource"
23
+ puts url
24
+ response, api_key = Shirtsio.request(:get, url, @api_key, @retrieve_options)
25
+ refresh_from(response, api_key)
26
+ self
27
+ end
28
+
29
+ def self.retrieve(id, api_key=nil)
30
+ instance = self.new(id, api_key)
31
+ instance.refresh
32
+ instance
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,13 @@
1
+ module Shirtsio
2
+ class Authentication < APIResource
3
+
4
+ @auth_url = 'internal/integration/auth/'
5
+
6
+ def Authentication.auth(params={})
7
+ response, api_key = Shirtsio.request(:get, @auth_url, @api_key, params)
8
+ Util.convert_to_shirtsio_object(response, api_key)
9
+ response
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module Shirtsio
2
+ class Category < APIResource
3
+
4
+ @category_url = 'products/category/'
5
+
6
+ def Category.all(params={})
7
+ response, api_key = Shirtsio.request(:get, @category_url, @api_key, params)
8
+ Util.convert_to_shirtsio_object(response, api_key)
9
+ end
10
+
11
+ end
12
+ end
@@ -0,0 +1,4 @@
1
+ module Shirtsio
2
+ class APIConnectionError < ShirtsioError
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Shirtsio
2
+ class APIError < ShirtsioError
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Shirtsio
2
+ class AuthenticationError < ShirtsioError
3
+ end
4
+ end
@@ -0,0 +1,11 @@
1
+ module Shirtsio
2
+ class InvalidRequestError < ShirtsioError
3
+ attr_accessor :param
4
+
5
+ def initialize(message, param, http_status=nil, http_body=nil, json_body=nil)
6
+
7
+ super(message, http_status, http_body, json_body)
8
+ @param = param
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,20 @@
1
+ module Shirtsio
2
+ class ShirtsioError < StandardError
3
+ attr_reader :message
4
+ attr_reader :http_status
5
+ attr_reader :http_body
6
+ attr_reader :json_body
7
+
8
+ def initialize(message=nil, http_status=nil, http_body=nil, json_body=nil)
9
+ @message = message
10
+ @http_status = http_status
11
+ @http_body = http_body
12
+ @json_body = json_body
13
+ end
14
+
15
+ def to_s
16
+ status_string = @http_status.nil? ? "" : "(Status #{@http_status}) "
17
+ "#{status_string}#{@message}"
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ module Shirtsio
2
+ module JSON
3
+ if MultiJson.respond_to?(:dump)
4
+ def self.dump(*args)
5
+ MultiJson.dump(*args)
6
+ end
7
+
8
+ def self.load(*args)
9
+ MultiJson.load(*args)
10
+ end
11
+ else
12
+ def self.dump(*args)
13
+ MultiJson.encode(*args)
14
+ end
15
+
16
+ def self.load(*args)
17
+ MultiJson.decode(*args)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ module Shirtsio
2
+ class Order < APIResource
3
+
4
+ @order_url = 'order/'
5
+
6
+ def Order.place_order(params={})
7
+ response, api_key = Shirtsio.request(:post, @order_url, @api_key, params)
8
+ Util.convert_to_shirtsio_object(response, api_key)
9
+ response
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,31 @@
1
+ module Shirtsio
2
+ class Product < APIResource
3
+
4
+ @products_url = 'products/'
5
+ @category_url = 'products/category/'
6
+
7
+ def Product.list_products(params={})
8
+ category_id = params[:category_id]
9
+ list_products_url = @category_url + category_id + "/"
10
+ response, api_key = Shirtsio.request(:get, list_products_url, @api_key, params={})
11
+ Util.convert_to_shirtsio_object(response, api_key)
12
+ response
13
+ end
14
+
15
+ def Product.get_product(params={})
16
+ product_id = params[:product_id]
17
+ get_product_url = @products_url + product_id + "/"
18
+ response, api_key = Shirtsio.request(:get, get_product_url, @api_key, params={})
19
+ Util.convert_to_shirtsio_object(response, api_key)
20
+ response
21
+ end
22
+
23
+ def Product.inventory_count(params={})
24
+ product_id = params.delete(:product_id)
25
+ get_product_url = @products_url + product_id + "/"
26
+ response, api_key = Shirtsio.request(:get, get_product_url, @api_key, params)
27
+ #Util.convert_to_shirtsio_object(response, api_key)
28
+ response
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,13 @@
1
+ module Shirtsio
2
+ class Quote < APIResource
3
+
4
+ @quote_url = 'quote/'
5
+
6
+ def Quote.get_quote(params={})
7
+ response, api_key = Shirtsio.request(:get, @quote_url, @api_key, params)
8
+ #Util.convert_to_shirtsio_object(response, api_key)
9
+ response
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,158 @@
1
+ module Shirtsio
2
+ class ShirtsioObject
3
+ include Enumerable
4
+
5
+ attr_accessor :api_key
6
+ @@permanent_attributes = Set.new([:api_key, :id])
7
+
8
+ # The default :id method is deprecated and isn't useful to us
9
+ if method_defined?(:id)
10
+ undef :id
11
+ end
12
+
13
+ def initialize(id=nil, api_key=nil)
14
+ # parameter overloading!
15
+ if id.kind_of?(Hash)
16
+ @retrieve_options = id.dup
17
+ @retrieve_options.delete(:id)
18
+ id = id[:id]
19
+ else
20
+ @retrieve_options = {}
21
+ end
22
+
23
+ @api_key = api_key
24
+ @values = {}
25
+ # This really belongs in APIResource, but not putting it there allows us
26
+ # to have a unified inspect method
27
+ @unsaved_values = Set.new
28
+ @transient_values = Set.new
29
+ self.id = id if id
30
+ end
31
+
32
+ def self.construct_from(values, api_key=nil)
33
+ obj = self.new(values[:id], api_key)
34
+ obj.refresh_from(values, api_key)
35
+ obj
36
+ end
37
+
38
+ def to_s(*args)
39
+ ShirtsioObject::JSON.dump(@values, :pretty => true)
40
+ end
41
+
42
+ def inspect()
43
+ id_string = (self.respond_to?(:id) && !self.id.nil?) ? " id=#{self.id}" : ""
44
+ "#<#{self.class}:0x#{self.object_id.to_s(16)}#{id_string}> JSON: " + ShirtsioObject::JSON.dump(@values, :pretty => true)
45
+ end
46
+
47
+ def refresh_from(values, api_key, partial=false)
48
+ @api_key = api_key
49
+
50
+ removed = partial ? Set.new : Set.new(@values.keys - values.keys)
51
+ added = Set.new(values.keys - @values.keys)
52
+ # Wipe old state before setting new. This is useful for e.g. updating a
53
+ # customer, where there is no persistent card parameter. Mark those values
54
+ # which don't persist as transient
55
+
56
+ instance_eval do
57
+ remove_accessors(removed)
58
+ add_accessors(added)
59
+ end
60
+ removed.each do |k|
61
+ @values.delete(k)
62
+ @transient_values.add(k)
63
+ @unsaved_values.delete(k)
64
+ end
65
+ values.each do |k, v|
66
+ @values[k] = Util.convert_to_shirtsio_object(v, api_key)
67
+ @transient_values.delete(k)
68
+ @unsaved_values.delete(k)
69
+ end
70
+ end
71
+
72
+ def [](k)
73
+ @values[k.to_sym]
74
+ end
75
+
76
+ def []=(k, v)
77
+ send(:"#{k}=", v)
78
+ end
79
+
80
+ def keys
81
+ @values.keys
82
+ end
83
+
84
+ def values
85
+ @values.values
86
+ end
87
+
88
+ def to_json(*a)
89
+ ShirtsioObject::JSON.dump(@values)
90
+ end
91
+
92
+ def as_json(*a)
93
+ @values.as_json(*a)
94
+ end
95
+
96
+ def to_hash
97
+ @values
98
+ end
99
+
100
+ def each(&blk)
101
+ @values.each(&blk)
102
+ end
103
+
104
+ protected
105
+
106
+ def metaclass
107
+ class << self; self; end
108
+ end
109
+
110
+ def remove_accessors(keys)
111
+ metaclass.instance_eval do
112
+ keys.each do |k|
113
+ next if @@permanent_attributes.include?(k)
114
+ k_eq = :"#{k}="
115
+ remove_method(k) if method_defined?(k)
116
+ remove_method(k_eq) if method_defined?(k_eq)
117
+ end
118
+ end
119
+ end
120
+
121
+ def add_accessors(keys)
122
+ metaclass.instance_eval do
123
+ keys.each do |k|
124
+ next if @@permanent_attributes.include?(k)
125
+ k_eq = :"#{k}="
126
+ define_method(k) { @values[k] }
127
+ define_method(k_eq) do |v|
128
+ @values[k] = v
129
+ @unsaved_values.add(k)
130
+ end
131
+ end
132
+ end
133
+ end
134
+
135
+ def method_missing(name, *args)
136
+ # TODO: only allow setting in updateable classes.
137
+ if name.to_s.end_with?('=')
138
+ attr = name.to_s[0...-1].to_sym
139
+ @values[attr] = args[0]
140
+ @unsaved_values.add(attr)
141
+ add_accessors([attr])
142
+ return
143
+ else
144
+ return @values[name] if @values.has_key?(name)
145
+ end
146
+
147
+ begin
148
+ super
149
+ rescue NoMethodError => e
150
+ if @transient_values.include?(name)
151
+ raise NoMethodError.new(e.message + ". HINT: The '#{name}' attribute was set in the past, however. It was then wiped when refreshing the object with the result returned by Stripe's API, probably as a result of a save(). The attributes currently available on this object are: #{@values.keys.join(', ')}")
152
+ else
153
+ raise
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,13 @@
1
+ module Shirtsio
2
+ class Status < APIResource
3
+
4
+ @status_url = 'status/'
5
+
6
+ def Status.get_order_status(params={})
7
+ response, api_key = Shirtsio.request(:get, @status_url, @api_key, params)
8
+ Util.convert_to_shirtsio_object(response, api_key)
9
+ response
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,106 @@
1
+ module Shirtsio
2
+ module Util
3
+ def self.objects_to_ids(h)
4
+ case h
5
+ when APIResource
6
+ h.id
7
+ when Hash
8
+ res = {}
9
+ h.each { |k, v| res[k] = objects_to_ids(v) unless v.nil? }
10
+ res
11
+ when Array
12
+ h.map { |v| objects_to_ids(v) }
13
+ else
14
+ h
15
+ end
16
+ end
17
+
18
+ def self.convert_to_shirtsio_object(resp, api_key)
19
+ types = {
20
+ 'category' => Category,
21
+ 'product' => Product,
22
+ 'quote' => Quote,
23
+ 'authentication' => Authentication,
24
+ 'webhooks' => Webhooks,
25
+ 'status' => Status,
26
+ 'order' => Order
27
+ }
28
+ case resp
29
+ when Array
30
+ resp.map { |i| convert_to_shirtsio_object(i, api_key) }
31
+ when Hash
32
+ #puts "in api resource"
33
+ #puts resp
34
+ #puts "end api resource"
35
+ # Try converting to a known object class. If none available, fall back to generic APIResource
36
+ if klass_name = resp[:object]
37
+ klass = types[klass_name]
38
+ end
39
+ klass ||= ShirtsioObject
40
+ klass.construct_from(resp, api_key)
41
+ else
42
+ resp
43
+ end
44
+ end
45
+
46
+ def self.file_readable(file)
47
+ begin
48
+ File.open(file) { |f| }
49
+ rescue
50
+ false
51
+ else
52
+ true
53
+ end
54
+ end
55
+
56
+ def self.symbolize_names(object)
57
+ case object
58
+ when Hash
59
+ new = {}
60
+ object.each do |key, value|
61
+ key = (key.to_sym rescue key) || key
62
+ new[key] = symbolize_names(value)
63
+ end
64
+ new
65
+ when Array
66
+ object.map { |value| symbolize_names(value) }
67
+ else
68
+ object
69
+ end
70
+ end
71
+
72
+ def self.url_encode(key)
73
+ URI.escape(key.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
74
+ end
75
+
76
+ def self.flatten_params(params, parent_key=nil)
77
+ result = []
78
+ params.each do |key, value|
79
+ calculated_key = parent_key ? "#{parent_key}[#{url_encode(key)}]" : url_encode(key)
80
+ if value.is_a?(Hash)
81
+ result += flatten_params(value, calculated_key)
82
+ elsif value.is_a?(Array)
83
+ result += flatten_params_array(value, calculated_key)
84
+ else
85
+ result << [calculated_key, value]
86
+ end
87
+ end
88
+ result
89
+ end
90
+
91
+ def self.flatten_params_array(value, calculated_key)
92
+ result = []
93
+ value.each do |elem|
94
+ if elem.is_a?(Hash)
95
+ result += flatten_params(elem, calculated_key)
96
+ elsif elem.is_a?(Array)
97
+ result += flatten_params_array(elem, calculated_key)
98
+ else
99
+ result << ["#{calculated_key}[]", elem]
100
+ end
101
+ end
102
+ result
103
+ end
104
+ end
105
+
106
+ end
@@ -0,0 +1,3 @@
1
+ module Shirtsio
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,34 @@
1
+ module Shirtsio
2
+ class Webhooks < APIResource
3
+
4
+ @webhooks_url = 'webhooks/'
5
+
6
+ def Webhooks.list(params={})
7
+ webhooks_list_url = @webhooks_url + 'list/'
8
+ response, api_key = Shirtsio.request(:get, webhooks_list_url, @api_key, params)
9
+ Util.convert_to_shirtsio_object(response, api_key)
10
+ response
11
+ end
12
+
13
+ def Webhooks.register(params={})
14
+ webhooks_register_url = @webhooks_url + 'register/'
15
+ response, api_key = Shirtsio.request(:post, webhooks_register_url, @api_key, params)
16
+ Util.convert_to_shirtsio_object(response, api_key)
17
+ response
18
+ end
19
+
20
+ def Webhooks.delete(params={})
21
+ webhooks_delete_url = @webhooks_url + 'delete/'
22
+ response, api_key = Shirtsio.request(:post, webhooks_delete_url, @api_key, params)
23
+ Util.convert_to_shirtsio_object(response, api_key)
24
+ response
25
+ end
26
+
27
+ def Webhooks.register_payment(params={})
28
+ webhooks_payment_url = 'payment/status'
29
+ response, api_key = Shirtsio.request(:post, webhooks_payment_url, @api_key, params)
30
+ Util.convert_to_shirtsio_object(response, api_key)
31
+ response
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ require "shirtsio/version"
6
+ require "rake"
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = "shirtsio-ruby"
10
+ spec.version = Shirtsio::VERSION
11
+ spec.authors = ["Dean Hailin Song"]
12
+ spec.email = ["dean.song@movit-tech.com"]
13
+ spec.description = "The Shirts.io client library"
14
+ spec.summary = "Ruby version for the Shirts.io client library"
15
+ spec.homepage = ""
16
+ spec.license = "MIT"
17
+
18
+ spec.files = `git ls-files`.split($/)
19
+ spec.files += FileList["lib/shirtsio/errors/*.rb"]
20
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
21
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
22
+ spec.require_paths = %w(lib)
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.3"
25
+ spec.add_development_dependency "rake"
26
+ spec.add_dependency('rest-client', '~> 1.4')
27
+ spec.add_dependency('multi_json', '>= 1.0.4', '< 2')
28
+
29
+ end
30
+
@@ -0,0 +1,76 @@
1
+ #require File.expand_path('../../lib/*', __FILE__)
2
+ require "shirtsio"
3
+
4
+ Shirtsio.api_key = '3ef58f89c6c8d0ce3f71e4ab3537db4e24d6ac40'
5
+
6
+
7
+ ###### Category ######
8
+ #categories = Shirtsio::Category.all()
9
+ #puts categories.result
10
+
11
+
12
+ ###### Product ######
13
+ #products = Shirtsio::Product.list_products(:category_id => "3")
14
+ #puts products[:result]
15
+ #
16
+ #product = Shirtsio::Product.get_product(:product_id => "5")
17
+ #puts product[:result]
18
+ #
19
+ #product = Shirtsio::Product.inventory_count(:product_id => "5", :color => "White", :state => "CA")
20
+ #puts product[:result][:inventory]
21
+
22
+
23
+ ###### Quote ######
24
+ #params = {'garment[0][product_id]' => 3, 'garment[0][color]' => 'White',
25
+ # 'garment[0][sizes][med]' => 100, 'print[front][color_count]' => 5}
26
+ #quote = Shirtsio::Quote.get_quote(params)
27
+ #puts quote[:result][:subtotal]
28
+
29
+
30
+ ###### Auth ######
31
+ #params = {'username' => 'deantest', 'password' => 'Pa$$w0rd'}
32
+ #auth_result = Shirtsio::Authentication.auth(params)
33
+ #puts auth_result[:result][:api_key]
34
+
35
+
36
+ ###### Webhooks ######
37
+ #new_webhooks = Shirtsio::Webhooks.register(:url => 'www.baidu.com')
38
+ #puts new_webhooks[:result]
39
+ #
40
+ #delete_webhooks = Shirtsio::Webhooks.delete(:url => 'www.baidu.com')
41
+ #puts delete_webhooks[:result]
42
+ #
43
+ #webhooks = Shirtsio::Webhooks.list()
44
+ #puts webhooks[:result][:listener_url]
45
+
46
+
47
+ ###### Order ######
48
+ #Dir.chdir(File.dirname(__FILE__))
49
+ #artwork_front = File.new("front.png", 'rb')
50
+ #proof_front = File.new("front.jpg", 'rb')
51
+ #artwork_back = File.new("back.png", 'rb')
52
+ #proof_back = File.new("back.jpg", 'rb')
53
+ #puts artwork_front
54
+ #
55
+ #data = {
56
+ # :multipart => true,
57
+ # 'test' => "True", 'price' => '79.28',
58
+ # 'print[back][color_count]' => '4', 'print[back][colors][0]' => "101C", 'print[back][colors][1]' => '107U',
59
+ # 'addresses[0][name]' => 'John Doe', 'addresses[0][address]' => '123 Hope Ln.',
60
+ # 'addresses[0][city]' => 'Las Vegas', 'addresses[0][state]' => 'Nevada', 'addresses[0][country]' => 'US',
61
+ # 'addresses[0][zipcode]' => '12345', 'addresses[0][batch]' => 1, 'addresses[0][sizes][med]' => '2',
62
+ # 'addresses[0][sizes][lrg]' => '2',
63
+ # 'print_type' => 'Digital Print', 'ship_type' => 'Standard',
64
+ # 'garment[0][product_id]' => '2', 'garment[0][color]' => "White",
65
+ # 'garment[0][sizes][med]' => '2', 'garment[0][sizes][lrg]' => '2', 'print[front][color_count]' => '5',
66
+ # 'print[front][artwork]' => artwork_front, 'print[front][proof]' => proof_front,
67
+ # 'print[back][artwork]' => artwork_back, 'print[back][proof]' => proof_back
68
+ #}
69
+ #
70
+ #order = Shirtsio::Order.place_order(data)
71
+ #puts order[:result]
72
+
73
+
74
+ ###### Status ######
75
+ #order_status = Shirtsio::Status.get_order_status(:order_id => '999999')
76
+ #puts order_status
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shirtsio-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Dean Hailin Song
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-05-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rest-client
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.4'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.4'
55
+ - !ruby/object:Gem::Dependency
56
+ name: multi_json
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 1.0.4
62
+ - - <
63
+ - !ruby/object:Gem::Version
64
+ version: '2'
65
+ type: :runtime
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - '>='
70
+ - !ruby/object:Gem::Version
71
+ version: 1.0.4
72
+ - - <
73
+ - !ruby/object:Gem::Version
74
+ version: '2'
75
+ description: The Shirts.io client library
76
+ email:
77
+ - dean.song@movit-tech.com
78
+ executables: []
79
+ extensions: []
80
+ extra_rdoc_files: []
81
+ files:
82
+ - .gitignore
83
+ - .idea/dictionaries/dean.xml
84
+ - Gemfile
85
+ - LICENSE.txt
86
+ - README.md
87
+ - Rakefile
88
+ - lib/shirtsio.rb
89
+ - lib/shirtsio/api_resource.rb
90
+ - lib/shirtsio/authentication.rb
91
+ - lib/shirtsio/category.rb
92
+ - lib/shirtsio/errors/api_connection_error.rb
93
+ - lib/shirtsio/errors/api_error.rb
94
+ - lib/shirtsio/errors/authentication_error.rb
95
+ - lib/shirtsio/errors/invalid_request_error.rb
96
+ - lib/shirtsio/errors/shirtsio_error.rb
97
+ - lib/shirtsio/json.rb
98
+ - lib/shirtsio/order.rb
99
+ - lib/shirtsio/product.rb
100
+ - lib/shirtsio/quote.rb
101
+ - lib/shirtsio/shirtsio_object.rb
102
+ - lib/shirtsio/status.rb
103
+ - lib/shirtsio/util.rb
104
+ - lib/shirtsio/version.rb
105
+ - lib/shirtsio/webhooks.rb
106
+ - shirtsio.gemspec
107
+ - test/example.rb
108
+ homepage: ''
109
+ licenses:
110
+ - MIT
111
+ metadata: {}
112
+ post_install_message:
113
+ rdoc_options: []
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - '>='
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ requirements: []
127
+ rubyforge_project:
128
+ rubygems_version: 2.0.3
129
+ signing_key:
130
+ specification_version: 4
131
+ summary: Ruby version for the Shirts.io client library
132
+ test_files:
133
+ - test/example.rb