spiffy_stores_api 4.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.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
|