class NhtsaVin::Validation

Constants

TRANSLITERATIONS
WEIGHTS

Attributes

check[R]
error[R]
plant[R]
seq[R]
valid[R]
vds[R]
vin[R]
wmi[R]

Public Class Methods

new(vin) click to toggle source

Validates a VIN that it fits both the definition, and that the checksum is valid.

# File lib/nhtsa_vin/validation.rb, line 18
def initialize(vin)
  @valid = false
  if vin.nil?
    @error = 'Blank VIN provided'
    return
  end
  @vin = vin.strip.upcase
  if !regex
    @error = 'Invalid VIN format'
    return
  elsif checksum != @check
    @error = "VIN checksum digit #{@check} failed "\
             "to calculate (expected #{checksum})"
    return
  else
    @valid = true
  end
end

Public Instance Methods

valid?() click to toggle source
# File lib/nhtsa_vin/validation.rb, line 37
def valid?
  @valid
end

Private Instance Methods

checksum() click to toggle source
# File lib/nhtsa_vin/validation.rb, line 64
def checksum
  m = @vin.chars.each_with_index.map do |char, i|
    if char !~ /\D/
      char.to_i * WEIGHTS[i]
    else
      TRANSLITERATIONS[char.upcase.to_sym] * WEIGHTS[i]
    end
  end
  checksum = m.inject(0, :+) % 11
  checksum == 10 ? 'X' : checksum.to_s
end
regex() click to toggle source
# File lib/nhtsa_vin/validation.rb, line 43
def regex
  match_data = %r{
    ^(?<wmi>[A-HJ-NPR-Z\d]{3})
     (?<vds>[A-HJ-NPR-Z\d]{5})
     (?<check>[\dX])
     (?<vis>(?<year>[A-HJ-NPR-Z\d])
     (?<plant>[A-HJ-NPR-Z\d])
     (?<seq>[A-HJ-NPR-Z\d]{6}))$
  }ix.match(@vin)

  if match_data
    @wmi = match_data[:wmi]
    @vds = match_data[:vds]
    @check = match_data[:check]
    @vis = match_data[:vis]
    @plant = match_data[:plant]
    @seq = match_data[:seq]
  end
  match_data
end