shopify_api 9.2.0 → 9.5
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 +4 -4
- data/.github/CODEOWNERS +1 -1
- data/.github/ISSUE_TEMPLATE.md +36 -0
- data/.github/workflows/build.yml +44 -0
- data/.gitignore +0 -1
- data/.rubocop.yml +23 -3
- data/.rubocop_todo.yml +75 -0
- data/CHANGELOG.md +29 -0
- data/Gemfile +1 -0
- data/Gemfile.lock +153 -0
- data/Gemfile_ar51 +1 -1
- data/README.md +41 -31
- data/RELEASING +10 -6
- data/Rakefile +10 -6
- data/dev.yml +11 -0
- data/docs/graphql.md +1 -1
- data/docs/index.md +1 -1
- data/lib/active_resource/connection_ext.rb +1 -0
- data/lib/active_resource/detailed_log_subscriber.rb +10 -7
- data/lib/active_resource/json_errors.rb +8 -2
- data/lib/shopify_api/api_access.rb +57 -0
- data/lib/shopify_api/api_version.rb +6 -5
- data/lib/shopify_api/connection.rb +1 -0
- data/lib/shopify_api/countable.rb +3 -2
- data/lib/shopify_api/disable_prefix_check.rb +2 -2
- data/lib/shopify_api/events.rb +2 -1
- data/lib/shopify_api/graphql.rb +8 -6
- data/lib/shopify_api/hmac_params.rb +23 -0
- data/lib/shopify_api/limits.rb +3 -2
- data/lib/shopify_api/message_enricher.rb +11 -9
- data/lib/shopify_api/meta.rb +0 -1
- data/lib/shopify_api/metafields.rb +5 -4
- data/lib/shopify_api/pagination_link_headers.rb +4 -3
- data/lib/shopify_api/resources/access_scope.rb +1 -1
- data/lib/shopify_api/resources/access_token.rb +1 -0
- data/lib/shopify_api/resources/address.rb +1 -0
- data/lib/shopify_api/resources/announcement.rb +2 -1
- data/lib/shopify_api/resources/application_charge.rb +1 -0
- data/lib/shopify_api/resources/application_credit.rb +1 -0
- data/lib/shopify_api/resources/article.rb +3 -2
- data/lib/shopify_api/resources/asset.rb +6 -5
- data/lib/shopify_api/resources/assigned_fulfillment_order.rb +1 -1
- data/lib/shopify_api/resources/base.rb +11 -6
- data/lib/shopify_api/resources/billing_address.rb +1 -0
- data/lib/shopify_api/resources/blog.rb +2 -1
- data/lib/shopify_api/resources/carrier_service.rb +1 -0
- data/lib/shopify_api/resources/cart.rb +2 -1
- data/lib/shopify_api/resources/collect.rb +1 -0
- data/lib/shopify_api/resources/collection_listing.rb +1 -0
- data/lib/shopify_api/resources/comment.rb +20 -5
- data/lib/shopify_api/resources/country.rb +1 -0
- data/lib/shopify_api/resources/custom_collection.rb +4 -3
- data/lib/shopify_api/resources/customer.rb +2 -1
- data/lib/shopify_api/resources/customer_group.rb +1 -0
- data/lib/shopify_api/resources/customer_invite.rb +1 -0
- data/lib/shopify_api/resources/customer_saved_search.rb +2 -1
- data/lib/shopify_api/resources/discount_code.rb +1 -0
- data/lib/shopify_api/resources/discount_code_batch.rb +4 -2
- data/lib/shopify_api/resources/draft_order.rb +1 -0
- data/lib/shopify_api/resources/draft_order_invoice.rb +1 -0
- data/lib/shopify_api/resources/event.rb +1 -0
- data/lib/shopify_api/resources/fulfillment.rb +12 -3
- data/lib/shopify_api/resources/fulfillment_event.rb +1 -0
- data/lib/shopify_api/resources/fulfillment_order.rb +30 -16
- data/lib/shopify_api/resources/fulfillment_order_locations_for_move.rb +1 -0
- data/lib/shopify_api/resources/fulfillment_request.rb +1 -0
- data/lib/shopify_api/resources/fulfillment_service.rb +1 -0
- data/lib/shopify_api/resources/fulfillment_v2.rb +3 -2
- data/lib/shopify_api/resources/gift_card.rb +1 -0
- data/lib/shopify_api/resources/image.rb +2 -1
- data/lib/shopify_api/resources/inventory_level.rb +2 -3
- data/lib/shopify_api/resources/line_item.rb +4 -3
- data/lib/shopify_api/resources/location.rb +1 -1
- data/lib/shopify_api/resources/marketing_event.rb +1 -0
- data/lib/shopify_api/resources/metafield.rb +1 -0
- data/lib/shopify_api/resources/note_attribute.rb +1 -0
- data/lib/shopify_api/resources/option.rb +1 -0
- data/lib/shopify_api/resources/order.rb +2 -1
- data/lib/shopify_api/resources/order_risk.rb +1 -0
- data/lib/shopify_api/resources/page.rb +1 -0
- data/lib/shopify_api/resources/payment_details.rb +1 -0
- data/lib/shopify_api/resources/policy.rb +1 -0
- data/lib/shopify_api/resources/price_rule.rb +1 -1
- data/lib/shopify_api/resources/product.rb +14 -11
- data/lib/shopify_api/resources/product_listing.rb +1 -0
- data/lib/shopify_api/resources/province.rb +1 -0
- data/lib/shopify_api/resources/receipt.rb +1 -0
- data/lib/shopify_api/resources/recurring_application_charge.rb +4 -1
- data/lib/shopify_api/resources/redirect.rb +1 -0
- data/lib/shopify_api/resources/refund.rb +2 -1
- data/lib/shopify_api/resources/report.rb +1 -0
- data/lib/shopify_api/resources/resource_feedback.rb +1 -1
- data/lib/shopify_api/resources/rule.rb +1 -0
- data/lib/shopify_api/resources/script_tag.rb +1 -0
- data/lib/shopify_api/resources/shipping_address.rb +1 -0
- data/lib/shopify_api/resources/shipping_line.rb +1 -0
- data/lib/shopify_api/resources/shipping_zone.rb +1 -0
- data/lib/shopify_api/resources/shop.rb +2 -1
- data/lib/shopify_api/resources/smart_collection.rb +2 -2
- data/lib/shopify_api/resources/storefront_access_token.rb +1 -0
- data/lib/shopify_api/resources/tax_line.rb +1 -0
- data/lib/shopify_api/resources/tax_service.rb +1 -0
- data/lib/shopify_api/resources/theme.rb +1 -0
- data/lib/shopify_api/resources/transaction.rb +1 -0
- data/lib/shopify_api/resources/usage_charge.rb +1 -0
- data/lib/shopify_api/resources/user.rb +1 -0
- data/lib/shopify_api/resources/variant.rb +16 -18
- data/lib/shopify_api/resources/webhook.rb +1 -0
- data/lib/shopify_api/resources.rb +1 -0
- data/lib/shopify_api/session.rb +29 -19
- data/lib/shopify_api/version.rb +2 -1
- data/lib/shopify_api.rb +9 -1
- data/lib/verify_docs.rb +1 -0
- data/service.yml +2 -5
- data/shopify_api.gemspec +12 -5
- data/test/access_token_test.rb +6 -5
- data/test/active_resource/json_errors_test.rb +6 -6
- data/test/api_access_test.rb +153 -0
- data/test/api_version_test.rb +3 -3
- data/test/application_charge_test.rb +30 -27
- data/test/application_credit_test.rb +10 -9
- data/test/article_test.rb +34 -35
- data/test/asset_test.rb +14 -6
- data/test/assigned_fulfillment_order_test.rb +5 -4
- data/test/base_test.rb +55 -56
- data/test/blog_test.rb +4 -3
- data/test/carrier_service_test.rb +7 -6
- data/test/cart_test.rb +2 -1
- data/test/collect_test.rb +4 -3
- data/test/collection_listing_test.rb +21 -16
- data/test/collection_publication_test.rb +8 -8
- data/test/collection_test.rb +20 -19
- data/test/countable_test.rb +3 -2
- data/test/currency_test.rb +5 -5
- data/test/custom_collection_test.rb +4 -3
- data/test/customer_saved_search_test.rb +18 -8
- data/test/customer_test.rb +22 -14
- data/test/detailed_log_subscriber_test.rb +16 -12
- data/test/discount_code_batch_test.rb +11 -10
- data/test/discount_code_test.rb +21 -15
- data/test/draft_order_test.rb +68 -52
- data/test/fixtures/assigned_fulfillment_orders.json +2 -0
- data/test/fixtures/fulfillment_order.json +1 -0
- data/test/fixtures/fulfillment_orders.json +2 -0
- data/test/fulfillment_event_test.rb +31 -26
- data/test/fulfillment_order_test.rb +217 -149
- data/test/fulfillment_order_test_helper.rb +1 -0
- data/test/fulfillment_request_test.rb +10 -8
- data/test/fulfillment_service_test.rb +13 -12
- data/test/fulfillment_test.rb +81 -66
- data/test/fulfillment_v2_test.rb +16 -12
- data/test/gift_card_test.rb +6 -4
- data/test/graphql_test.rb +27 -27
- data/test/hmac_params_test.rb +25 -0
- data/test/image_test.rb +19 -17
- data/test/inventory_level_test.rb +24 -15
- data/test/lib/webmock_extensions/last_request.rb +1 -1
- data/test/limits_test.rb +2 -1
- data/test/location_test.rb +2 -1
- data/test/marketing_event_test.rb +20 -20
- data/test/message_enricher_test.rb +6 -6
- data/test/meta_test.rb +9 -11
- data/test/metafield_test.rb +30 -20
- data/test/order_risk_test.rb +17 -16
- data/test/order_test.rb +43 -28
- data/test/pagination_test.rb +89 -56
- data/test/policy_test.rb +6 -5
- data/test/price_rule_test.rb +20 -15
- data/test/product_listing_test.rb +20 -20
- data/test/product_publication_test.rb +8 -8
- data/test/product_test.rb +44 -32
- data/test/publication_test.rb +3 -3
- data/test/recurring_application_charge_test.rb +104 -42
- data/test/redirect_test.rb +4 -3
- data/test/refund_test.rb +22 -17
- data/test/report_test.rb +12 -10
- data/test/resource_feedback_test.rb +14 -13
- data/test/script_tag_test.rb +10 -9
- data/test/session_test.rb +159 -48
- data/test/shipping_zone_test.rb +4 -3
- data/test/shop_test.rb +47 -33
- data/test/smart_collection_test.rb +5 -4
- data/test/storefront_access_token_test.rb +13 -15
- data/test/tax_service_test.rb +7 -4
- data/test/tender_transaction_test.rb +3 -3
- data/test/test_helper.rb +13 -11
- data/test/transaction_test.rb +4 -3
- data/test/usage_charge_test.rb +12 -8
- data/test/user_test.rb +4 -3
- data/test/variant_test.rb +23 -54
- data/test/webhook_test.rb +10 -7
- metadata +34 -12
- data/.rubocop-https---shopify-github-io-ruby-style-guide-rubocop-yml +0 -1027
- data/.travis.yml +0 -28
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module ActiveResource
|
|
2
3
|
class DetailedLogSubscriber < ActiveSupport::LogSubscriber
|
|
3
4
|
VERSION_EOL_WARNING_HEADER = 'x-shopify-api-version-warning'
|
|
4
5
|
VERSION_DEPRECATION_HEADER = 'x-shopify-api-deprecated-reason'
|
|
6
|
+
SHOPIFY_ACCESS_TOKEN = 'X-Shopify-Access-Token'
|
|
7
|
+
FILTERED = '[FILTERED]'
|
|
8
|
+
|
|
5
9
|
def request(event)
|
|
6
10
|
log_request_response_details(event)
|
|
7
11
|
warn_on_deprecated_header_or_version_eol_header(event)
|
|
@@ -16,11 +20,12 @@ module ActiveResource
|
|
|
16
20
|
def log_request_response_details(event)
|
|
17
21
|
data = event.payload[:data]
|
|
18
22
|
headers = data.extract_options!
|
|
23
|
+
headers[SHOPIFY_ACCESS_TOKEN] = FILTERED
|
|
19
24
|
request_body = data.first
|
|
20
25
|
|
|
21
|
-
info
|
|
22
|
-
info
|
|
23
|
-
info
|
|
26
|
+
info("Request:\n#{request_body}") if request_body
|
|
27
|
+
info("Headers: #{headers.inspect}")
|
|
28
|
+
info("Response:\n#{event.payload[:response].body}")
|
|
24
29
|
end
|
|
25
30
|
|
|
26
31
|
def warn_on_deprecated_header_or_version_eol_header(event)
|
|
@@ -34,7 +39,7 @@ module ActiveResource
|
|
|
34
39
|
use of a deprecated endpoint, behaviour, or parameter. See #{header_value} for more details.
|
|
35
40
|
MSG
|
|
36
41
|
|
|
37
|
-
warn
|
|
42
|
+
warn(warning_message)
|
|
38
43
|
|
|
39
44
|
when VERSION_EOL_WARNING_HEADER
|
|
40
45
|
warning_message = <<-MSG
|
|
@@ -42,11 +47,9 @@ module ActiveResource
|
|
|
42
47
|
an API version that is unsupported or will become unsupported within 30 days. See #{header_value} for more details.
|
|
43
48
|
MSG
|
|
44
49
|
|
|
45
|
-
warn
|
|
50
|
+
warn(warning_message)
|
|
46
51
|
end
|
|
47
52
|
end
|
|
48
53
|
end
|
|
49
54
|
end
|
|
50
55
|
end
|
|
51
|
-
|
|
52
|
-
ActiveResource::DetailedLogSubscriber.attach_to :active_resource_detailed
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'active_resource/base'
|
|
2
3
|
|
|
3
4
|
module ActiveResource
|
|
4
5
|
class Errors < ActiveModel::Errors
|
|
5
6
|
def from_json(json, save_cache = false)
|
|
6
|
-
data =
|
|
7
|
+
data =
|
|
8
|
+
begin
|
|
9
|
+
ActiveSupport::JSON.decode(json)['errors'] || {}
|
|
10
|
+
rescue
|
|
11
|
+
{}
|
|
12
|
+
end
|
|
7
13
|
case data
|
|
8
14
|
when String
|
|
9
15
|
from_string(data, save_cache)
|
|
@@ -15,7 +21,7 @@ module ActiveResource
|
|
|
15
21
|
def from_hash(messages, save_cache = false)
|
|
16
22
|
clear unless save_cache
|
|
17
23
|
|
|
18
|
-
messages.each do |key,errors|
|
|
24
|
+
messages.each do |key, errors|
|
|
19
25
|
errors.each do |error|
|
|
20
26
|
add(key, error)
|
|
21
27
|
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ShopifyAPI
|
|
4
|
+
class ApiAccess
|
|
5
|
+
SCOPE_DELIMITER = ','
|
|
6
|
+
|
|
7
|
+
def initialize(scope_names)
|
|
8
|
+
if scope_names.is_a?(String)
|
|
9
|
+
scope_names = scope_names.to_s.split(SCOPE_DELIMITER)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
store_scopes(scope_names)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def covers?(scopes)
|
|
16
|
+
scopes.compressed_scopes <= expanded_scopes
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def to_s
|
|
20
|
+
to_a.join(SCOPE_DELIMITER)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def to_a
|
|
24
|
+
compressed_scopes.to_a
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def ==(other)
|
|
28
|
+
other.class == self.class &&
|
|
29
|
+
compressed_scopes == other.compressed_scopes
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
alias :eql? :==
|
|
33
|
+
|
|
34
|
+
def hash
|
|
35
|
+
compressed_scopes.hash
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
protected
|
|
39
|
+
|
|
40
|
+
attr_reader :compressed_scopes, :expanded_scopes
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def store_scopes(scope_names)
|
|
45
|
+
scopes = scope_names.map(&:strip).reject(&:empty?).to_set
|
|
46
|
+
implied_scopes = scopes.map { |scope| implied_scope(scope) }.compact
|
|
47
|
+
|
|
48
|
+
@compressed_scopes = scopes - implied_scopes
|
|
49
|
+
@expanded_scopes = scopes + implied_scopes
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def implied_scope(scope)
|
|
53
|
+
is_write_scope = scope =~ /\A(unauthenticated_)?write_(.*)\z/
|
|
54
|
+
"#{$1}read_#{$2}" if is_write_scope
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -54,8 +54,8 @@ module ShopifyAPI
|
|
|
54
54
|
|
|
55
55
|
def define_known_versions
|
|
56
56
|
warn(
|
|
57
|
-
'[DEPRECATED] ShopifyAPI::ApiVersion.define_known_versions is deprecated and will be
|
|
58
|
-
'Use `fetch_known_versions` instead.'
|
|
57
|
+
'[DEPRECATED] ShopifyAPI::ApiVersion.define_known_versions is deprecated and will be ' \
|
|
58
|
+
'removed in a future version. Use `fetch_known_versions` instead.'
|
|
59
59
|
)
|
|
60
60
|
fetch_known_versions
|
|
61
61
|
end
|
|
@@ -70,15 +70,16 @@ module ShopifyAPI
|
|
|
70
70
|
|
|
71
71
|
def clear_defined_versions
|
|
72
72
|
warn(
|
|
73
|
-
'[DEPRECATED] ShopifyAPI::ApiVersion.clear_defined_versions is deprecated and will be
|
|
74
|
-
'Use `clear_known_versions` instead.'
|
|
73
|
+
'[DEPRECATED] ShopifyAPI::ApiVersion.clear_defined_versions is deprecated and will be ' \
|
|
74
|
+
'removed in a future version. Use `clear_known_versions` instead.'
|
|
75
75
|
)
|
|
76
76
|
clear_known_versions
|
|
77
77
|
end
|
|
78
78
|
|
|
79
79
|
def latest_stable_version
|
|
80
80
|
warn(
|
|
81
|
-
'[DEPRECATED] ShopifyAPI::ApiVersion.latest_stable_version is deprecated and will be
|
|
81
|
+
'[DEPRECATED] ShopifyAPI::ApiVersion.latest_stable_version is deprecated and will be ' \
|
|
82
|
+
'removed in a future version.'
|
|
82
83
|
)
|
|
83
84
|
versions.values.find(&:latest_supported?)
|
|
84
85
|
end
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module ShopifyAPI
|
|
2
3
|
module Countable
|
|
3
4
|
def count(options = {})
|
|
4
5
|
data = get(:count, options)
|
|
5
6
|
|
|
6
7
|
count = case data
|
|
7
|
-
|
|
8
|
-
|
|
8
|
+
when Hash then data["count"]
|
|
9
|
+
else data
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
Integer(count)
|
|
@@ -14,13 +14,13 @@ module ShopifyAPI
|
|
|
14
14
|
|
|
15
15
|
init_prefix_explicit(resource_type, resource_id)
|
|
16
16
|
|
|
17
|
-
define_singleton_method
|
|
17
|
+
define_singleton_method(:resource_prefix) do |options = {}|
|
|
18
18
|
resource_type = options[resource] if flexible
|
|
19
19
|
|
|
20
20
|
options[resource_id].nil? ? '' : "#{resource_type}/#{options[resource_id]}/"
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
define_singleton_method
|
|
23
|
+
define_singleton_method(:instantiate_record) do |record, prefix_options = {}|
|
|
24
24
|
new(record, true).tap do |resource_instance|
|
|
25
25
|
resource_instance.prefix_options = prefix_options unless prefix_options.blank?
|
|
26
26
|
end
|
data/lib/shopify_api/events.rb
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module ShopifyAPI
|
|
2
3
|
module Events
|
|
3
4
|
def events
|
|
4
|
-
Event.find(:all, :
|
|
5
|
+
Event.find(:all, params: { resource: self.class.collection_name, resource_id: id })
|
|
5
6
|
end
|
|
6
7
|
end
|
|
7
8
|
end
|
data/lib/shopify_api/graphql.rb
CHANGED
|
@@ -30,7 +30,10 @@ module ShopifyAPI
|
|
|
30
30
|
To dump the schema file, use the `rake shopify_api:graphql:dump` task.
|
|
31
31
|
MSG
|
|
32
32
|
else
|
|
33
|
-
puts
|
|
33
|
+
puts(
|
|
34
|
+
'[WARNING] Client was not pre-initialized. Ensure `ShopifyAPI::GraphQL.initialize_clients` ' \
|
|
35
|
+
'is called during app initialization.'
|
|
36
|
+
)
|
|
34
37
|
initialize_clients
|
|
35
38
|
@_client_cache[api_version]
|
|
36
39
|
end
|
|
@@ -50,12 +53,11 @@ module ShopifyAPI
|
|
|
50
53
|
|
|
51
54
|
if matches
|
|
52
55
|
api_version = ShopifyAPI::ApiVersion.new(handle: matches[1])
|
|
56
|
+
elsif raise_on_invalid_schema
|
|
57
|
+
raise InvalidSchema,
|
|
58
|
+
"Invalid schema file name `#{schema_file}`. Does not match format of: `<version>.json`."
|
|
53
59
|
else
|
|
54
|
-
|
|
55
|
-
raise InvalidSchema, "Invalid schema file name `#{schema_file}`. Does not match format of: `<version>.json`."
|
|
56
|
-
else
|
|
57
|
-
next
|
|
58
|
-
end
|
|
60
|
+
next
|
|
59
61
|
end
|
|
60
62
|
|
|
61
63
|
schema = graphql_client.load_schema(schema_file.to_s)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require 'webrick/httputils'
|
|
3
|
+
|
|
4
|
+
module ShopifyAPI
|
|
5
|
+
module HmacParams
|
|
6
|
+
extend WEBrick::HTTPUtils
|
|
7
|
+
|
|
8
|
+
def self.encode(params)
|
|
9
|
+
params
|
|
10
|
+
.except(:signature, :hmac, :action, :controller)
|
|
11
|
+
.map { |k,v| sprintf("%s=%s", encode_key(k), encode_value(v)) }
|
|
12
|
+
.sort.join("&")
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.encode_key(key)
|
|
16
|
+
_escape(key.to_s, _make_regex('&=%'))
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.encode_value(value)
|
|
20
|
+
_escape(value.to_s, _make_regex('&%'))
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
data/lib/shopify_api/limits.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module ShopifyAPI
|
|
2
3
|
module Limits
|
|
3
4
|
class LimitUnavailable < StandardError; end
|
|
@@ -38,7 +39,7 @@ module ShopifyAPI
|
|
|
38
39
|
# @param {Symbol} scope [:shop]
|
|
39
40
|
# @return {Integer}
|
|
40
41
|
#
|
|
41
|
-
def credit_limit(scope
|
|
42
|
+
def credit_limit(scope = :shop)
|
|
42
43
|
api_credit_limit_param(scope).pop.to_i - 1
|
|
43
44
|
end
|
|
44
45
|
alias_method :call_limit, :credit_limit
|
|
@@ -48,7 +49,7 @@ module ShopifyAPI
|
|
|
48
49
|
# @param {Symbol} scope [:shop]
|
|
49
50
|
# @return {Integer}
|
|
50
51
|
#
|
|
51
|
-
def credit_used(scope
|
|
52
|
+
def credit_used(scope = :shop)
|
|
52
53
|
api_credit_limit_param(scope).shift.to_i
|
|
53
54
|
end
|
|
54
55
|
alias_method :call_count, :credit_used
|
|
@@ -1,20 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module ShopifyAPI
|
|
2
3
|
class MessageEnricher < SimpleDelegator
|
|
3
4
|
def message
|
|
4
5
|
return super unless (400...500).include?(code.to_i)
|
|
5
6
|
|
|
6
7
|
@_cached_message ||= begin
|
|
7
|
-
detailed_error =
|
|
8
|
-
|
|
8
|
+
detailed_error =
|
|
9
|
+
begin
|
|
10
|
+
parsed_body = JSON.parse(body)
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
if parsed_body['error']
|
|
13
|
+
parsed_body['error'].to_s
|
|
14
|
+
elsif parsed_body['errors']
|
|
15
|
+
Array(parsed_body['errors']).join('; ')
|
|
16
|
+
end
|
|
17
|
+
rescue JSON::ParserError
|
|
18
|
+
nil
|
|
14
19
|
end
|
|
15
|
-
rescue JSON::ParserError
|
|
16
|
-
nil
|
|
17
|
-
end
|
|
18
20
|
|
|
19
21
|
detailed_error.present? ? "#{super} (#{detailed_error})" : super
|
|
20
22
|
end
|
data/lib/shopify_api/meta.rb
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module ShopifyAPI
|
|
2
3
|
module Metafields
|
|
3
4
|
def metafields(**options)
|
|
4
|
-
options.merge!
|
|
5
|
+
options.merge!(resource: self.class.collection_name, resource_id: id)
|
|
5
6
|
|
|
6
|
-
Metafield.find
|
|
7
|
+
Metafield.find(:all, params: options)
|
|
7
8
|
end
|
|
8
9
|
|
|
9
10
|
def add_metafield(metafield)
|
|
10
11
|
raise ArgumentError, "You can only add metafields to resource that has been saved" if new?
|
|
11
12
|
|
|
12
13
|
metafield.prefix_options = {
|
|
13
|
-
:
|
|
14
|
-
:
|
|
14
|
+
resource: self.class.collection_name,
|
|
15
|
+
resource_id: id,
|
|
15
16
|
}
|
|
16
17
|
metafield.save
|
|
17
18
|
metafield
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module ShopifyAPI
|
|
2
3
|
class InvalidPaginationLinksError < StandardError; end
|
|
3
4
|
|
|
@@ -9,8 +10,6 @@ module ShopifyAPI
|
|
|
9
10
|
links = parse_link_header(link_header)
|
|
10
11
|
@previous_link = links.find { |link| link.rel == :previous }
|
|
11
12
|
@next_link = links.find { |link| link.rel == :next }
|
|
12
|
-
|
|
13
|
-
self
|
|
14
13
|
end
|
|
15
14
|
|
|
16
15
|
private
|
|
@@ -20,7 +19,9 @@ module ShopifyAPI
|
|
|
20
19
|
links = link_header.split(',')
|
|
21
20
|
links.map do |link|
|
|
22
21
|
parts = link.split('; ')
|
|
23
|
-
|
|
22
|
+
unless parts.length == 2
|
|
23
|
+
raise ShopifyAPI::InvalidPaginationLinksError, "Invalid link header: url and rel expected"
|
|
24
|
+
end
|
|
24
25
|
|
|
25
26
|
url = parts[0][/<(.*)>/, 1]
|
|
26
27
|
rel = parts[1][/rel="(.*)"/, 1]&.to_sym
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module ShopifyAPI
|
|
2
3
|
class Article < Base
|
|
3
4
|
include Events
|
|
@@ -7,14 +8,14 @@ module ShopifyAPI
|
|
|
7
8
|
conditional_prefix :blog
|
|
8
9
|
|
|
9
10
|
def comments
|
|
10
|
-
Comment.find(:all, :
|
|
11
|
+
Comment.find(:all, params: { article_id: id })
|
|
11
12
|
end
|
|
12
13
|
|
|
13
14
|
def self.authors(options = {})
|
|
14
15
|
get(:authors, options)
|
|
15
16
|
end
|
|
16
17
|
|
|
17
|
-
def self.tags(options={})
|
|
18
|
+
def self.tags(options = {})
|
|
18
19
|
get(:tags, options)
|
|
19
20
|
end
|
|
20
21
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module ShopifyAPI
|
|
2
3
|
# Assets represent the files that comprise your theme.
|
|
3
4
|
# There are different buckets which hold different kinds
|
|
@@ -9,10 +10,10 @@ module ShopifyAPI
|
|
|
9
10
|
# or assets/bg-body.gif.
|
|
10
11
|
#
|
|
11
12
|
# Initialize with a key:
|
|
12
|
-
# asset = ShopifyAPI::Asset.new(:
|
|
13
|
+
# asset = ShopifyAPI::Asset.new(key: 'assets/special.css', theme_id: 12345)
|
|
13
14
|
#
|
|
14
15
|
# Find by key:
|
|
15
|
-
# asset = ShopifyAPI::Asset.find('assets/image.png', :
|
|
16
|
+
# asset = ShopifyAPI::Asset.find('assets/image.png', params: {theme_id: 12345})
|
|
16
17
|
#
|
|
17
18
|
# Get the text or binary value:
|
|
18
19
|
# asset.value # decodes from attachment attribute if necessary
|
|
@@ -38,13 +39,13 @@ module ShopifyAPI
|
|
|
38
39
|
|
|
39
40
|
conditional_prefix :theme
|
|
40
41
|
|
|
41
|
-
def self.element_path(
|
|
42
|
+
def self.element_path(_id, prefix_options = {}, query_options = nil) #:nodoc:
|
|
42
43
|
prefix_options, query_options = split_options(prefix_options) if query_options.nil?
|
|
43
44
|
"#{prefix(prefix_options)}#{collection_name}.#{format.extension}#{query_string(query_options)}"
|
|
44
45
|
end
|
|
45
46
|
|
|
46
47
|
# find an asset by key:
|
|
47
|
-
# ShopifyAPI::Asset.find('layout/theme.liquid', :
|
|
48
|
+
# ShopifyAPI::Asset.find('layout/theme.liquid', params: { theme_id: 99 })
|
|
48
49
|
def self.find(*args)
|
|
49
50
|
if args[0].is_a?(Symbol)
|
|
50
51
|
super
|
|
@@ -75,7 +76,7 @@ module ShopifyAPI
|
|
|
75
76
|
end
|
|
76
77
|
|
|
77
78
|
def destroy
|
|
78
|
-
connection.delete(element_path(prefix_options.merge(:
|
|
79
|
+
connection.delete(element_path(prefix_options.merge(asset: { key: key })), self.class.headers)
|
|
79
80
|
end
|
|
80
81
|
|
|
81
82
|
def new?
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'shopify_api/version'
|
|
2
3
|
|
|
3
4
|
module ShopifyAPI
|
|
@@ -15,7 +16,7 @@ module ShopifyAPI
|
|
|
15
16
|
|
|
16
17
|
def encode(options = {})
|
|
17
18
|
same = dup
|
|
18
|
-
same.attributes = {self.class.element_name => same.attributes} if self.class.format.extension == 'json'
|
|
19
|
+
same.attributes = { self.class.element_name => same.attributes } if self.class.format.extension == 'json'
|
|
19
20
|
|
|
20
21
|
same.send("to_#{self.class.format.extension}", options)
|
|
21
22
|
end
|
|
@@ -43,7 +44,7 @@ module ShopifyAPI
|
|
|
43
44
|
end
|
|
44
45
|
|
|
45
46
|
def activate_session(session)
|
|
46
|
-
raise InvalidSessionError
|
|
47
|
+
raise InvalidSessionError, "Session cannot be nil" if session.nil?
|
|
47
48
|
self.site = session.site
|
|
48
49
|
self.headers.merge!('X-Shopify-Access-Token' => session.token)
|
|
49
50
|
self.api_version = session.api_version
|
|
@@ -67,7 +68,11 @@ module ShopifyAPI
|
|
|
67
68
|
end
|
|
68
69
|
|
|
69
70
|
def api_version=(version)
|
|
70
|
-
self._api_version = ApiVersion::NullVersion.matches?(version)
|
|
71
|
+
self._api_version = if ApiVersion::NullVersion.matches?(version)
|
|
72
|
+
ApiVersion::NullVersion
|
|
73
|
+
else
|
|
74
|
+
ApiVersion.find_version(version)
|
|
75
|
+
end
|
|
71
76
|
end
|
|
72
77
|
|
|
73
78
|
def prefix(options = {})
|
|
@@ -91,7 +96,7 @@ module ShopifyAPI
|
|
|
91
96
|
|
|
92
97
|
silence_warnings do
|
|
93
98
|
# Redefine the new methods.
|
|
94
|
-
instance_eval
|
|
99
|
+
instance_eval(<<-RUBY_EVAL, __FILE__, __LINE__ + 1)
|
|
95
100
|
def prefix_source() "#{value}" end
|
|
96
101
|
def resource_prefix(options={}) "#{resource_prefix_call}" end
|
|
97
102
|
RUBY_EVAL
|
|
@@ -122,7 +127,7 @@ module ShopifyAPI
|
|
|
122
127
|
def init_prefix_explicit(resource_type, resource_id)
|
|
123
128
|
self.resource_prefix = "#{resource_type}/:#{resource_id}/"
|
|
124
129
|
|
|
125
|
-
define_method
|
|
130
|
+
define_method(resource_id.to_sym) do
|
|
126
131
|
@prefix_options[resource_id]
|
|
127
132
|
end
|
|
128
133
|
end
|
|
@@ -155,7 +160,7 @@ module ShopifyAPI
|
|
|
155
160
|
private
|
|
156
161
|
|
|
157
162
|
def only_id
|
|
158
|
-
encode(:
|
|
163
|
+
encode(only: :id, include: [], methods: [])
|
|
159
164
|
end
|
|
160
165
|
end
|
|
161
166
|
end
|
|
@@ -1,9 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module ShopifyAPI
|
|
2
3
|
class Comment < Base
|
|
3
|
-
def remove
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def
|
|
4
|
+
def remove
|
|
5
|
+
load_attributes_from_response(post(:remove, {}, only_id))
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def spam
|
|
9
|
+
load_attributes_from_response(post(:spam, {}, only_id))
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def approve
|
|
13
|
+
load_attributes_from_response(post(:approve, {}, only_id))
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def restore
|
|
17
|
+
load_attributes_from_response(post(:restore, {}, only_id))
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def not_spam
|
|
21
|
+
load_attributes_from_response(post(:not_spam, {}, only_id))
|
|
22
|
+
end
|
|
8
23
|
end
|
|
9
24
|
end
|
|
@@ -1,18 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module ShopifyAPI
|
|
2
3
|
class CustomCollection < Base
|
|
3
4
|
include Events
|
|
4
5
|
include Metafields
|
|
5
6
|
|
|
6
7
|
def products
|
|
7
|
-
Product.find(:all, :
|
|
8
|
+
Product.find(:all, params: { collection_id: self.id })
|
|
8
9
|
end
|
|
9
10
|
|
|
10
11
|
def add_product(product)
|
|
11
|
-
Collect.create(:
|
|
12
|
+
Collect.create(collection_id: self.id, product_id: product.id)
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
def remove_product(product)
|
|
15
|
-
collect = Collect.find(:first, :
|
|
16
|
+
collect = Collect.find(:first, params: { collection_id: self.id, product_id: product.id })
|
|
16
17
|
collect.destroy if collect
|
|
17
18
|
end
|
|
18
19
|
end
|