module Smartcar::Utils

Utils module , provides utility methods to underlying classes

Public Class Methods

new(options = {}) click to toggle source

A constructor to take a hash and assign it to the instance variables @param options = {} [Hash] Could by any class's hash, but the first level keys should be defined in the class

@return [Subclass os Base] Returns object of any subclass like Report

# File lib/smartcar/utils.rb, line 10
def initialize(options = {})
  options.each do |attribute, value|
    instance_variable_set("@#{attribute}", value)
  end
end

Public Instance Methods

build_aliases(response, aliases) click to toggle source
# File lib/smartcar/utils.rb, line 60
def build_aliases(response, aliases)
  (aliases || []).each do |original_name, alias_name|
    response.send("#{alias_name}=".to_sym, response.send(original_name.to_sym))
  end

  response
end
build_error(status, body_string, headers) click to toggle source
# File lib/smartcar/utils.rb, line 68
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.message,
        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) click to toggle source
# File lib/smartcar/utils.rb, line 40
def build_meta(headers)
  meta_hash = {
    'sc-data-age' => :data_age,
    'sc-unit-system' => :unit_system,
    'sc-request-id' => :request_id
  }.each_with_object({}) do |(header_name, key), meta|
    meta[key] = headers[header_name] if headers[header_name]
  end
  meta = json_to_ostruct(meta_hash)
  meta.data_age &&= DateTime.parse(meta.data_age)

  meta
end
build_response(body, headers) click to toggle source
# File lib/smartcar/utils.rb, line 54
def build_response(body, headers)
  response = json_to_ostruct(body)
  response.meta = build_meta(headers)
  response
end
convert_path_to_attribute(path) click to toggle source

takes a path and converts it to the keys we use. EX - '/charge' -> :charge, '/battery/capacity' -> :battery_capacity

# File lib/smartcar/utils.rb, line 122
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'

  path.split('/').reject(&:empty?).join('_').to_sym
end
get_config(config_name) click to toggle source

gets a given env variable, checks for existence and throws exception if not present @param config_name [String] key of the env variable

@return [String] value of the env variable

# File lib/smartcar/utils.rb, line 20
def get_config(config_name)
  # ENV.MODE is set to test by e2e tests.
  config_name = "E2E_#{config_name}" if ENV['MODE'] == 'test'
  raise Smartcar::ConfigNotFound, "Environment variable #{config_name} not found !" unless ENV[config_name]

  ENV[config_name]
end
handle_error(response) click to toggle source

Given the response from smartcar API, throws an error if needed @param response [Object] response Object with status and body

# File lib/smartcar/utils.rb, line 92
def handle_error(response)
  status = response.status
  return nil if [200, 204].include?(status)

  raise build_error(response.status, response.body, response.headers)
end
json_to_ostruct(hash) click to toggle source

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 : github.com/ohler55/oj/issues/239 @param hash [Hash] json object as hash

@return [RecursiveOpenStruct]

# File lib/smartcar/utils.rb, line 36
def json_to_ostruct(hash)
  RecursiveOpenStruct.new(hash, recurse_over_arrays: true)
end
process_batch_response(response_body, response_headers) click to toggle source
# File lib/smartcar/utils.rb, line 99
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