shopify_api 4.9.0 → 4.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +8 -0
  3. data/.travis.yml +0 -4
  4. data/CHANGELOG +18 -0
  5. data/README.md +28 -12
  6. data/lib/shopify_api/limits.rb +1 -2
  7. data/lib/shopify_api/resources/access_scope.rb +5 -0
  8. data/lib/shopify_api/resources/api_permission.rb +9 -0
  9. data/lib/shopify_api/resources/asset.rb +8 -8
  10. data/lib/shopify_api/resources/billing_address.rb +1 -1
  11. data/lib/shopify_api/resources/custom_collection.rb +3 -3
  12. data/lib/shopify_api/resources/{customer_invite_message.rb → customer_invite.rb} +0 -0
  13. data/lib/shopify_api/resources/graphql.rb +22 -0
  14. data/lib/shopify_api/resources/image.rb +2 -2
  15. data/lib/shopify_api/resources/inventory_item.rb +6 -0
  16. data/lib/shopify_api/resources/inventory_level.rb +55 -0
  17. data/lib/shopify_api/resources/line_item.rb +9 -1
  18. data/lib/shopify_api/resources/location.rb +4 -0
  19. data/lib/shopify_api/resources/o_auth.rb +8 -0
  20. data/lib/shopify_api/resources/order.rb +7 -2
  21. data/lib/shopify_api/resources/ping.rb +3 -0
  22. data/lib/shopify_api/resources/ping/conversation.rb +18 -0
  23. data/lib/shopify_api/resources/ping/message.rb +9 -0
  24. data/lib/shopify_api/resources/product.rb +4 -4
  25. data/lib/shopify_api/resources/shipping_line.rb +1 -1
  26. data/lib/shopify_api/resources/shop.rb +4 -4
  27. data/lib/shopify_api/version.rb +1 -1
  28. data/shopify_api.gemspec +2 -1
  29. data/test/api_permission_test.rb +9 -0
  30. data/test/fixtures/inventory_level.json +7 -0
  31. data/test/fixtures/inventory_levels.json +24 -0
  32. data/test/fixtures/order_with_properties.json +373 -0
  33. data/test/fixtures/ping/conversation.json +1 -0
  34. data/test/fixtures/ping/message.json +1 -0
  35. data/test/inventory_level_test.rb +59 -0
  36. data/test/location_test.rb +14 -0
  37. data/test/order_test.rb +13 -1
  38. data/test/ping/conversation_test.rb +39 -0
  39. data/test/test_helper.rb +7 -5
  40. data/test/variant_test.rb +4 -1
  41. metadata +37 -10
  42. data/lib/shopify_api/resources/discount.rb +0 -11
  43. data/test/discount_test.rb +0 -52
  44. data/test/fixtures/discount.json +0 -17
  45. data/test/fixtures/discount_disabled.json +0 -17
  46. data/test/fixtures/discounts.json +0 -34
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fff80db1065be0d32a1762d81992769fc9cde8b6
4
- data.tar.gz: 2a00b35496dcffdb72d0788c5b4bd18b90bee947
3
+ metadata.gz: ef057d0e70073f7c63a076b7f878c1c3afd062d0
4
+ data.tar.gz: 477cf304d0a68dc7e68cfac7e39c9af5617611c5
5
5
  SHA512:
6
- metadata.gz: 4d53f0ae3e229f88800e277b83c4434228b1118f39627794b62868b37a4236deb626c295ee01557e10867b7070dd227a0fc1d1429201ecff203aabb2cb80ae24
7
- data.tar.gz: 259547ebef03ae4f739ea2e7489ce0f01b8d03726037d8648c69321d8f640847872ee7b8ca27ed6c0c27ff7e4f529a04fdf35947a7b7a927a06aa05d9be5fa37
6
+ metadata.gz: c24fa3742f763e0f798a4e2d0eccd37ff2db06ba21e08e09d5853584550398db112354f39b9fd6edc55af2cc8e438f5d04b8e3ade7e704c81e2eda2a8236338f
7
+ data.tar.gz: 9886ecfff88b5b9e7dac1e1e1948fbe3ea3a0c69cbc9f13f601c413dead928bdfc68678f81d06ad74f277631f8048628252f390a37717bf17d9c1b6c4c3e016b
data/.rubocop.yml ADDED
@@ -0,0 +1,8 @@
1
+ inherit_from:
2
+ - https://shopify.github.io/ruby-style-guide/rubocop.yml
3
+
4
+ AllCops:
5
+ TargetRubyVersion: 2.4
6
+
7
+ Rails:
8
+ Enabled: false
data/.travis.yml CHANGED
@@ -2,7 +2,6 @@ language: ruby
2
2
  sudo: false
3
3
 
4
4
  rvm:
5
- - '2.0'
6
5
  - 2.3.1
