shopify_api 2.3.0 → 3.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.
- data/RELEASING +1 -1
- data/lib/active_resource/base_ext.rb +14 -0
- data/lib/shopify_api.rb +1 -0
- data/lib/shopify_api/cli.rb +1 -0
- data/lib/shopify_api/resources.rb +1 -0
- data/lib/shopify_api/resources/base.rb +27 -0
- data/lib/shopify_api/resources/cart.rb +4 -0
- data/lib/shopify_api/session.rb +15 -106
- data/lib/shopify_api/version.rb +3 -0
- data/shopify_api.gemspec +3 -1
- data/test/base_test.rb +50 -0
- data/test/cart_test.rb +13 -0
- data/test/detailed_log_subscriber_test.rb +3 -2
- data/test/fixtures/carts.json +43 -0
- data/test/session_test.rb +17 -12
- metadata +16 -10
data/RELEASING
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
Releasing ShopifyAPI
|
2
2
|
|
3
3
|
1. Check the Semantic Versioning page for info on how to version the new release: http://semver.org
|
4
|
-
2. Update the version of ShopifyAPI in shopify_api.
|
4
|
+
2. Update the version of ShopifyAPI in lib/shopify_api/version.rb
|
5
5
|
3. Add a CHANGELOG entry for the new release with the date
|
6
6
|
4. Commit the changes with a commit message like "Packaging for release X.Y.Z"
|
7
7
|
5. Tag the release with the version (Leave REV blank for HEAD or provide a SHA)
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module ActiveResource
|
2
|
+
class Base
|
3
|
+
# Backported from ActiveResource master branch
|
4
|
+
def self.headers
|
5
|
+
@headers ||= {}
|
6
|
+
|
7
|
+
if superclass != Object && superclass.headers
|
8
|
+
@headers = superclass.headers.merge(@headers)
|
9
|
+
else
|
10
|
+
@headers
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/shopify_api.rb
CHANGED
data/lib/shopify_api/cli.rb
CHANGED
@@ -25,6 +25,7 @@ module ShopifyAPI
|
|
25
25
|
config = {'protocol' => 'https'}
|
26
26
|
config['domain'] = ask("Domain? (leave blank for #{connection}.myshopify.com)")
|
27
27
|
config['domain'] = "#{connection}.myshopify.com" if config['domain'].blank?
|
28
|
+
config['domain'] = "#{config['domain']}.myshopify.com" unless config['domain'].match(/[.:]/)
|
28
29
|
puts "\nopen https://#{config['domain']}/admin/api in your browser to get API credentials\n"
|
29
30
|
config['api_key'] = ask("API key?")
|
30
31
|
config['password'] = ask("Password?")
|
@@ -5,6 +5,7 @@ require 'shopify_api/resources/article'
|
|
5
5
|
require 'shopify_api/resources/asset'
|
6
6
|
require 'shopify_api/resources/billing_address'
|
7
7
|
require 'shopify_api/resources/blog'
|
8
|
+
require 'shopify_api/resources/cart'
|
8
9
|
require 'shopify_api/resources/collect'
|
9
10
|
require 'shopify_api/resources/comment'
|
10
11
|
require 'shopify_api/resources/country'
|
@@ -1,7 +1,34 @@
|
|
1
|
+
require 'shopify_api/version'
|
2
|
+
|
1
3
|
module ShopifyAPI
|
2
4
|
class Base < ActiveResource::Base
|
3
5
|
extend Countable
|
4
6
|
self.include_root_in_json = false
|
7
|
+
self.headers['User-Agent'] = ["ShopifyAPI/#{ShopifyAPI::VERSION}",
|
8
|
+
"ActiveResource/#{ActiveResource::VERSION::STRING}",
|
9
|
+
"Ruby/#{RUBY_VERSION}"].join(' ')
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def headers
|
13
|
+
if defined?(@headers)
|
14
|
+
@headers
|
15
|
+
elsif superclass != Object && superclass.headers
|
16
|
+
superclass.headers
|
17
|
+
else
|
18
|
+
@headers ||= {}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def activate_session(session)
|
23
|
+
self.site = session.site
|
24
|
+
self.headers.merge!('X-Shopify-Access-Token' => session.token)
|
25
|
+
end
|
26
|
+
|
27
|
+
def clear_session
|
28
|
+
self.site = nil
|
29
|
+
self.headers.delete('X-Shopify-Access-Token')
|
30
|
+
end
|
31
|
+
end
|
5
32
|
|
6
33
|
private
|
7
34
|
def only_id
|
data/lib/shopify_api/session.rb
CHANGED
@@ -1,84 +1,6 @@
|
|
1
|
+
|
1
2
|
module ShopifyAPI
|
2
|
-
|
3
|
-
# The Shopify API authenticates each call via HTTP Authentication, using
|
4
|
-
# * the application's API key as the username, and
|
5
|
-
# * a hex digest of the application's shared secret and an
|
6
|
-
# authentication token as the password.
|
7
|
-
#
|
8
|
-
# Generation & acquisition of the beforementioned looks like this:
|
9
|
-
#
|
10
|
-
# 0. Developer (that's you) registers Application (and provides a
|
11
|
-
# callback url) and receives an API key and a shared secret
|
12
|
-
#
|
13
|
-
# 1. User visits Application and are told they need to authenticate the
|
14
|
-
# application first for read/write permission to their data (needs to
|
15
|
-
# happen only once). User is asked for their shop url.
|
16
|
-
#
|
17
|
-
# 2. Application redirects to Shopify : GET <user's shop url>/admin/api/auth?api_key=<API key>
|
18
|
-
# (See Session#create_permission_url)
|
19
|
-
#
|
20
|
-
# 3. User logs-in to Shopify, approves application permission request
|
21
|
-
#
|
22
|
-
# 4. Shopify redirects to the Application's callback url (provided during
|
23
|
-
# registration), including the shop's name, and an authentication token in the parameters:
|
24
|
-
# GET client.com/customers?shop=snake-oil.myshopify.com&t=a94a110d86d2452eb3e2af4cfb8a3828
|
25
|
-
#
|
26
|
-
# 5. Authentication password computed using the shared secret and the
|
27
|
-
# authentication token (see Session#computed_password)
|
28
|
-
#
|
29
|
-
# 6. Profit!
|
30
|
-
# (API calls can now authenticate through HTTP using the API key, and
|
31
|
-
# computed password)
|
32
|
-
#
|
33
|
-
# LoginController and ShopifyLoginProtection use the Session class to set Shopify::Base.site
|
34
|
-
# so that all API calls are authorized transparently and end up just looking like this:
|
35
|
-
#
|
36
|
-
# # get 3 products
|
37
|
-
# @products = ShopifyAPI::Product.find(:all, :params => {:limit => 3})
|
38
|
-
#
|
39
|
-
# # get latest 3 orders
|
40
|
-
# @orders = ShopifyAPI::Order.find(:all, :params => {:limit => 3, :order => "created_at DESC" })
|
41
|
-
#
|
42
|
-
# As an example of what your LoginController should look like, take a look
|
43
|
-
# at the following:
|
44
|
-
#
|
45
|
-
# class LoginController < ApplicationController
|
46
|
-
# def index
|
47
|
-
# # Ask user for their #{shop}.myshopify.com address
|
48
|
-
# end
|
49
|
-
#
|
50
|
-
# def authenticate
|
51
|
-
# redirect_to ShopifyAPI::Session.new(params[:shop]).create_permission_url
|
52
|
-
# end
|
53
|
-
#
|
54
|
-
# # Shopify redirects the logged-in user back to this action along with
|
55
|
-
# # the authorization token t.
|
56
|
-
# #
|
57
|
-
# # This token is later combined with the developer's shared secret to form
|
58
|
-
# # the password used to call API methods.
|
59
|
-
# def finalize
|
60
|
-
# shopify_session = ShopifyAPI::Session.new(params[:shop], params[:t])
|
61
|
-
# if shopify_session.valid?
|
62
|
-
# session[:shopify] = shopify_session
|
63
|
-
# flash[:notice] = "Logged in to shopify store."
|
64
|
-
#
|
65
|
-
# return_address = session[:return_to] || '/home'
|
66
|
-
# session[:return_to] = nil
|
67
|
-
# redirect_to return_address
|
68
|
-
# else
|
69
|
-
# flash[:error] = "Could not log in to Shopify store."
|
70
|
-
# redirect_to :action => 'index'
|
71
|
-
# end
|
72
|
-
# end
|
73
|
-
#
|
74
|
-
# def logout
|
75
|
-
# session[:shopify] = nil
|
76
|
-
# flash[:notice] = "Successfully logged out."
|
77
|
-
#
|
78
|
-
# redirect_to :action => 'index'
|
79
|
-
# end
|
80
|
-
# end
|
81
|
-
#
|
3
|
+
|
82
4
|
class Session
|
83
5
|
cattr_accessor :api_key
|
84
6
|
cattr_accessor :secret
|
@@ -95,13 +17,18 @@ module ShopifyAPI
|
|
95
17
|
|
96
18
|
def temp(domain, token, &block)
|
97
19
|
session = new(domain, token)
|
20
|
+
begin
|
21
|
+
original_domain = URI.parse(ShopifyAPI::Base.site.to_s).host
|
22
|
+
rescue URI::InvalidURIError
|
23
|
+
end
|
24
|
+
original_token = ShopifyAPI::Base.headers['X-Shopify-Access-Token']
|
25
|
+
original_session = new(original_domain, original_token)
|
98
26
|
|
99
|
-
original_site = ShopifyAPI::Base.site
|
100
27
|
begin
|
101
|
-
ShopifyAPI::Base.
|
28
|
+
ShopifyAPI::Base.activate_session(session)
|
102
29
|
yield
|
103
30
|
ensure
|
104
|
-
ShopifyAPI::Base.
|
31
|
+
ShopifyAPI::Base.activate_session(original_session)
|
105
32
|
end
|
106
33
|
end
|
107
34
|
|
@@ -110,56 +37,38 @@ module ShopifyAPI
|
|
110
37
|
url.gsub!(/https?:\/\//, '') # remove http:// or https://
|
111
38
|
url.concat(".myshopify.com") unless url.include?('.') # extend url to myshopify.com if no host is given
|
112
39
|
end
|
113
|
-
|
40
|
+
|
114
41
|
def validate_signature(params)
|
115
42
|
return false unless signature = params[:signature]
|
116
43
|
|
117
44
|
sorted_params = params.except(:signature, :action, :controller).collect{|k,v|"#{k}=#{v}"}.sort.join
|
118
45
|
Digest::MD5.hexdigest(secret + sorted_params) == signature
|
119
46
|
end
|
120
|
-
|
47
|
+
|
121
48
|
end
|
122
49
|
|
123
50
|
def initialize(url, token = nil, params = nil)
|
124
51
|
self.url, self.token = url, token
|
52
|
+
self.class.prepare_url(self.url)
|
125
53
|
|
126
54
|
if params
|
127
55
|
unless self.class.validate_signature(params) && params[:timestamp].to_i > 24.hours.ago.utc.to_i
|
128
56
|
raise "Invalid Signature: Possible malicious login"
|
129
57
|
end
|
130
58
|
end
|
131
|
-
|
132
|
-
self.class.prepare_url(self.url)
|
133
59
|
end
|
134
60
|
|
135
61
|
def shop
|
136
62
|
Shop.current
|
137
63
|
end
|
138
|
-
|
139
|
-
def create_permission_url
|
140
|
-
return nil if url.blank? || api_key.blank?
|
141
|
-
"http://#{url}/admin/api/auth?api_key=#{api_key}"
|
142
|
-
end
|
143
64
|
|
144
|
-
# Used by ActiveResource::Base to make all non-authentication API calls
|
145
|
-
#
|
146
|
-
# (ShopifyAPI::Base.site set in ShopifyLoginProtection#shopify_session)
|
147
65
|
def site
|
148
|
-
"#{protocol}://#{
|
66
|
+
"#{protocol}://#{url}/admin"
|
149
67
|
end
|
150
68
|
|
151
69
|
def valid?
|
152
70
|
url.present? && token.present?
|
153
71
|
end
|
154
|
-
|
155
|
-
private
|
156
|
-
|
157
|
-
# The secret is computed by taking the shared_secret which we got when
|
158
|
-
# registring this third party application and concating the request_to it,
|
159
|
-
# and then calculating a MD5 hexdigest.
|
160
|
-
def computed_password
|
161
|
-
Digest::MD5.hexdigest(secret + token.to_s)
|
162
|
-
end
|
163
|
-
|
72
|
+
|
164
73
|
end
|
165
74
|
end
|
data/shopify_api.gemspec
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "shopify_api/version"
|
2
4
|
|
3
5
|
Gem::Specification.new do |s|
|
4
6
|
s.name = %q{shopify_api}
|
5
|
-
s.version =
|
7
|
+
s.version = ShopifyAPI::VERSION
|
6
8
|
s.author = "Shopify"
|
7
9
|
|
8
10
|
s.summary = %q{The Shopify API gem is a lightweight gem for accessing the Shopify admin REST web services}
|
data/test/base_test.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
|
4
|
+
class BaseTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@session1 = ShopifyAPI::Session.new('shop1.myshopify.com', 'token1')
|
8
|
+
@session2 = ShopifyAPI::Session.new('shop2.myshopify.com', 'token2')
|
9
|
+
end
|
10
|
+
|
11
|
+
test '#activate_session should set site and headers for given session' do
|
12
|
+
ShopifyAPI::Base.activate_session @session1
|
13
|
+
|
14
|
+
assert_nil ActiveResource::Base.site
|
15
|
+
assert_equal 'https://shop1.myshopify.com/admin', ShopifyAPI::Base.site.to_s
|
16
|
+
assert_equal 'https://shop1.myshopify.com/admin', ShopifyAPI::Shop.site.to_s
|
17
|
+
|
18
|
+
assert_nil ActiveResource::Base.headers['X-Shopify-Access-Token']
|
19
|
+
assert_equal 'token1', ShopifyAPI::Base.headers['X-Shopify-Access-Token']
|
20
|
+
assert_equal 'token1', ShopifyAPI::Shop.headers['X-Shopify-Access-Token']
|
21
|
+
end
|
22
|
+
|
23
|
+
test '#clear_session should clear site and headers from Base' do
|
24
|
+
ShopifyAPI::Base.activate_session @session1
|
25
|
+
ShopifyAPI::Base.clear_session
|
26
|
+
|
27
|
+
assert_nil ActiveResource::Base.site
|
28
|
+
assert_nil ShopifyAPI::Base.site
|
29
|
+
assert_nil ShopifyAPI::Shop.site
|
30
|
+
|
31
|
+
assert_nil ActiveResource::Base.headers['X-Shopify-Access-Token']
|
32
|
+
assert_nil ShopifyAPI::Base.headers['X-Shopify-Access-Token']
|
33
|
+
assert_nil ShopifyAPI::Shop.headers['X-Shopify-Access-Token']
|
34
|
+
end
|
35
|
+
|
36
|
+
test '#activate_session with one session, then clearing and activating with another session should send request to correct shop' do
|
37
|
+
ShopifyAPI::Base.activate_session @session1
|
38
|
+
ShopifyAPI::Base.clear_session
|
39
|
+
ShopifyAPI::Base.activate_session @session2
|
40
|
+
|
41
|
+
assert_nil ActiveResource::Base.site
|
42
|
+
assert_equal 'https://shop2.myshopify.com/admin', ShopifyAPI::Base.site.to_s
|
43
|
+
assert_equal 'https://shop2.myshopify.com/admin', ShopifyAPI::Shop.site.to_s
|
44
|
+
|
45
|
+
assert_nil ActiveResource::Base.headers['X-Shopify-Access-Token']
|
46
|
+
assert_equal 'token2', ShopifyAPI::Base.headers['X-Shopify-Access-Token']
|
47
|
+
assert_equal 'token2', ShopifyAPI::Shop.headers['X-Shopify-Access-Token']
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
data/test/cart_test.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class CartTest < Test::Unit::TestCase
|
4
|
+
test 'all should return all carts' do
|
5
|
+
fake 'carts'
|
6
|
+
carts = ShopifyAPI::Cart.all
|
7
|
+
assert_equal carts.size, 2
|
8
|
+
assert_equal 2, carts.first.id
|
9
|
+
assert_equal "3eed8183d4281db6ea82ee2b8f23e9cc", carts.first.token
|
10
|
+
assert_equal 1, carts.first.line_items.size
|
11
|
+
assert_equal 'test', carts.first.line_items.first.title
|
12
|
+
end
|
13
|
+
end
|
@@ -7,6 +7,7 @@ class LogSubscriberTest < Test::Unit::TestCase
|
|
7
7
|
def setup
|
8
8
|
super
|
9
9
|
@page = { :page => { :id => 1, :title => 'Shopify API' } }.to_json
|
10
|
+
@ua_header = "\"User-Agent\"=>\"ShopifyAPI/#{ShopifyAPI::VERSION} ActiveResource/#{ActiveResource::VERSION::STRING} Ruby/#{RUBY_VERSION}\""
|
10
11
|
|
11
12
|
ShopifyAPI::Base.site = "http://localhost/admin"
|
12
13
|
|
@@ -26,7 +27,7 @@ class LogSubscriberTest < Test::Unit::TestCase
|
|
26
27
|
assert_equal 4, @logger.logged(:info).size
|
27
28
|
assert_equal "GET http://localhost:80/admin/pages/1.json", @logger.logged(:info)[0]
|
28
29
|
assert_match /\-\-\> 200/, @logger.logged(:info)[1]
|
29
|
-
assert_equal "Headers: {\"Accept\"=>\"application/json\"}",
|
30
|
+
assert_equal "Headers: {\"Accept\"=>\"application/json\", #{@ua_header}}", @logger.logged(:info)[2]
|
30
31
|
assert_match /Response:\n\{\"page\"\:\{((\"id\"\:1)|(\"title\"\:\"Shopify API\")),((\"id\"\:1)|(\"title\"\:\"Shopify API\"))\}\}/, @logger.logged(:info)[3]
|
31
32
|
|
32
33
|
end
|
@@ -41,7 +42,7 @@ class LogSubscriberTest < Test::Unit::TestCase
|
|
41
42
|
assert_equal 4, @logger.logged(:info).size
|
42
43
|
assert_equal "GET http://localhost:80/admin/pages/2.json", @logger.logged(:info)[0]
|
43
44
|
assert_match /\-\-\> 404/, @logger.logged(:info)[1]
|
44
|
-
assert_equal "Headers: {\"Accept\"=>\"application/json\"}", @logger.logged(:info)[2]
|
45
|
+
assert_equal "Headers: {\"Accept\"=>\"application/json\", #{@ua_header}}", @logger.logged(:info)[2]
|
45
46
|
assert_equal "Response:", @logger.logged(:info)[3]
|
46
47
|
end
|
47
48
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
{
|
2
|
+
"carts": [
|
3
|
+
{
|
4
|
+
"id": 2,
|
5
|
+
"note": null,
|
6
|
+
"token": "3eed8183d4281db6ea82ee2b8f23e9cc",
|
7
|
+
"updated_at": "2012-02-13T14:39:37-05:00",
|
8
|
+
"line_items":
|
9
|
+
[
|
10
|
+
{
|
11
|
+
"id": 1,
|
12
|
+
"title": "test",
|
13
|
+
"price": "1.00",
|
14
|
+
"line_price": "1.00",
|
15
|
+
"quantity": 1,
|
16
|
+
"sku": "",
|
17
|
+
"grams": 1000,
|
18
|
+
"vendor": "test",
|
19
|
+
"variant_id": 1
|
20
|
+
}
|
21
|
+
]
|
22
|
+
},
|
23
|
+
{
|
24
|
+
"id": 1,
|
25
|
+
"note": "",
|
26
|
+
"token": "49801807939c296be1e9a4bf6783a705",
|
27
|
+
"updated_at": "2012-02-13T14:39:12-05:00",
|
28
|
+
"line_items":[
|
29
|
+
{
|
30
|
+
"id": 1,
|
31
|
+
"title": "test",
|
32
|
+
"price": "1.00",
|
33
|
+
"line_price": "1.00",
|
34
|
+
"quantity": 1,
|
35
|
+
"sku": "",
|
36
|
+
"grams": 1000,
|
37
|
+
"vendor": "test",
|
38
|
+
"variant_id": 1
|
39
|
+
}
|
40
|
+
]
|
41
|
+
}
|
42
|
+
]
|
43
|
+
}
|
data/test/session_test.rb
CHANGED
@@ -23,7 +23,7 @@ class SessionTest < Test::Unit::TestCase
|
|
23
23
|
session = ShopifyAPI::Session.new("testshop.myshopify.com", "any-token")
|
24
24
|
end
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
should "raise error if params passed but signature omitted" do
|
28
28
|
assert_raises(RuntimeError) do
|
29
29
|
session = ShopifyAPI::Session.new("testshop.myshopify.com", "any-token", {'foo' => 'bar'})
|
@@ -41,25 +41,30 @@ class SessionTest < Test::Unit::TestCase
|
|
41
41
|
end
|
42
42
|
|
43
43
|
should "#temp reset ShopifyAPI::Base.site to original value" do
|
44
|
-
|
45
|
-
|
44
|
+
|
46
45
|
ShopifyAPI::Session.setup(:api_key => "key", :secret => "secret")
|
47
|
-
|
46
|
+
session1 = ShopifyAPI::Session.new('fakeshop.myshopify.com', 'token1')
|
47
|
+
ShopifyAPI::Base.activate_session(session1)
|
48
|
+
|
48
49
|
ShopifyAPI::Session.temp("testshop.myshopify.com", "any-token") {
|
49
|
-
assigned_site = ShopifyAPI::Base.site
|
50
|
+
@assigned_site = ShopifyAPI::Base.site
|
50
51
|
}
|
51
|
-
assert_equal 'https://
|
52
|
-
assert_equal '
|
52
|
+
assert_equal 'https://testshop.myshopify.com/admin', @assigned_site.to_s
|
53
|
+
assert_equal 'https://fakeshop.myshopify.com/admin', ShopifyAPI::Base.site.to_s
|
53
54
|
end
|
54
55
|
|
55
|
-
should "return
|
56
|
+
should "return site for session" do
|
56
57
|
session = ShopifyAPI::Session.new("testshop.myshopify.com", "any-token")
|
57
|
-
assert_equal "
|
58
|
+
assert_equal "https://testshop.myshopify.com/admin", session.site
|
58
59
|
end
|
59
60
|
|
60
|
-
should "
|
61
|
-
|
62
|
-
|
61
|
+
should "raise error if signature does not match expected" do
|
62
|
+
ShopifyAPI::Session.secret = 'secret'
|
63
|
+
params = {:foo => 'hello', :foo => 'world', :timestamp => Time.now}
|
64
|
+
sorted_params = params.except(:signature, :action, :controller).collect{|k,v|"#{k}=#{v}"}.sort.join
|
65
|
+
signature = Digest::MD5.hexdigest(ShopifyAPI::Session.secret + sorted_params)
|
66
|
+
|
67
|
+
session = ShopifyAPI::Session.new("testshop.myshopify.com", "any-token", params.merge(:signature => signature))
|
63
68
|
end
|
64
69
|
end
|
65
70
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shopify_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-04-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activeresource
|
16
|
-
requirement: &
|
16
|
+
requirement: &70215153027780 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 3.0.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70215153027780
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: thor
|
27
|
-
requirement: &
|
27
|
+
requirement: &70215153026900 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 0.14.4
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70215153026900
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: mocha
|
38
|
-
requirement: &
|
38
|
+
requirement: &70215153026040 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 0.9.8
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70215153026040
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: fakeweb
|
49
|
-
requirement: &
|
49
|
+
requirement: &70215153062680 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,7 +54,7 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70215153062680
|
58
58
|
description: The Shopify API gem allows Ruby developers to programmatically access
|
59
59
|
the admin section of Shopify stores. The API is implemented as JSON or XML over
|
60
60
|
HTTP using all four verbs (GET/POST/PUT/DELETE). Each resource, like Order, Product,
|
@@ -76,6 +76,7 @@ files:
|
|
76
76
|
- RELEASING
|
77
77
|
- Rakefile
|
78
78
|
- bin/shopify
|
79
|
+
- lib/active_resource/base_ext.rb
|
79
80
|
- lib/active_resource/connection_ext.rb
|
80
81
|
- lib/active_resource/detailed_log_subscriber.rb
|
81
82
|
- lib/active_resource/disable_prefix_check.rb
|
@@ -95,6 +96,7 @@ files:
|
|
95
96
|
- lib/shopify_api/resources/base.rb
|
96
97
|
- lib/shopify_api/resources/billing_address.rb
|
97
98
|
- lib/shopify_api/resources/blog.rb
|
99
|
+
- lib/shopify_api/resources/cart.rb
|
98
100
|
- lib/shopify_api/resources/collect.rb
|
99
101
|
- lib/shopify_api/resources/comment.rb
|
100
102
|
- lib/shopify_api/resources/country.rb
|
@@ -129,14 +131,18 @@ files:
|
|
129
131
|
- lib/shopify_api/resources/variant.rb
|
130
132
|
- lib/shopify_api/resources/webhook.rb
|
131
133
|
- lib/shopify_api/session.rb
|
134
|
+
- lib/shopify_api/version.rb
|
132
135
|
- shopify_api.gemspec
|
133
136
|
- test/asset_test.rb
|
137
|
+
- test/base_test.rb
|
134
138
|
- test/blog_test.rb
|
139
|
+
- test/cart_test.rb
|
135
140
|
- test/cli_test.rb
|
136
141
|
- test/detailed_log_subscriber_test.rb
|
137
142
|
- test/fixtures/asset.json
|
138
143
|
- test/fixtures/assets.json
|
139
144
|
- test/fixtures/blogs.json
|
145
|
+
- test/fixtures/carts.json
|
140
146
|
- test/fixtures/events.json
|
141
147
|
- test/fixtures/metafield.json
|
142
148
|
- test/fixtures/metafields.json
|