spiffy_stores_api 4.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.gitignore +10 -0
- data/.travis.yml +14 -0
- data/CHANGELOG +3 -0
- data/Gemfile +5 -0
- data/Gemfile_ar40 +5 -0
- data/Gemfile_ar41 +5 -0
- data/Gemfile_ar50 +5 -0
- data/Gemfile_ar_master +5 -0
- data/README.md +200 -0
- data/Rakefile +39 -0
- data/lib/active_resource/base_ext.rb +21 -0
- data/lib/active_resource/connection_ext.rb +10 -0
- data/lib/active_resource/detailed_log_subscriber.rb +19 -0
- data/lib/active_resource/disable_prefix_check.rb +36 -0
- data/lib/active_resource/json_errors.rb +31 -0
- data/lib/active_resource/to_query.rb +10 -0
- data/lib/spiffy_stores_api.rb +29 -0
- data/lib/spiffy_stores_api/connection.rb +33 -0
- data/lib/spiffy_stores_api/countable.rb +14 -0
- data/lib/spiffy_stores_api/json_format.rb +18 -0
- data/lib/spiffy_stores_api/limits.rb +86 -0
- data/lib/spiffy_stores_api/metafields.rb +19 -0
- data/lib/spiffy_stores_api/resources.rb +2 -0
- data/lib/spiffy_stores_api/resources/address.rb +4 -0
- data/lib/spiffy_stores_api/resources/article.rb +20 -0
- data/lib/spiffy_stores_api/resources/base.rb +86 -0
- data/lib/spiffy_stores_api/resources/blog.rb +9 -0
- data/lib/spiffy_stores_api/resources/collect.rb +5 -0
- data/lib/spiffy_stores_api/resources/country.rb +4 -0
- data/lib/spiffy_stores_api/resources/customer.rb +24 -0
- data/lib/spiffy_stores_api/resources/image.rb +16 -0
- data/lib/spiffy_stores_api/resources/metafield.rb +12 -0
- data/lib/spiffy_stores_api/resources/order.rb +23 -0
- data/lib/spiffy_stores_api/resources/page.rb +5 -0
- data/lib/spiffy_stores_api/resources/product.rb +32 -0
- data/lib/spiffy_stores_api/resources/province.rb +5 -0
- data/lib/spiffy_stores_api/resources/script_tag.rb +4 -0
- data/lib/spiffy_stores_api/resources/standard_collection.rb +18 -0
- data/lib/spiffy_stores_api/resources/store.rb +18 -0
- data/lib/spiffy_stores_api/resources/super_collection.rb +14 -0
- data/lib/spiffy_stores_api/resources/variant.rb +8 -0
- data/lib/spiffy_stores_api/resources/webhook.rb +4 -0
- data/lib/spiffy_stores_api/session.rb +145 -0
- data/lib/spiffy_stores_api/version.rb +3 -0
- data/spiffy_stores_api.gemspec +34 -0
- data/test/active_resource/json_errors_test.rb +19 -0
- data/test/article_test.rb +73 -0
- data/test/base_test.rb +112 -0
- data/test/blog_test.rb +8 -0
- data/test/collect_test.rb +9 -0
- data/test/countable_test.rb +13 -0
- data/test/customer_test.rb +50 -0
- data/test/fixtures/article.json +15 -0
- data/test/fixtures/articles.json +39 -0
- data/test/fixtures/asset.json +9 -0
- data/test/fixtures/assets.json +136 -0
- data/test/fixtures/authors.json +1 -0
- data/test/fixtures/blog.json +12 -0
- data/test/fixtures/blogs.json +13 -0
- data/test/fixtures/collect.json +10 -0
- data/test/fixtures/custom_collection.json +17 -0
- data/test/fixtures/customers.json +64 -0
- data/test/fixtures/customers_search.json +66 -0
- data/test/fixtures/image.json +10 -0
- data/test/fixtures/images.json +20 -0
- data/test/fixtures/metafield.json +13 -0
- data/test/fixtures/metafields.json +26 -0
- data/test/fixtures/o_auth_revoke.json +5 -0
- data/test/fixtures/order.json +297 -0
- data/test/fixtures/orders.json +299 -0
- data/test/fixtures/product.json +116 -0
- data/test/fixtures/redirect.json +7 -0
- data/test/fixtures/script_tag.json +10 -0
- data/test/fixtures/script_tags.json +18 -0
- data/test/fixtures/smart_collection.json +21 -0
- data/test/fixtures/store.json +35 -0
- data/test/fixtures/tags.json +1 -0
- data/test/fixtures/transaction.json +29 -0
- data/test/fixtures/variant.json +23 -0
- data/test/fixtures/variants.json +88 -0
- data/test/fixtures/webhook.json +10 -0
- data/test/fixtures/webhooks.json +18 -0
- data/test/metafield_test.rb +46 -0
- data/test/store_test.rb +58 -0
- data/test/test_helper.rb +90 -0
- metadata +219 -0
@@ -0,0 +1,10 @@
|
|
1
|
+
# ActiveSupport 3.0 doesn't URL-encode paths with arrays as params properly.
|
2
|
+
# Backported from ActiveSupport > 3.0
|
3
|
+
if ActiveSupport::VERSION::MAJOR == 3 && ActiveSupport::VERSION::MINOR == 0
|
4
|
+
class Object
|
5
|
+
def to_query(key)
|
6
|
+
require 'cgi' unless defined?(CGI) && defined?(CGI::escape)
|
7
|
+
"#{CGI.escape(key.to_param)}=#{CGI.escape(to_param.to_s)}"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__)
|
2
|
+
|
3
|
+
require 'active_resource'
|
4
|
+
require 'active_support/core_ext/class/attribute_accessors'
|
5
|
+
require 'digest/md5'
|
6
|
+
require 'base64'
|
7
|
+
require 'active_resource/detailed_log_subscriber'
|
8
|
+
require 'spiffy_stores_api/limits'
|
9
|
+
require 'spiffy_stores_api/json_format'
|
10
|
+
require 'active_resource/json_errors'
|
11
|
+
require 'active_resource/disable_prefix_check'
|
12
|
+
require 'active_resource/base_ext'
|
13
|
+
require 'active_resource/to_query'
|
14
|
+
|
15
|
+
module SpiffyStoresAPI
|
16
|
+
include Limits
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'spiffy_stores_api/metafields'
|
20
|
+
require 'spiffy_stores_api/countable'
|
21
|
+
require 'spiffy_stores_api/resources'
|
22
|
+
require 'spiffy_stores_api/session'
|
23
|
+
require 'spiffy_stores_api/connection'
|
24
|
+
|
25
|
+
if SpiffyStoresAPI::Base.respond_to?(:connection_class)
|
26
|
+
SpiffyStoresAPI::Base.connection_class = SpiffyStoresAPI::Connection
|
27
|
+
else
|
28
|
+
require 'active_resource/connection_ext'
|
29
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module SpiffyStoresAPI
|
2
|
+
class Connection < ActiveResource::Connection
|
3
|
+
attr_reader :response
|
4
|
+
|
5
|
+
module ResponseCapture
|
6
|
+
def handle_response(response)
|
7
|
+
@response = super
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
include ResponseCapture
|
12
|
+
|
13
|
+
module RequestNotification
|
14
|
+
def request(method, path, *arguments)
|
15
|
+
super.tap do |response|
|
16
|
+
notify_about_request(response, arguments)
|
17
|
+
end
|
18
|
+
rescue => e
|
19
|
+
notify_about_request(e.response, arguments) if e.respond_to?(:response)
|
20
|
+
raise
|
21
|
+
end
|
22
|
+
|
23
|
+
def notify_about_request(response, arguments)
|
24
|
+
ActiveSupport::Notifications.instrument("request.active_resource_detailed") do |payload|
|
25
|
+
payload[:response] = response
|
26
|
+
payload[:data] = arguments
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
include RequestNotification
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module ActiveResource
|
2
|
+
|
3
|
+
# ActiveResource 3.1 removes root on decoding, so this patch is only needed in 3.0
|
4
|
+
if ActiveResource::VERSION::MAJOR == 3 && ActiveResource::VERSION::MINOR == 0
|
5
|
+
module Formats
|
6
|
+
module JsonFormat
|
7
|
+
def decode(json)
|
8
|
+
data = ActiveSupport::JSON.decode(json)
|
9
|
+
if data.is_a?(Hash) && data.keys.size == 1
|
10
|
+
data.values.first
|
11
|
+
else
|
12
|
+
data
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module SpiffyStoresAPI
|
2
|
+
module Limits
|
3
|
+
class LimitUnavailable < StandardError; end
|
4
|
+
|
5
|
+
def self.included(klass)
|
6
|
+
klass.send(:extend, ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
|
11
|
+
# The ratelimit header comes from rack-ratelimit
|
12
|
+
# The parameters provided are
|
13
|
+
# name
|
14
|
+
# period
|
15
|
+
# limit
|
16
|
+
# remaining
|
17
|
+
# until
|
18
|
+
# {"name":"API","period":300,"limit":500,"remaining":496,"until":"2014-11-28T03:45:00Z"}
|
19
|
+
CREDIT_LIMIT_HEADER_PARAM = {
|
20
|
+
:store => 'http_x_ratelimit'
|
21
|
+
}
|
22
|
+
|
23
|
+
##
|
24
|
+
# How many more API calls can I make?
|
25
|
+
# @return {Integer}
|
26
|
+
#
|
27
|
+
def credit_left
|
28
|
+
credit_limit(:store) - credit_used(:store)
|
29
|
+
end
|
30
|
+
alias_method :available_calls, :credit_left
|
31
|
+
|
32
|
+
##
|
33
|
+
# Have I reached my API call limit?
|
34
|
+
# @return {Boolean}
|
35
|
+
#
|
36
|
+
def credit_maxed?
|
37
|
+
credit_left <= 0
|
38
|
+
end
|
39
|
+
alias_method :maxed?, :credit_maxed?
|
40
|
+
|
41
|
+
##
|
42
|
+
# How many total API calls can I make?
|
43
|
+
# NOTE: subtracting 1 from credit_limit because I think SpiffyStoresAPI cuts off at 299 or store limits.
|
44
|
+
# @param {Symbol} scope [:store]
|
45
|
+
# @return {Integer}
|
46
|
+
#
|
47
|
+
def credit_limit(scope=:store)
|
48
|
+
@api_credit_limit ||= {}
|
49
|
+
@api_credit_limit[scope] ||= api_credit_limit_param(scope).pop.to_i - 1
|
50
|
+
end
|
51
|
+
alias_method :call_limit, :credit_limit
|
52
|
+
|
53
|
+
##
|
54
|
+
# How many API calls have I made?
|
55
|
+
# @param {Symbol} scope [:store]
|
56
|
+
# @return {Integer}
|
57
|
+
#
|
58
|
+
def credit_used(scope=:store)
|
59
|
+
api_credit_limit_param(scope).shift.to_i
|
60
|
+
end
|
61
|
+
alias_method :call_count, :credit_used
|
62
|
+
|
63
|
+
##
|
64
|
+
# @return {HTTPResonse}
|
65
|
+
#
|
66
|
+
def response
|
67
|
+
Store.current unless SpiffyStoresAPI::Base.connection.response
|
68
|
+
SpiffyStoresAPI::Base.connection.response
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
##
|
74
|
+
# @return {Array}
|
75
|
+
#
|
76
|
+
def api_credit_limit_param(scope)
|
77
|
+
header = response[CREDIT_LIMIT_HEADER_PARAM[scope]]
|
78
|
+
raise LimitUnavailable unless header
|
79
|
+
p = JSON.parse(header)
|
80
|
+
p_limit = p['limit'].to_i
|
81
|
+
p_used = p_limit - p['remaining'].to_i
|
82
|
+
[p_used, p_limit]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module SpiffyStoresAPI
|
2
|
+
module Metafields
|
3
|
+
def metafields(**options)
|
4
|
+
options.merge!(resource: self.class.collection_name, resource_id: id)
|
5
|
+
Metafield.find(:all, params: options)
|
6
|
+
end
|
7
|
+
|
8
|
+
def add_metafield(metafield)
|
9
|
+
raise ArgumentError, "You can only add metafields to resource that has been saved" if new?
|
10
|
+
|
11
|
+
metafield.prefix_options = {
|
12
|
+
:resource => self.class.collection_name,
|
13
|
+
:resource_id => id
|
14
|
+
}
|
15
|
+
metafield.save
|
16
|
+
metafield
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module SpiffyStoresAPI
|
2
|
+
class Article < Base
|
3
|
+
include Metafields
|
4
|
+
include DisablePrefixCheck
|
5
|
+
|
6
|
+
conditional_prefix :blog
|
7
|
+
|
8
|
+
# def comments
|
9
|
+
# Comment.find(:all, :params => { :article_id => id })
|
10
|
+
# end
|
11
|
+
|
12
|
+
def self.authors(options = {})
|
13
|
+
get(:authors, options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.tags(options={})
|
17
|
+
get(:tags, options)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'spiffy_stores_api/version'
|
2
|
+
|
3
|
+
module SpiffyStoresAPI
|
4
|
+
class Base < ActiveResource::Base
|
5
|
+
class InvalidSessionError < StandardError; end
|
6
|
+
extend Countable
|
7
|
+
self.timeout = 90
|
8
|
+
self.include_root_in_json = false
|
9
|
+
self.headers['User-Agent'] = ["SpiffyStoresAPI/#{SpiffyStoresAPI::VERSION}",
|
10
|
+
"ActiveResource/#{ActiveResource::VERSION::STRING}",
|
11
|
+
"Ruby/#{RUBY_VERSION}"].join(' ')
|
12
|
+
|
13
|
+
def encode(options = {})
|
14
|
+
same = dup
|
15
|
+
same.attributes = {self.class.element_name => same.attributes} if self.class.format.extension == 'json'
|
16
|
+
|
17
|
+
same.send("to_#{self.class.format.extension}", options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def as_json(options = nil)
|
21
|
+
root = options[:root] if options.try(:key?, :root)
|
22
|
+
if include_root_in_json
|
23
|
+
root = self.class.model_name.element if root == true
|
24
|
+
{ root => serializable_hash(options) }
|
25
|
+
else
|
26
|
+
serializable_hash(options)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class << self
|
31
|
+
if ActiveResource::Base.respond_to?(:_headers) && ActiveResource::Base.respond_to?(:_headers_defined?)
|
32
|
+
def headers
|
33
|
+
if _headers_defined?
|
34
|
+
_headers
|
35
|
+
elsif superclass != Object && superclass.headers
|
36
|
+
superclass.headers
|
37
|
+
else
|
38
|
+
_headers ||= {}
|
39
|
+
end
|
40
|
+
end
|
41
|
+
else
|
42
|
+
def headers
|
43
|
+
if defined?(@headers)
|
44
|
+
@headers
|
45
|
+
elsif superclass != Object && superclass.headers
|
46
|
+
superclass.headers
|
47
|
+
else
|
48
|
+
@headers ||= {}
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def activate_session(session)
|
54
|
+
raise InvalidSessionError.new("Session cannot be nil") if session.nil?
|
55
|
+
self.site = session.site
|
56
|
+
self.headers.merge!('Authorization' => "Bearer #{session.token}")
|
57
|
+
end
|
58
|
+
|
59
|
+
def clear_session
|
60
|
+
self.site = nil
|
61
|
+
self.headers.delete('Authorization')
|
62
|
+
end
|
63
|
+
|
64
|
+
def init_prefix(resource)
|
65
|
+
init_prefix_explicit(resource.to_s.pluralize, "#{resource}_id")
|
66
|
+
end
|
67
|
+
|
68
|
+
def init_prefix_explicit(resource_type, resource_id)
|
69
|
+
self.prefix = "/api/#{resource_type}/:#{resource_id}/"
|
70
|
+
|
71
|
+
define_method resource_id.to_sym do
|
72
|
+
@prefix_options[resource_id]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def persisted?
|
78
|
+
!id.nil?
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
def only_id
|
83
|
+
encode(:only => :id, :include => [], :methods => [])
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module SpiffyStoresAPI
|
2
|
+
class Customer < Base
|
3
|
+
include Metafields
|
4
|
+
|
5
|
+
def orders
|
6
|
+
Order.find(:all, params: {customer_id: self.id})
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.search(params)
|
10
|
+
find(:all, from: :search, params: params)
|
11
|
+
end
|
12
|
+
|
13
|
+
def account_activation_url
|
14
|
+
resource = post(:account_activation_url, {}, only_id)
|
15
|
+
data = ActiveSupport::JSON.decode(resource.body.to_s)
|
16
|
+
result = nil
|
17
|
+
|
18
|
+
if data.key?('account_activation_url')
|
19
|
+
result = data['account_activation_url']
|
20
|
+
end
|
21
|
+
result
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module SpiffyStoresAPI
|
2
|
+
class Image < Base
|
3
|
+
init_prefix :product
|
4
|
+
|
5
|
+
# generate a method for each possible image variant
|
6
|
+
[:pico, :icon, :thumb, :small, :compact, :medium, :large, :grande, :original].each do |m|
|
7
|
+
reg_exp_match = "/\\1_#{m}.\\2"
|
8
|
+
define_method(m) { src.gsub(/\/(.*)\.(\w{2,4})/, reg_exp_match) }
|
9
|
+
end
|
10
|
+
|
11
|
+
def attach_image(data, filename = nil)
|
12
|
+
attributes['attachment'] = Base64.encode64(data)
|
13
|
+
attributes['filename'] = filename unless filename.nil?
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module SpiffyStoresAPI
|
2
|
+
class Metafield < Base
|
3
|
+
include DisablePrefixCheck
|
4
|
+
|
5
|
+
conditional_prefix :resource, true
|
6
|
+
|
7
|
+
def value
|
8
|
+
return if attributes["value"].nil?
|
9
|
+
attributes["value_type"] == "integer" ? attributes["value"].to_i : attributes["value"]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SpiffyStoresAPI
|
2
|
+
class Order < Base
|
3
|
+
include Metafields
|
4
|
+
|
5
|
+
def close; load_attributes_from_response(post(:close, {}, only_id)); end
|
6
|
+
def open; load_attributes_from_response(post(:open, {}, only_id)); end
|
7
|
+
|
8
|
+
def cancel(options = {})
|
9
|
+
load_attributes_from_response(post(:cancel, {}, options.to_json))
|
10
|
+
end
|
11
|
+
|
12
|
+
def transactions
|
13
|
+
Transaction.find(:all, :params => { :order_id => id })
|
14
|
+
end
|
15
|
+
|
16
|
+
def capture(amount = "")
|
17
|
+
Transaction.create(:amount => amount, :kind => "capture", :order_id => id)
|
18
|
+
end
|
19
|
+
|
20
|
+
class ClientDetails < Base
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|