7
6
  - 2.4.0-preview1
8
7
 
@@ -15,9 +14,6 @@ gemfile:
15
14
  - Gemfile_ar_master
16
15
 
17
16
  matrix:
18
- exclude:
19
- - rvm: '2.0'
20
- gemfile: Gemfile_ar_master
21
17
  fast_finish: true
22
18
  allow_failures:
23
19
  - rvm: 2.4.0-preview1
data/CHANGELOG CHANGED
@@ -1,3 +1,21 @@
1
+ == Version 4.12.0
2
+
3
+ * Added support for the GraphQL API
4
+
5
+ == Version 4.11.0
6
+
7
+ * Added `ShopifyAPI::InventoryItem`
8
+ * Added `ShopifyAPI::InventoryLevel`
9
+ * Added `#inventory_levels` method to `ShopifyAPI::Location`
10
+
11
+ == Version 4.10.0
12
+
13
+ * Added `ShopifyAPI::AccessScope`
14
+
15
+ == Version 4.9.1
16
+
17
+ * Fix a bug with custom properties for orders
18
+
1
19
  == Version 4.9.0
2
20
 
3
21
  * Added `ShopifyAPI::PriceRule`
data/README.md CHANGED
@@ -19,7 +19,7 @@ All API usage happens through Shopify applications, created by either shop owner
19
19
  * Shop owners can create applications for themselves through their own admin: https://docs.shopify.com/api/authentication/creating-a-private-app
20
20
  * Shopify Partners create applications through their admin: http://app.shopify.com/services/partners
21
21
 
22
- For more information and detailed documentation about the API visit http://api.shopify.com
22
+ For more information and detailed documentation about the API visit https://developers.shopify.com/
23
23
 
24
24
  #### Ruby version
25
25
 
