From c61e8018c984d4a9ecc5350e897694c5cb11ecc9 Mon Sep 17 00:00:00 2001 From: Ashwin Kumar Subramanian Date: Wed, 14 Jul 2021 15:43:00 -0700 Subject: [PATCH] fix: handle json parser dependencies (#38) --- Gemfile.lock | 4 +++- lib/open_struct_extensions.rb | 21 --------------------- lib/smartcar.rb | 1 + lib/smartcar/auth_client.rb | 4 ++-- lib/smartcar/utils.rb | 16 ++++++++++++++-- lib/smartcar/version.rb | 2 +- ruby-sdk.gemspec | 1 + spec/smartcar/e2e/vehicle_spec.rb | 8 ++++---- spec/smartcar/integration/vehicle_spec.rb | 4 ++-- 9 files changed, 28 insertions(+), 33 deletions(-) delete mode 100644 lib/open_struct_extensions.rb diff --git a/Gemfile.lock b/Gemfile.lock index 90093f6..1effa6c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,8 +1,9 @@ PATH remote: . specs: - smartcar (3.0.0) + smartcar (3.0.1) oauth2 (~> 1.4) + recursive-open-struct (~> 1.1.3) GEM remote: https://rubygems.org/ @@ -53,6 +54,7 @@ GEM readapt (1.3.0) backport (~> 1.1) thor (~> 1.0) + recursive-open-struct (1.1.3) redcarpet (3.5.1) regexp_parser (2.1.1) rexml (3.2.5) diff --git a/lib/open_struct_extensions.rb b/lib/open_struct_extensions.rb deleted file mode 100644 index 7f05b52..0000000 --- a/lib/open_struct_extensions.rb +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true - -# Extension to OpenStruct to convert a nested OpenStruct object to a hash. -# Using this method any of the API response can be converted back to hash -# or JSON (from hash) for convenience. -# Example Usage : -# response = {a: { b: {c: "test", d: [{x: 1}, {y: 3}]}}} -class OpenStruct - def deep_to_h - to_h.transform_values do |value| - case value - when is_a?(OpenStruct) - value.deep_to_h - when is_a?(Array) - value.map { |item| item.is_a?(OpenStruct) ? item.deep_to_h : item } - else - value - end - end - end -end diff --git a/lib/smartcar.rb b/lib/smartcar.rb index ed63b45..0840fa6 100644 --- a/lib/smartcar.rb +++ b/lib/smartcar.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +require 'recursive_open_struct' require 'smartcar_error' require 'smartcar/utils' require 'smartcar/version' diff --git a/lib/smartcar/auth_client.rb b/lib/smartcar/auth_client.rb index e764fd3..c98a0e4 100644 --- a/lib/smartcar/auth_client.rb +++ b/lib/smartcar/auth_client.rb @@ -72,7 +72,7 @@ def exchange_code(code, options = {}) .get_token(code, redirect_uri: redirect_uri) .to_hash - JSON.parse(token_hash.to_json, object_class: OpenStruct) + json_to_ostruct(token_hash) rescue OAuth2::Error => e raise build_error(e.response.status, e.response.body, e.response.headers) end @@ -89,7 +89,7 @@ def exchange_refresh_token(token, options = {}) token_object = OAuth2::AccessToken.from_hash(client, { refresh_token: token }) token_object = token_object.refresh! - JSON.parse(token_object.to_hash.to_json, object_class: OpenStruct) + json_to_ostruct(token_object.to_hash) rescue OAuth2::Error => e raise build_error(e.response.status, e.response.body, e.response.headers) end diff --git a/lib/smartcar/utils.rb b/lib/smartcar/utils.rb index 2401ab9..e131e54 100644 --- a/lib/smartcar/utils.rb +++ b/lib/smartcar/utils.rb @@ -25,6 +25,18 @@ def get_config(config_name) ENV[config_name] end + # Converts a hash to RecursiveOpenStruct (a powered up OpenStruct object). + # NOTE - Do not replace with the more elegant looking + # JSON.parse(meta_hash.to_json, object_class: OpenStruct) + # this is because we had an app using OJ as their json parser which led to an issue using the + # above mentioned method. Source : https://github.com/ohler55/oj/issues/239 + # @param hash [Hash] json object as hash + # + # @return [RecursiveOpenStruct] + def json_to_ostruct(hash) + RecursiveOpenStruct.new(hash) + end + def build_meta(headers) meta_hash = { 'sc-data-age' => :data_age, @@ -33,14 +45,14 @@ def build_meta(headers) }.each_with_object({}) do |(header_name, key), meta| meta[key] = headers[header_name] if headers[header_name] end - meta = JSON.parse(meta_hash.to_json, object_class: OpenStruct) + meta = json_to_ostruct(meta_hash) meta.data_age &&= DateTime.parse(meta.data_age) meta end def build_response(body, headers) - response = JSON.parse(body.to_json, object_class: OpenStruct) + response = json_to_ostruct(body) response.meta = build_meta(headers) response end diff --git a/lib/smartcar/version.rb b/lib/smartcar/version.rb index f47869a..5c6eb4c 100644 --- a/lib/smartcar/version.rb +++ b/lib/smartcar/version.rb @@ -2,5 +2,5 @@ module Smartcar # Gem current version number - VERSION = '3.0.0' + VERSION = '3.0.1' end diff --git a/ruby-sdk.gemspec b/ruby-sdk.gemspec index 9fb232b..8f449e7 100644 --- a/ruby-sdk.gemspec +++ b/ruby-sdk.gemspec @@ -36,4 +36,5 @@ Gem::Specification.new do |spec| spec.add_development_dependency 'selenium-webdriver', '~> 3.142' spec.add_development_dependency 'webmock', '~> 3.13' spec.add_dependency 'oauth2', '~> 1.4' + spec.add_dependency 'recursive-open-struct', '~> 1.1.3' end diff --git a/spec/smartcar/e2e/vehicle_spec.rb b/spec/smartcar/e2e/vehicle_spec.rb index 9e66e16..3c246e1 100644 --- a/spec/smartcar/e2e/vehicle_spec.rb +++ b/spec/smartcar/e2e/vehicle_spec.rb @@ -125,17 +125,17 @@ it 'should return hash of objects with attribute requested as keys' do attributes = ['/charge', '/battery', '/odometer'] result = @vehicle.batch(attributes) - expect(result.instance_of?(OpenStruct)).to eq(true) - expect(result.charge.instance_of?(OpenStruct)).to eq(true) + expect(result.is_a?(OpenStruct)).to eq(true) + expect(result.charge.is_a?(OpenStruct)).to eq(true) expect(result.charge.is_plugged_in?).not_to be_nil expect(result.charge.state).not_to be_nil expect(result.charge.meta).not_to be_nil expect(result.charge.meta.request_id.length).to eq(36) - expect(result.battery.instance_of?(OpenStruct)).to eq(true) + expect(result.battery.is_a?(OpenStruct)).to eq(true) expect(result.battery.percentage_remaining).not_to be_nil expect(result.battery.range).not_to be_nil expect(result.battery.meta).not_to be_nil - expect(result.odometer.instance_of?(OpenStruct)).to eq(true) + expect(result.odometer.is_a?(OpenStruct)).to eq(true) expect(result.odometer.meta).not_to be_nil expect(result.odometer.distance).not_to be_nil end diff --git a/spec/smartcar/integration/vehicle_spec.rb b/spec/smartcar/integration/vehicle_spec.rb index bf1750c..bba0916 100644 --- a/spec/smartcar/integration/vehicle_spec.rb +++ b/spec/smartcar/integration/vehicle_spec.rb @@ -101,8 +101,8 @@ ) expected_description = 'The vehicle was unable to perform your request because it is currently unreachable.' result = subject.batch(attributes) - expect(result.instance_of?(OpenStruct)).to eq(true) - expect(result.odometer.instance_of?(OpenStruct)).to eq(true) + expect(result.is_a?(OpenStruct)).to eq(true) + expect(result.odometer.is_a?(OpenStruct)).to eq(true) expect { result.location }.to(raise_error do |error| expect(error.status_code).to eq(409) expect(error.type).to eq('VEHICLE_STATE')