shopify_api 2.3.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|