Hashdiff does not see change if nested object is updated in place due to same reference value in resource object and original_state
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 45/100
Research direction
Start at lib/shopify_api/rest/base.rb lines 293-296, where create_instance builds the resource and original_state. Run the reproduction with bundle exec rspec, then verify that mutating a nested value in place does not alter original_state and is detected on save.
Written by the indexing model from the issue text.
Description
Issue summary
HashDiff does not see change if nested resource object is updated in place. When resource object is created with #create_instance method, it adds value to both resource and to the original_state. If you update the object in place, the change will be reflected in original_state aswell which is wrong.
Expected behavior
All values in original_state should be duplicates, not references.
Steps to reproduce the problem
- Install gems gem install shopify_api rspec
- Create ruby script with the content below
- Execute script with rspec bundle exec rspec ${script_file_name}
it "should reproduce issue with reference value in original_state" do
resource_hash = {
name: "#111",
line_items: [
{ title: "One", price: 100, quantity: 1 },
],
shipping_address: {
first_name: "John",
last_name: "Doe",
address_1: "Freedom street",
},
}.values_as_hash
draft_order = ShopifyAPI::DraftOrder.new(from_hash: resource_hash)
draft_order.save!
expect(draft_order.shipping_address["first_name"]).to eq("John")
# This changes original_state which is wrong
draft_order.shipping_address["first_name"] = "Tom"
draft_order.save!
expect(draft_order.shipping_address["first_name"]).to eq("Tom")
# It is only possible to update it by setting whole object like this
updated_address = draft_order.shipping_address.values_as_hash
updated_address[:first_name] = "Tom"
draft_order.shipping_address = updated_address
draft_order.save!
expect(draft_order.shipping_address["first_name"]).to eq("Tom")
end
This is our current workaround to fix this issue.
module ShopifyAPI
module Rest
module BaseExtension
def create_instance(data:, session:, instance: nil)
result = super
result.original_state = result.original_state.deep_dup
result
end
end
end
end
ShopifyAPI::Rest::Base.singleton_class.prepend(ShopifyAPI::Rest::BaseExtension)
This is where the actual issue is happening:
https://github.com/Shopify/shopify-api-ruby/blob/6a74e1e2a1ec454d700e3b53d91cae00c236fada/lib/shopify_api/rest/base.rb#L293-L296
- Dominant language
- Ruby
- Stars
- 1.1k
- Forks
- 484
- PR merge metrics
- No merged PRs in 30d
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from Shopify/shopify-api-ruby
-
devtools-gardener
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Shopify/shopify-api-ruby#1456 · 3 reactions ·
-
devtools-gardener
Difficulty 3/5 1-2 days Newbie friendliness 67/100
Shopify/shopify-api-ruby#1461 ·
-
automated
Difficulty 4/5 3-5 days Newbie friendliness 48/100
Shopify/shopify-api-ruby#1460 ·
-
devtools-gardener
Difficulty 5/5 Over a week Newbie friendliness 35/100
Shopify/shopify-api-ruby#1455 ·
-
devtools-gardener
Difficulty 4/5 3-5 days Newbie friendliness 48/100
Shopify/shopify-api-ruby#1453 ·
All issues in Shopify/shopify-api-ruby
Similar issues
-
user-reported
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Kong/developer.konghq.com#7316 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
TheOdinProject/curriculum#31408 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
notch8/utk_knapsack#148 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 78/100
Homebrew/homebrew-cask#288729 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100