Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
# frozen_string_literal: true
class TaxidValidator < ActiveModel::EachValidator
VALID_FORMATS = {
nif: /^(\d{8})([A-Z])$/,
nie: /^[XYZ]\d{7,8}[A-Z]$/,
}.freeze
CONTROL_DIGIT_TABLE = %w[T R W A G M Y F P D X B N J Z S Q V H L C K E].freeze
CONTROL_DIGIT_NIE_MAPPING = {
X: 0, Y: 1, Z: 2,
}.freeze
def validate_each(record, attribute, value)
provided_taxid = value.dup
record.errors.add(attribute, :invalid_taxid_format) unless valid_format(provided_taxid)
record.errors.add(attribute, :invalid_taxid_control_digit) unless valid_control_digit(provided_taxid)
end
private def valid_format(taxid)
VALID_FORMATS[:nif] =~ taxid || VALID_FORMATS[:nie] =~ taxid
end
private def valid_control_digit(taxid)
provided_control_digit = taxid.slice!(-1)
if VALID_FORMATS[:nie] =~ taxid
replacement = CONTROL_DIGIT_NIE_MAPPING[taxid[0].to_sym]
taxid = "#{replacement}#{taxid[1..-1]}"
end
provided_control_digit == CONTROL_DIGIT_TABLE[taxid.to_i % 23]
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment