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

Instance Method Details

#build_aliases(response, aliases) ⇒ Object



60
61
62
63
64
65
66
67
68
# File 'lib/smartcar/utils.rb', line 60

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



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/smartcar/utils.rb', line 70

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) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
# 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) ⇒ Object



54
55
56
57
58
# 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) ⇒ Object

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



124
125
126
127
128
129
130
131
132
133
# File 'lib/smartcar/utils.rb', line 124

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'

  path.split('/').reject(&:empty?).join('_').to_sym
end

#determine_mode(test_mode, mode) ⇒ Object



141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/smartcar/utils.rb', line 141

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) ⇒ String

gets a given env variable, checks for existence and throws exception if not present

Parameters:

  • config_name (String)

    key of the env variable

Returns:

  • (String)

    value of the env variable

Raises:



20
21
22
23
24
25
26
# 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.fetch(config_name, nil)
end

#handle_error(response) ⇒ Object

Given the response from smartcar API, throws an error if needed

Parameters:

  • response (Object)

    response Object with status and body



94
95
96
97
98
99
# File 'lib/smartcar/utils.rb', line 94

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

Parameters:

  • options (defaults to: {})

    = {} [Hash] Could by any class's hash, but the first level keys should be defined in the class

Returns:

  • (Subclass os Base)

    Returns object of any subclass like Report



10
11
12
13
14
# File 'lib/smartcar/utils.rb', line 10

def initialize(options = {})
  options.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

Parameters:

  • hash (Hash)

    json object as hash

Returns:

  • (RecursiveOpenStruct)


36
37
38
# 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) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/smartcar/utils.rb', line 101

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"



137
138
139
# File 'lib/smartcar/utils.rb', line 137

def stringify_params(query_params)
  query_params&.map { |key, value| "#{key}:#{value}" }&.join(' ')
end