From ef787b4f9e595255dd4bb58a38763061f2eb2cd0 Mon Sep 17 00:00:00 2001 From: "Junjie(Jack) Chen" Date: Wed, 12 Apr 2023 15:43:11 -0400 Subject: [PATCH] Improves Error Deserialization (#253) --- CHANGELOG.md | 1 + lib/easypost/error.rb | 16 +++++++++++++++- spec/error_spec.rb | 29 +++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3c17cd1..6397119e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Drops support for Ruby 2.5 - Bumps all dev dependencies +- Improves Error Deserialization to dynamically handle edge cases that have a bad format ## v4.13.0 (2023-04-04) diff --git a/lib/easypost/error.rb b/lib/easypost/error.rb index 03810fa9..1cd30b9b 100644 --- a/lib/easypost/error.rb +++ b/lib/easypost/error.rb @@ -7,7 +7,7 @@ class EasyPost::Error < StandardError # Initialize a new EasyPost Error def initialize(message = nil, status = nil, code = nil, errors = nil, http_body = nil) # message should be a string but can sometimes incorrectly come back as an array - @message = message.is_a?(Array) ? message.join(', ') : message + @message = message.is_a?(String) ? message : EasyPost::Error.traverse_json_element(message, []) @status = status @code = code @errors = errors @@ -16,6 +16,20 @@ def initialize(message = nil, status = nil, code = nil, errors = nil, http_body super(message) end + # Recursively traverses a JSON element to extract error messages and returns them as a comma-separated string. + def self.traverse_json_element(error_message, messages_list) + case error_message + when Hash + error_message.each_value { |value| traverse_json_element(value, messages_list) } + when Array + error_message.each { |value| traverse_json_element(value, messages_list) } + else + messages_list.push(error_message.to_s) + end + + messages_list.join(', ') + end + # Convert an error to a string. def to_s "#{code} (#{status}): #{message} #{errors}".strip diff --git a/spec/error_spec.rb b/spec/error_spec.rb index 6b571383..da34d505 100644 --- a/spec/error_spec.rb +++ b/spec/error_spec.rb @@ -33,5 +33,34 @@ expect(error.message).to eq('Error1, Error2') end + + it 'concatenates error.message when it comes back incorrectly as a hash from the API' do + error_message = { + errors: ['bad error', 'second bad error'], + } + + error = described_class.new(error_message) + + expect(error.message).to eq('bad error, second bad error') + end + + it 'concatenates error.message when it comes back incorrectly as an bad format from the API' do + error_message = { + message: { + errors: ['Bad format 1', 'Bad format 2'], + bad_data: [ + { + first_message: 'Bad format 3', + second_message: 'Bad format 4', + thrid_message: 'Bad format 5', + }, + ], + }, + } + + error = described_class.new(error_message) + + expect(error.message).to eq('Bad format 1, Bad format 2, Bad format 3, Bad format 4, Bad format 5') + end end end