@@ -39,15 +39,6 @@ Or install via [gem](http://rubygems.org/)
39
39
  gem install shopify_api
40
40
  ```
41
41
 
42
- #### Rails 5
43
-
44
- shopify_api is compatible with Rails 5 but since the latest ActiveResource release (4.1) is locked on Rails 4.x, you'll need to use the unreleased master version:
45
-
46
- ```ruby
47
- gem 'shopify_api'
48
- gem 'activeresource', github: 'rails/activeresource'
49
- ```
50
-
51
42
  ### Getting Started
52
43
 
53
44
  ShopifyAPI uses ActiveResource to communicate with the REST web service. ActiveResource has to be configured with a fully authorized URL of a particular store first. To obtain that URL you can follow these steps:
@@ -230,6 +221,30 @@ gem install shopify_cli
230
221
  shopify-cli help
231
222
  ```
232
223
 
224
+ ## GraphQL
225
+
226
+ This library also supports Shopify's new [GraphQL API](https://help.shopify.com/api/graphql-admin-api)
227
+ via a dependency on the [graphql-client](https://github.com/github/graphql-client) gem.
228
+ The authentication process (steps 1-5 under [Getting Started](#getting-started))
229
+ is identical. Once your session is activated, simply construct a new graphql
230
+ client and use `parse` and `query` as defined by
231
+ [graphql-client](https://github.com/github/graphql-client#defining-queries).
232
+
233
+ ```ruby
234
+ client = ShopifyAPI::GraphQL.new
235
+
236
+ SHOP_NAME_QUERY = client.parse <<-'GRAPHQL'
237
+ {
238
+ shop {
239
+ name
240
+ }
241
+ }
242
+ GRAPHQL
243
+
244
+ result = client.query(SHOP_NAME_QUERY)
245
+ result.data.shop.name
246
+ ```
247
+
233
248
  ## Threadsafety
234
249
 
235
250
  ActiveResource is threadsafe as of version 4.1 (which works with Rails 4.x and above).
@@ -241,12 +256,13 @@ If you were previously using Shopify's [activeresource fork](https://github.com/
241
256
  Download the source code and run:
242
257
 
243
258
  ```bash
244
- rake install
259
+ bundle install
260
+ bundle exec rake test
245
261
  ```
246
262
 
247
263
  ## Additional Resources
248
264
 
249
- API Docs: https://help.shopify.com/api/reference
265
+ API Reference: https://help.shopify.com/api/reference
250
266
 
251
267
  Ask questions on the forums: http://ecommerce.shopify.com/c/shopify-apis-and-technology
252
268
 
@@ -39,8 +39,7 @@ module ShopifyAPI
39
39
  # @return {Integer}
40
40
  #
41
41
  def credit_limit(scope=:shop)
42
- @api_credit_limit ||= {}
43
- @api_credit_limit[scope] ||= api_credit_limit_param(scope).pop.to_i - 1
42
+ api_credit_limit_param(scope).pop.to_i - 1
44
43
  end
45
44
  alias_method :call_limit, :credit_limit
46
45
 
@@ -0,0 +1,5 @@
1
+ module ShopifyAPI
2
+ class AccessScope < Base
3
+ self.prefix = '/admin/oauth/'
4
+ end
5
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShopifyAPI
4
+ class ApiPermission < Base
5
+ def self.destroy
6
+ delete(:current)
7
+ end
8
+ end
9
+ end
@@ -42,7 +42,7 @@ module ShopifyAPI
42
42
  prefix_options, query_options = split_options(prefix_options) if query_options.nil?
43
43
  "#{prefix(prefix_options)}#{collection_name}.#{format.extension}#{query_string(query_options)}"
44
44
  end
45
-
45
+
46
46
  # find an asset by key:
47
47
  # ShopifyAPI::Asset.find('layout/theme.liquid', :params => {:theme_id => 99})
48
48
  def self.find(*args)
@@ -57,7 +57,7 @@ module ShopifyAPI
57
57
  resource
58
58
  end
59
59
  end
60
-
60
+
61
61
  # For text assets, Shopify returns the data in the 'value' attribute.
62
62
  # For binary assets, the data is base-64-encoded and returned in the
63
63
  # 'attachment' attribute. This accessor returns the data in both cases.
@@ -65,28 +65,28 @@ module ShopifyAPI
65
65
  attributes['value'] ||
66
66
  (attributes['attachment'] ? Base64.decode64(attributes['attachment']) : nil)
67
67
  end
68
-
68
+
69
69
  def attach(data)
70
70
  self.attachment = Base64.encode64(data)
71
71
  end
72
-
72
+
73
73
  def destroy
74
74
  connection.delete(element_path(prefix_options.merge(:asset => {:key => key})), self.class.headers)
75
75
  end
76
-
76
+
77
77
  def new?
78
78
  false
79
79
  end
80
-
80
+
81
81
  def method_missing(method_symbol, *arguments) #:nodoc:
82
82
  if %w{value= attachment= src= source_key=}.include?(method_symbol)
83
83
  wipe_value_attributes
84
84
  end
85
85
  super
86
86
  end
87
-
87
+
88
88
  private
89
-
89
+
90
90
  def wipe_value_attributes
91
91
  %w{value attachment src source_key}.each do |attr|
92
92
  attributes.delete(attr)
@@ -1,4 +1,4 @@
1
1
  module ShopifyAPI
2
2
  class BillingAddress < Base
3
- end
3
+ end
4
4
  end
@@ -6,14 +6,14 @@ module ShopifyAPI
6
6
  def products
7
7
  Product.find(:all, :params => {:collection_id => self.id})
8
8
  end
9
-
9
+
10
10
  def add_product(product)
11
11
  Collect.create(:collection_id => self.id, :product_id => product.id)
12
12
  end
13
-
13
+
14
14
  def remove_product(product)
15
15
  collect = Collect.find(:first, :params => {:collection_id => self.id, :product_id => product.id})
16
16
  collect.destroy if collect
17
17
  end
18
- end
18
+ end
19
19
  end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+ require 'graphql/client'
3
+ require 'graphql/client/http'
4
+
5
+ module ShopifyAPI
6
+ # GraphQL API.
7
+ class GraphQL
8
+ def initialize
9
+ uri = Base.site.dup
10
+ uri.path = '/admin/api/graphql.json'
11
+ @http = ::GraphQL::Client::HTTP.new(uri.to_s) do
12
+ define_method(:headers) do |_context|
13
+ Base.headers
14
+ end
15
+ end
16
+ @schema = ::GraphQL::Client.load_schema(@http)
17
+ @client = ::GraphQL::Client.new(schema: @schema, execute: @http)
18
+ end
19
+
20
+ delegate :parse, :query, to: :@client
21
+ end
22
+ end
@@ -1,13 +1,13 @@
1
1
  module ShopifyAPI
2
2
  class Image < Base
3
3
  init_prefix :product
4
-
4
+
5
5
  # generate a method for each possible image variant
6
6
  [:pico, :icon, :thumb, :small, :compact, :medium, :large, :grande, :original].each do |m|
7
7
  reg_exp_match = "/\\1_#{m}.\\2"
8
8
  define_method(m) { src.gsub(/\/(.*)\.(\w{2,4})/, reg_exp_match) }
9
9
  end
10
-
10
+
11
11
  def attach_image(data, filename = nil)
12
12
  attributes['attachment'] = Base64.encode64(data)
13
13
  attributes['filename'] = filename unless filename.nil?
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShopifyAPI
4
+ class InventoryItem < Base
5
+ end
6
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShopifyAPI
4
+ class InventoryLevel < Base
5
+
6
+ # The default path structure in ActiveResource for delete would result in:
7
+ # /admin/inventory_levels/#{ inventory_level.id }.json?#{ params }, but since
8
+ # InventroyLevels are a second class resource made up of a Where and a What
9
+ # (Location and InventoryItem), it does not have a resource ID. Here we
10
+ # redefine element_path to remove the id so HTTP DELETE requests go to
11
+ # /admin/inventory_levels.json?#{ params } instead.
12
+ #
13
+ def self.element_path(prefix_options = {}, query_options = nil)
14
+ prefix_options, query_options = split_options(prefix_options) if query_options.nil?
15
+ "#{prefix(prefix_options)}#{collection_name}.#{format.extension}#{query_string(query_options)}"
16
+ end
17
+
18
+ def destroy
19
+ load_attributes_from_response(
20
+ self.class.delete('/', location_id: location_id, inventory_item_id: inventory_item_id)
21
+ )
22
+ end
23
+
24
+ def connect(relocate_if_necessary: nil)
25
+ body = { location_id: location_id, inventory_item_id: inventory_item_id }
26
+ body[:relocate_if_necessary] = relocate_if_necessary unless relocate_if_necessary.nil?
27
+ load_attributes_from_response(
28
+ self.class.post(:connect, {}, body.to_json)
29
+ )
30
+ end
31
+
32
+ def set(new_available, disconnect_if_necessary: nil)
33
+ body = {
34
+ location_id: location_id,
35
+ inventory_item_id: inventory_item_id,
36
+ available: new_available
37
+ }
38
+ body[:disconnect_if_necessary] = disconnect_if_necessary unless disconnect_if_necessary.nil?
39
+ load_attributes_from_response(
40
+ self.class.post(:set, {}, body.to_json)
41
+ )
42
+ end
43
+
44
+ def adjust(available_adjustment)
45
+ body = {
46
+ location_id: location_id,
47
+ inventory_item_id: inventory_item_id,
48
+ available_adjustment: available_adjustment
49
+ }
50
+ load_attributes_from_response(
51
+ self.class.post(:adjust, {}, body.to_json)
52
+ )
53
+ end
54
+ end
55
+ end
@@ -1,6 +1,14 @@
1
1
  module ShopifyAPI
2
- class LineItem < Base
2
+ class LineItem < Base
3
3
  class Property < Base
4
+ def initialize(*args)
5
+ attributes = args[0] || {}
6
+ persisted = args[1] || false
7
+ super
8
+ rescue NameError
9
+ attributes = attributes.to_hash
10
+ self
11
+ end
4
12
  end
5
13
  end
6
14
  end
@@ -1,4 +1,8 @@
1
1
  module ShopifyAPI
2
2
  class Location < Base
3
+
4
+ def inventory_levels
5
+ ShopifyAPI::InventoryLevel.find(:all, from: "/admin/locations/#{id}/inventory_levels.json")
6
+ end
3
7
  end
4
8
  end
@@ -1,8 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This resource is deprecated and will be removed in a future version of this gem.
4
+ # Use ShopifyAPI::ApiPermission.destroy instead
5
+
1
6
  module ShopifyAPI
2
7
  class OAuth < Base
3
8
  self.collection_name = 'oauth'
4
9
 
5
10
  def self.revoke
11
+ warn '[DEPRECATED] ShopifyAPI::OAuth#revoke is deprecated and will be removed in a future version. ' \
12
+ 'Use ShopifyAPI::ApiPermission#destroy instead.'
13
+
6
14
  delete(:revoke)
7
15
  end
8
16
  end
@@ -3,8 +3,13 @@ module ShopifyAPI
3
3
  include Events
4
4
  include Metafields
5
5
 
6
- def close; load_attributes_from_response(post(:close, {}, only_id)); end
7
- def open; load_attributes_from_response(post(:open, {}, only_id)); end
6
+ def close
7
+ load_attributes_from_response(post(:close, {}, only_id))
8
+ end
9
+
10
+ def open
11
+ load_attributes_from_response(post(:open, {}, only_id))
12
+ end
8
13
 
9
14
  def cancel(options = {})
10
15
  load_attributes_from_response(post(:cancel, {}, options.to_json))
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ Dir.glob("#{File.dirname(__FILE__)}/ping/*").each { |file| require file }
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShopifyAPI
4
+ module Ping
5
+ class Conversation < Base
6
+ self.prefix = "/admin/api/ping-api/v1/"
7
+
8
+ def send_message(message_attrs)
9
+ message = ShopifyAPI::Ping::Message.new(
10
+ message_attrs.merge(conversation_id: id)
11
+ )
12
+
13
+ message.save
14
+ message
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ShopifyAPI
4
+ module Ping
5
+ class Message < Base
6
+ self.prefix = "/admin/api/ping-api/v1/conversations/:conversation_id/"
7
+ end
8
+ end
9
+ end