module GTIN

Constants

CONVERTER_MAP
Converter
GtinConverter
GtinValidationError
IsbnConverter
IssnConverter
UpcEConverter
VERSION

Public Instance Methods

compute_checksum_gtin(unchecked) click to toggle source
# File lib/gtin/gtin.rb, line 104
def compute_checksum_gtin(unchecked)
  reversed_digits = unchecked.reverse.chars.map(&:to_i)
  sum = reversed_digits.each_with_index.sum { |digit, idx| digit * (idx.odd? ? 1 : 3) }
  ((10 - sum) % 10).to_s
end
compute_checksum_isbn10(unchecked_isbn) click to toggle source
# File lib/gtin/gtin.rb, line 110
def compute_checksum_isbn10(unchecked_isbn)
  digits = unchecked_isbn.chars.map(&:to_i)
  sum = digits.each_with_index.sum { |digit, idx| digit * (idx + 1) }
  (sum % 11).to_s
end
compute_checksum_issn8(unchecked_issn) click to toggle source
# File lib/gtin/gtin.rb, line 116
def compute_checksum_issn8(unchecked_issn)
  reversed_digits = unchecked_issn.reverse.chars.map(&:to_i)
  sum = reversed_digits.each_with_index.sum { |digit, idx| digit * (idx + 2) }
  ((11 - sum) % 11).to_s
end
compute_checksum_upce(unchecked_upce) click to toggle source

can't be done directly; convert to upc-a first

# File lib/gtin/gtin.rb, line 123
def compute_checksum_upce(unchecked_upce)
  standardize('UPC', unchecked_upce + '0', validate_checksum: false)[-1]
end
fail_on_invalid_checksum(id_type, identifier) click to toggle source
# File lib/gtin/gtin.rb, line 91
def fail_on_invalid_checksum(id_type, identifier)
  converter = get_converter(id_type, identifier.length)
  if converter.nil?
    raise GtinValidationError.new("Invalid checksum: gtin converter not found for #{id_type} with length #{value.length}")
  end

  expected_checksum = send(converter.checksum_computer, identifier[0..-2])
  actual_checksum = identifier[-1]
  return if actual_checksum == expected_checksum

  raise GtinValidationError.new("#{id_type} #{identifier} has invalid checksum #{actual_checksum} -- expected #{expected_checksum}")
end
get_converter(id_type, value_length) click to toggle source
# File lib/gtin/gtin.rb, line 44
def get_converter(id_type, value_length)
  CONVERTER_MAP.each do |(type_matcher, length), converter|
    return converter if type_matcher.match?(id_type) && value_length == length
  end

  # rubocop warns about this, but it's needed because #each returns its owner
  return nil
end
gtin_compatible?(id_type) click to toggle source
# File lib/gtin/gtin.rb, line 127
def gtin_compatible?(id_type)
  CONVERTER_MAP.keys.map(&:first).any? { |r| r.match?(id_type) }
end
standardize(id_type, value, validate_checksum: true) click to toggle source
# File lib/gtin/gtin.rb, line 33
def standardize(id_type, value, validate_checksum: true)
  converter = get_converter(id_type, value.length)
  if converter.nil?
    raise GtinValidationError.new("#{id_type} standardization failed: no gtin converter for value with length #{value.length}")
  end

  fail_on_invalid_checksum(id_type, value) if validate_checksum

  send(converter.standardizer, value)
end
standardize_gtin(gtin) click to toggle source
# File lib/gtin/gtin.rb, line 53
def standardize_gtin(gtin)
  gtin
end
standardize_isbn10(isbn) click to toggle source
# File lib/gtin/gtin.rb, line 75
def standardize_isbn10(isbn)
  with_checksum('978' + isbn[0..-2])
end
standardize_issn8(issn) click to toggle source
# File lib/gtin/gtin.rb, line 71
def standardize_issn8(issn)
  with_checksum('977' + issn[0..-2] + '00')
end
standardize_upce(upce) click to toggle source
# File lib/gtin/gtin.rb, line 57
def standardize_upce(upce)
  # http://www.taltech.com/barcodesoftware/symbologies/upc
  case upce[5]
  when '0', '1', '2'
    with_checksum('0' + upce.slice(0, 2) + upce[5] + '0000' + upce.slice(2, 3))
  when '3'
    with_checksum('0' + upce.slice(0, 3) + '00000' + upce.slice(3, 2))
  when '4'
    with_checksum('0' + upce.slice(0, 4) + '00000' + upce[4])
  else
    with_checksum('0' + upce.slice(0, 5) + '0000' + upce[5])
  end
end
to_gtin(id_type, value) click to toggle source

raises GtinValidationError if the provided value has an invalid checksum

# File lib/gtin/gtin.rb, line 25
def to_gtin(id_type, value)
  zero_pad(standardize(id_type, value))
end
valid_checksum?(id_type, identifier) click to toggle source
# File lib/gtin/gtin.rb, line 83
def valid_checksum?(id_type, identifier)
  converter = get_converter(id_type, identifier.length)
  return false if converter.nil?

  expected_checksum = send(converter.checksum_computer, identifier[0..-2])
  identifier[-1] == expected_checksum
end
with_checksum(unchecked) click to toggle source
# File lib/gtin/gtin.rb, line 79
def with_checksum(unchecked)
  unchecked + compute_checksum_gtin(unchecked)
end
zero_pad(gtin) click to toggle source
# File lib/gtin/gtin.rb, line 29
def zero_pad(gtin)
  gtin.rjust(14, '0')
end