module ShopifyAPI::Utils::AttributesComparator

Public Class Methods

build_update_value(diff, path: [], reference_values: {}, atomic_hash_attributes: []) click to toggle source
# File lib/shopify_api/utils/attributes_comparator.rb, line 42
def build_update_value(diff, path: [], reference_values: {}, atomic_hash_attributes: [])
  new_hash = {}

  diff.each do |key, value|
    current_path = path + [key.to_s]

    if value.is_a?(Hash)
      has_numbered_key = value.keys.any? { |k| k.is_a?(Integer) }
      ref_value = T.unsafe(reference_values).dig(*current_path)

      if has_numbered_key && ref_value.is_a?(Array)
        new_hash[key] = ref_value
      else
        new_value = build_update_value(
          value,
          path: current_path,
          reference_values: reference_values,
          atomic_hash_attributes: atomic_hash_attributes,
        )

        atomic_update = atomic_hash_attributes.include?(key.to_sym)

        # If the key is in atomic_hash_attributes, we use the entire reference value
        # so we update the hash as a whole.
        if !new_value.empty? && !ref_value.empty? && atomic_update
          new_hash[key] = ref_value

        # Only add to new_hash if the user intentionally updates
        # to empty value like `{}` or `[]`. For example:
        #
        # original = { "a" => { "foo" => 1 } }
        # updated = { "a" => {} }
        # diff = { "a" => { "foo" => HashDiff::NO_VALUE } }
        # key = "a", new_value = {}, ref_value = {}
        # new_hash = { "a" => {} }
        #
        # In addition, we omit cases where after removing `HashDiff::NO_VALUE`
        # we only have `{}` left. For example:
        #
        # original = { "a" => { "foo" => 1, "bar" => 2} }
        # updated = { "a" => { "foo" => 1 } }
        # diff = { "a" => { "bar" => HashDiff::NO_VALUE } }
        # key = "a", new_value = {}, ref_value = { "foo" => 1 }
        # new_hash = {}
        #
        # new_hash is empty because nothing changes
        elsif !new_value.empty? || ref_value.empty?
          new_hash[key] = new_value
        end
      end
    elsif value != HashDiff::NO_VALUE
      new_hash[key] = value
    end
  end

  new_hash
end
compare(original_attributes, updated_attributes, atomic_hash_attributes: []) click to toggle source
# File lib/shopify_api/utils/attributes_comparator.rb, line 19
def compare(original_attributes, updated_attributes, atomic_hash_attributes: [])
  attributes_diff = HashDiff::Comparison.new(
    original_attributes,
    updated_attributes,
  ).left_diff

  update_value = build_update_value(
    attributes_diff,
    reference_values: updated_attributes,
    atomic_hash_attributes: atomic_hash_attributes,
  )

  update_value
end