Skip to content

Instantly share code, notes, and snippets.

@polimorfico
Created May 28, 2012 21:24
Show Gist options
  • Save polimorfico/2821274 to your computer and use it in GitHub Desktop.
Save polimorfico/2821274 to your computer and use it in GitHub Desktop.
Spanish Tax ID Validator
class SpanishTaxIdValidator < ActiveModel::EachValidator
def validate_each(object, attribute, value)
valid_tax_id = case
when value.match(/^[0-9]{8}[a-z]/i)
validate_nif(value.dup)
when value.match(/[a-w][0-9]{7}[0-9a-z]/i)
validate_cif(value.dup)
when value.match(/[xyz][0-9]{7,8}[a-z]/i)
validate_nie(value.dup)
else
false
end
object.errors[attribute] << (options[:message] || "is not valid") if not valid_tax_id
end
private
def validate_nif(value)
letters = "TRWAGMYFPDXBNJZSQVHLCKE"
check = value.slice!(value.length - 1..value.length - 1).upcase
calculated_letter = letters[value.to_i % 23].chr
return check === calculated_letter
end
def validate_cif(value)
letter = value.slice!(0).chr.upcase
check = value.slice!(value.length - 1).chr.upcase
n1 = n2 = 0
for idx in 0..value.length - 1
number = value.slice!(0).chr.to_i
if (idx % 2) != 0
n1 += number
else
n2 += ((2*number) % 10) + ((2 * number) / 10)
end
end
calculated_number = 10 - ((n1 + n2) % 10)
calculated_number = 0 if calculated_number==10
calculated_letter = (64 + calculated_number).chr
if letter.match(/[KNPQS]/)
return check.to_s == calculated_letter.to_s
else
return check.to_i == calculated_number.to_i
end
end
def validate_nie(value)
if value[0].chr.upcase == 'X'
value[0] = '0'
else
value[0] = '1'
end
value.slice(0) if value.size > 9
validate_nif(value)
end
end
@loveybot
Copy link

Yay Ruby!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment