From d69bdf15fa30759e660db27d07575c7359987d89 Mon Sep 17 00:00:00 2001 From: Paulo Margarido <64600052+paulomarg@users.noreply.github.com> Date: Thu, 7 Apr 2022 09:56:28 -0400 Subject: [PATCH] Handle loading attributes with special characters --- lib/shopify_api/rest/base.rb | 57 +++++++++++++++++++------ test/clients/base_rest_resource_test.rb | 14 +++++- 2 files changed, 58 insertions(+), 13 deletions(-) diff --git a/lib/shopify_api/rest/base.rb b/lib/shopify_api/rest/base.rb index e64a8c3d6..124a0f19c 100644 --- a/lib/shopify_api/rest/base.rb +++ b/lib/shopify_api/rest/base.rb @@ -16,6 +16,8 @@ class Base @paths = T.let([], T::Array[T::Hash[Symbol, T.any(T::Array[Symbol], String, Symbol)]]) @custom_prefix = T.let(nil, T.nilable(String)) + @aliased_properties = T.let({}, T::Hash[String, String]) + sig { returns(T::Hash[Symbol, T.untyped]) } attr_accessor :original_state @@ -32,6 +34,7 @@ def initialize(session: nil, from_hash: nil) @original_state = T.let({}, T::Hash[Symbol, T.untyped]) @custom_prefix = T.let(nil, T.nilable(String)) @forced_nils = T.let({}, T::Hash[String, T::Boolean]) + @aliased_properties = T.let({}, T::Hash[String, String]) session ||= ShopifyAPI::Context.active_session @@ -42,7 +45,7 @@ def initialize(session: nil, from_hash: nil) @errors = T.let(Rest::BaseErrors.new, Rest::BaseErrors) from_hash&.each do |key, value| - instance_variable_set("@#{key}", value) + set_property(key, value) end end @@ -235,13 +238,13 @@ def create_instance(data:, session:, instance: nil) def method_missing(meth_id, val = nil) match = meth_id.id2name.match(/([^=]+)(=)?/) - var = match[1] + var = T.must(T.must(match)[1]) - if match[2] - instance_variable_set("@#{var}", val) - @forced_nils[T.must(var)] = val.nil? + if T.must(match)[2] + set_property(var, val) + @forced_nils[var] = val.nil? else - instance_variable_get("@#{var}") + get_property(var) end end @@ -257,17 +260,30 @@ def respond_to_missing?(meth_id, *args) def to_hash hash = {} instance_variables.each do |var| - next if [:"@original_state", :"@session", :"@client", :"@forced_nils", :"@errors"].include?(var) + next if [ + :"@original_state", + :"@session", + :"@client", + :"@forced_nils", + :"@errors", + :"@aliased_properties", + ].include?(var) + + var = var.to_s.delete("@") + attribute = if @aliased_properties.value?(var) + T.must(@aliased_properties.key(var)) + else + var + end.to_sym - attribute = var.to_s.delete("@").to_sym if self.class.has_many?(attribute) - hash[attribute.to_s] = instance_variable_get(var).map(&:to_hash).to_a if instance_variable_get(var) + hash[attribute.to_s] = get_property(attribute).map(&:to_hash).to_a if get_property(attribute) elsif self.class.has_one?(attribute) - element_hash = instance_variable_get(var)&.to_hash + element_hash = get_property(attribute)&.to_hash hash[attribute.to_s] = element_hash if element_hash || @forced_nils[attribute.to_s] - elsif !instance_variable_get(var).nil? || @forced_nils[attribute.to_s] + elsif !get_property(attribute).nil? || @forced_nils[attribute.to_s] hash[attribute.to_s] = - instance_variable_get(var) + get_property(attribute) end end hash @@ -312,6 +328,23 @@ def save(update_object: false) @errors.errors << e raise end + + private + + sig { params(var: T.any(String, Symbol), val: T.untyped).void } + def set_property(var, val) + clean = var.to_s.gsub(/[\?\s]/, "") + @aliased_properties[var.to_s] = clean if clean != var + + instance_variable_set("@#{clean}", val) + end + + sig { params(var: T.any(String, Symbol)).returns(T.untyped) } + def get_property(var) + clean = @aliased_properties.key?(var.to_s) ? @aliased_properties[var.to_s] : var + + instance_variable_get("@#{clean}") + end end end end diff --git a/test/clients/base_rest_resource_test.rb b/test/clients/base_rest_resource_test.rb index d33a09927..3a9e14550 100644 --- a/test/clients/base_rest_resource_test.rb +++ b/test/clients/base_rest_resource_test.rb @@ -156,7 +156,7 @@ def test_deletes_existing_resource_and_fails_on_deleting_nonexistent_resource assert_requested(stubbed_request) end - def test_load_unknown_attribute + def test_loads_unknown_attribute body = { fake_resource: { id: 1, attribute: "attribute", unknown: "some-value" } }.to_json stub_request(:get, "#{@prefix}/fake_resources/1.json").to_return(body: body) @@ -164,6 +164,18 @@ def test_load_unknown_attribute resource = TestHelpers::FakeResource.find(id: 1, session: @session) assert_equal("some-value", resource.unknown) + assert_equal("some-value", resource.to_hash["unknown"]) + end + + def test_loads_unknown_attribute_with_special_character + body = { fake_resource: { id: 1, attribute: "attribute", "unknown?": "some-value" } }.to_json + + stub_request(:get, "#{@prefix}/fake_resources/1.json").to_return(body: body) + + resource = TestHelpers::FakeResource.find(id: 1, session: @session) + + assert_equal("some-value", resource.unknown?) + assert_equal("some-value", resource.to_hash["unknown?"]) end def test_save_with_unknown_attribute