class NhtsaVin::Query

Constants

NHTSA_URL

Attributes

data[R]
error[R]
error_code[R]
raw_response[R]
response[R]
url[R]
vin[R]

Public Class Methods

new(vin, options={}) click to toggle source
# File lib/nhtsa_vin/query.rb, line 11
def initialize(vin, options={})
  @vin = vin.strip.upcase
  @http_options = options[:http] || {}
  build_url
end

Public Instance Methods

get() click to toggle source
# File lib/nhtsa_vin/query.rb, line 17
def get
  @raw_response = fetch
  begin
    return if @raw_response.nil? || (json_response = JSON.parse(@raw_response)).nil?
    parse(json_response)
  rescue JSON::ParserError
    @valid = false
    @error = 'Response is not valid JSON'
  rescue StandardError => ex
    raise "#{ex.message}: #{@raw_response.inspect}"
  end
end
parse(json) click to toggle source
# File lib/nhtsa_vin/query.rb, line 34
def parse(json)
  if json['Message']&.match(/execution error/i)
    @valid = false
    @error = json.dig('Results', 0, 'Message')
    return
  end
  @data = json['Results']

  # 0 - Good
  # 1 - VIN decoded clean. Check Digit (9th position) does not calculate properly.
  # 3 - VIN corrected, error in one position (assuming Check Digit is correct).
  # 5 - VIN has errors in few positions.
  # 6 - Incomplete VIN.
  # 8 - No detailed data available currently.
  # 11- Incorrect Model Year, decoded data may not be accurate!
  @error_code = value_id_for('Error Code')&.to_i
  @valid = (@error_code < 4) ? true : false

  if @error_code != 0
    @error = value_for('Error Code')
  end
  return nil unless valid?

  make = value_for('Make').capitalize
  model = value_for('Model')
  trim = value_for('Trim')
  year = value_for('Model Year')
  style = value_for('Body Class')
  type = vehicle_type(style, value_for('Vehicle Type'))
  doors = value_for('Doors')&.to_i

  @response = Struct::NhtsaResponse.new(@vin, make, model, trim, type, year,
                                        style, value_for('Vehicle Type'), doors)
end
valid?() click to toggle source
# File lib/nhtsa_vin/query.rb, line 30
def valid?
  @valid
end
vehicle_type(body_class, type) click to toggle source
# File lib/nhtsa_vin/query.rb, line 69
def vehicle_type(body_class, type)
  return case type
  when 'PASSENGER CAR'
    'Car'
  when 'TRUCK'
    if body_class =~ /van/i
      'Van'
    else
      'Truck'
    end
  when 'MULTIPURPOSE PASSENGER VEHICLE (MPV)'
    if body_class =~ /Sport Utility/i
      'SUV'
    else
      'Minivan'
    end
  end
end

Private Instance Methods

build_url() click to toggle source
# File lib/nhtsa_vin/query.rb, line 102
def build_url
  @url = "#{NHTSA_URL}#{@vin}?format=json"
end
fetch() click to toggle source
# File lib/nhtsa_vin/query.rb, line 106
def fetch
  begin
    @valid = false

    url = URI.parse(@url)
    http_options = { use_ssl: (url.scheme == 'https') }
    http_options.update(@http_options)
    Net::HTTP.start(url.host, url.port, http_options) do |http|
      resp = http.request_get(url)
      case resp
      when Net::HTTPSuccess
        @valid = true
        resp.body
      when Net::HTTPRedirection
        raise 'No support for HTTP redirection from NHTSA API'
      when Net::HTTPClientError
        @error = "Client error: #{resp.code} #{resp.message}"
        nil
      else
        @error = resp.message
        nil
      end
    end
  rescue Timeout::Error, Errno::EINVAL, Errno::ECONNRESET, EOFError, SocketError,
         Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError,
         Net::ProtocolError, Errno::ECONNREFUSED => e
    @error = e.message
    nil
  end
end
get_row(attr_name) click to toggle source
# File lib/nhtsa_vin/query.rb, line 90
def get_row(attr_name)
  @data.select { |r| r['Variable'] == attr_name }.first
end
value_for(attr_name) click to toggle source
# File lib/nhtsa_vin/query.rb, line 94
def value_for(attr_name)
  get_row(attr_name)['Value']
end
value_id_for(attr_name) click to toggle source
# File lib/nhtsa_vin/query.rb, line 98
def value_id_for(attr_name)
  get_row(attr_name)['ValueId']
end