Hashdiff does not see change if nested object is updated in place due to same reference value in resource object and original_state

Aperta
#1,331 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
45/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Ferma
Stack tecnologico
ruby
Ambito
api, backend

Direzione di ricerca

Inizia da lib/shopify_api/rest/base.rb alle righe 293-296, dove create_instance costruisce la risorsa e original_state. Esegui la riproduzione con bundle exec rspec, quindi verifica che la mutazione in-place di un valore annidato non modifichi original_state e venga rilevata al salvataggio.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

bug

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

  1. Install gems gem install shopify_api rspec
  2. Create ruby script with the content below
  3. 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

Lingua principale
Ruby
Stelle
1.1k
Fork
484
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di Shopify/shopify-api-ruby

Tutte le issue di Shopify/shopify-api-ruby

Issue simili

Altre issue su Ruby

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.