Module: Smartcar::Utils
- Included in:
- Smartcar, AuthClient, Base
- Defined in:
- lib/smartcar/utils.rb
Overview
Utils module , provides utility methods to underlying classes
Instance Method Summary collapse
- #build_aliases(response, aliases) ⇒ Object
- #build_error(status, body_string, headers) ⇒ Object
- #build_meta(headers) ⇒ Object
- #build_response(body, headers) ⇒ Object
- #build_v3_response(body, headers) ⇒ Object
-
#convert_path_to_attribute(path) ⇒ Object
takes a path and converts it to the keys we use.
-
#convert_to_ostruct_recursively(obj) ⇒ Object
Helper method to recursively convert hashes and arrays to RecursiveOpenStruct.
-
#deep_transform_keys_to_snake_case(obj) ⇒ Object
Helper method to recursively convert hash keys to snake_case.
- #determine_mode(test_mode, mode) ⇒ Object
-
#get_config(config_name, options = {}) ⇒ String
gets a given env variable, checks for existence and throws exception if not present.
-
#handle_error(response) ⇒ Object
Given the response from smartcar API, throws an error if needed.
-
#initialize(options = {}) ⇒ Subclass os Base
A constructor to take a hash and assign it to the instance variables.
-
#json_to_ostruct(hash) ⇒ RecursiveOpenStruct
Converts a hash to RecursiveOpenStruct (a powered up OpenStruct object).
-
#parse_date_safely(date_string) ⇒ Object
Parse date string to DateTime or return nil on error.
- #process_batch_response(response_body, response_headers) ⇒ Object
-
#stringify_params(query_params) ⇒ Object
takes query parameters and returns them as a string EX - 'DE', 'flags': true -> "county:DE flags:true".
-
#to_snake_case(str) ⇒ Object
Helper method to convert string from camelCase or kebab-case to snake_case.
Instance Method Details
#build_aliases(response, aliases) ⇒ Object
139 140 141 142 143 144 145 146 147 |
# File 'lib/smartcar/utils.rb', line 139 def build_aliases(response, aliases) (aliases || []).each do |original_name, alias_name| # rubocop:disable Lint/SymbolConversion response.send("#{alias_name}=".to_sym, response.send(original_name.to_sym)) # rubocop:enable Lint/SymbolConversion end response end |
#build_error(status, body_string, headers) ⇒ Object
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/smartcar/utils.rb', line 149 def build_error(status, body_string, headers) content_type = headers['content-type'] || '' return SmartcarError.new(status, body_string, headers) unless content_type.include?('application/json') begin parsed_body = JSON.parse(body_string, { symbolize_names: true }) rescue StandardError => e return SmartcarError.new( status, { message: e., type: 'SDK_ERROR' }, headers ) end return SmartcarError.new(status, parsed_body, headers) if parsed_body[:error] || parsed_body[:type] SmartcarError.new(status, parsed_body.merge({ type: 'SDK_ERROR' }), headers) end |
#build_meta(headers) ⇒ Object
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/smartcar/utils.rb', line 98 def (headers) = { 'sc-data-age' => :data_age, 'sc-unit-system' => :unit_system, 'sc-request-id' => :request_id, 'sc-fetched-at' => :fetched_at }.each_with_object({}) do |(header_name, key), | [key] = headers[header_name] if headers[header_name] end = json_to_ostruct() .data_age = parse_date_safely(.data_age) .fetched_at = parse_date_safely(.fetched_at) end |
#build_response(body, headers) ⇒ Object
114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/smartcar/utils.rb', line 114 def build_response(body, headers) # Check if body is already parsed (i.e., a Hash) or if it needs parsing (i.e., a String) body_data = body.is_a?(String) ? JSON.parse(body) : body if body_data.is_a?(Array) response = OpenStruct.new(items: json_to_ostruct(body), meta: (headers)) else response = json_to_ostruct(body) response. = (headers) end response end |
#build_v3_response(body, headers) ⇒ Object
126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/smartcar/utils.rb', line 126 def build_v3_response(body, headers) body_data = body.is_a?(String) ? JSON.parse(body) : body headers_data = headers.is_a?(String) ? JSON.parse(headers) : headers body_snake = deep_transform_keys_to_snake_case(body_data) headers_snake = deep_transform_keys_to_snake_case(headers_data) OpenStruct.new( body: json_to_ostruct(body_snake), headers: json_to_ostruct(headers_snake) ) end |
#convert_path_to_attribute(path) ⇒ Object
takes a path and converts it to the keys we use. EX - '/charge' -> :charge, '/battery/capacity' -> :battery_capacity
203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/smartcar/utils.rb', line 203 def convert_path_to_attribute(path) return :attributes if path == '/' # Adding this because else it would become tires_pressure return :tire_pressure if path == '/tires/pressure' return :lock_status if path == '/security' return :diagnostic_system_status if path == '/diagnostics/system_status' return :diagnostic_trouble_codes if path == '/diagnostics/dtcs' path.split('/').reject(&:empty?).join('_').to_sym end |
#convert_to_ostruct_recursively(obj) ⇒ Object
Helper method to recursively convert hashes and arrays to RecursiveOpenStruct
48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/smartcar/utils.rb', line 48 def convert_to_ostruct_recursively(obj) case obj when Array obj.map { |el| convert_to_ostruct_recursively(el) } when Hash RecursiveOpenStruct.new( obj.transform_values { |value| convert_to_ostruct_recursively(value) }, recurse_over_arrays: true ) else obj end end |
#deep_transform_keys_to_snake_case(obj) ⇒ Object
Helper method to recursively convert hash keys to snake_case
73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/smartcar/utils.rb', line 73 def deep_transform_keys_to_snake_case(obj) case obj when Array obj.map { |el| deep_transform_keys_to_snake_case(el) } when Hash obj.each_with_object({}) do |(key, value), result| new_key = to_snake_case(key) result[new_key] = deep_transform_keys_to_snake_case(value) end else obj end end |
#determine_mode(test_mode, mode) ⇒ Object
223 224 225 226 227 228 229 230 231 232 233 234 235 |
# File 'lib/smartcar/utils.rb', line 223 def determine_mode(test_mode, mode) unless mode.nil? unless %w[test live simulated].include? mode raise 'The "mode" parameter MUST be one of the following: \'test\', \'live\', \'simulated\'' end return mode end return if test_mode.nil? warn '[DEPRECATION] The "test_mode" parameter is deprecated, please use the "mode" parameter instead.' test_mode.is_a?(TrueClass) ? 'test' : 'live' end |
#get_config(config_name, options = {}) ⇒ String
gets a given env variable, checks for existence and throws exception if not present
21 22 23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/smartcar/utils.rb', line 21 def get_config(config_name, = {}) # ENV.MODE is set to test by e2e tests. config_name = "E2E_#{config_name}" if ENV['MODE'] == 'test' unless ENV[config_name] nullable = .fetch(:nullable, false) return nil if nullable raise Smartcar::ConfigNotFound, "Environment variable #{config_name} not found !" end ENV.fetch(config_name, nil) end |
#handle_error(response) ⇒ Object
Given the response from smartcar API, throws an error if needed
173 174 175 176 177 178 |
# File 'lib/smartcar/utils.rb', line 173 def handle_error(response) status = response.status return nil if [200, 204].include?(status) raise build_error(response.status, response.body, response.headers) end |
#initialize(options = {}) ⇒ Subclass os Base
A constructor to take a hash and assign it to the instance variables
10 11 12 13 14 |
# File 'lib/smartcar/utils.rb', line 10 def initialize( = {}) .each do |attribute, value| instance_variable_set("@#{attribute}", value) end end |
#json_to_ostruct(hash) ⇒ RecursiveOpenStruct
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
43 44 45 |
# File 'lib/smartcar/utils.rb', line 43 def json_to_ostruct(hash) convert_to_ostruct_recursively(hash) end |
#parse_date_safely(date_string) ⇒ Object
Parse date string to DateTime or return nil on error
88 89 90 91 92 93 94 95 96 |
# File 'lib/smartcar/utils.rb', line 88 def parse_date_safely(date_string) return nil unless date_string begin DateTime.parse(date_string) rescue ArgumentError nil end end |
#process_batch_response(response_body, response_headers) ⇒ Object
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/smartcar/utils.rb', line 180 def process_batch_response(response_body, response_headers) response_object = OpenStruct.new response_body['responses'].each do |item| attribute_name = convert_path_to_attribute(item['path']) aliases = (Vehicle::METHODS[attribute_name.to_sym] || {})[:aliases] # merging the top level request headers and separate headers for each item of batch headers = response_headers.merge(item['headers'] || {}) response = if [200, 204].include?(item['code']) build_aliases(build_response(item['body'], headers), aliases) else build_error(item['code'], item['body'].to_json, headers) end response_object.define_singleton_method attribute_name do raise response if response.is_a?(SmartcarError) response end end response_object end |
#stringify_params(query_params) ⇒ Object
takes query parameters and returns them as a string EX - 'DE', 'flags': true -> "county:DE flags:true"
219 220 221 |
# File 'lib/smartcar/utils.rb', line 219 def stringify_params(query_params) query_params&.map { |key, value| "#{key}:#{value}" }&.join(' ') end |
#to_snake_case(str) ⇒ Object
Helper method to convert string from camelCase or kebab-case to snake_case
64 65 66 67 68 69 70 |
# File 'lib/smartcar/utils.rb', line 64 def to_snake_case(str) str.to_s .gsub('-', '_') # Convert kebab-case to snake_case .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2') .gsub(/([a-z\d])([A-Z])/, '\1_\2') .downcase end |