From fca16f181f528216a98edf8a4db8c572e2d82e7d Mon Sep 17 00:00:00 2001 From: Anthony Robertson Date: Thu, 18 May 2023 11:13:44 -0400 Subject: [PATCH] Ignore read-only attributes when updating through REST resources (#1157) * Add test for saving resources with read only attributes * Fixing save logic when the resource has read-only attributes * Adding changelog entry --- CHANGELOG.md | 2 ++ lib/shopify_api/rest/base.rb | 6 +++- test/clients/base_rest_resource_test.rb | 47 +++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e9a82f1e..6a6f5e89e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ Note: For changes to the API, see https://shopify.dev/changelog?filter=api ## Unreleased +- [#1157](https://github.com/Shopify/shopify-api-ruby/pull/1157) Fix an issue where read-only attributes are included when saving REST resources + ## 13.0.0 - [#1140](https://github.com/Shopify/shopify-api-ruby/pull/1140) ⚠️ [Breaking] Reformat Http error messages to be JSON parsable. diff --git a/lib/shopify_api/rest/base.rb b/lib/shopify_api/rest/base.rb index 833c9a60c..650439c7e 100644 --- a/lib/shopify_api/rest/base.rb +++ b/lib/shopify_api/rest/base.rb @@ -361,8 +361,12 @@ def save(update_object: false) sig { returns(T::Hash[String, String]) } def attributes_to_update + original_state_for_update = original_state.reject do |attribute, _| + self.class.read_only_attributes&.include?("@#{attribute}".to_sym) + end + HashDiff::Comparison.new( - deep_stringify_keys(original_state), + deep_stringify_keys(original_state_for_update), deep_stringify_keys(to_hash(true)), ).left_diff end diff --git a/test/clients/base_rest_resource_test.rb b/test/clients/base_rest_resource_test.rb index 92f3418b4..5094090de 100644 --- a/test/clients/base_rest_resource_test.rb +++ b/test/clients/base_rest_resource_test.rb @@ -397,6 +397,53 @@ def test_put_request_for_has_one_associaiton_works customer.save end + + def test_put_requests_for_resource_with_read_only_attributes + stub_request(:get, "https://test-shop.myshopify.com/admin/api/unstable/variants/169.json") + .to_return( + status: 200, + body: JSON.generate( + { + "variant" => { + "id" => 169, + "product_id" => 116, + "title" => "Default Title", + "price" => "2.50", + "sku" => "SKU123", + "position" => 1, + "inventory_policy" => "deny", + "compare_at_price" => nil, + "fulfillment_service" => "manual", + "inventory_management" => nil, + "option1" => "Default Title", + "option2" => nil, + "option3" => nil, + "created_at" => "2023-05-10T16:37:23-04:00", + "updated_at" => "2023-05-10T16:37:23-04:00", + "taxable" => true, + "barcode" => "0000", + "grams" => 45359236093, + "image_id" => nil, + "weight" => 99999998.0, + "weight_unit" => "lb", + "inventory_item_id" => 167, + "inventory_quantity" => 0, + "old_inventory_quantity" => 0, + "requires_shipping" => true, + "admin_graphql_api_id" => "gid://shopify/ProductVariant/169", + }, + }, + ), + ) + + variant = ShopifyAPI::Variant.find(id: 169, session: @session) + variant.client.expects(:put).with( + body: { "variant" => { "barcode" => "1234" } }, + path: "variants/169.json", + ) + variant.barcode = "1234" + variant.save + end end end end