Skip to content

Instantly share code, notes, and snippets.

@jasiek
Created June 23, 2015 15:15
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jasiek/731c4b69d92dd21dfe3c to your computer and use it in GitHub Desktop.
Save jasiek/731c4b69d92dd21dfe3c to your computer and use it in GitHub Desktop.
ISIN validation in Ruby
class IsinValidator < ActiveModel::Validator
CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
def validate(record)
value = record[:isin_cusip]
return if value.blank?
digits = value.upcase.chars.collect { |c| CHARS.index c }
digits = digits.join.chars.collect { |c| c.to_i }
actual_check_digit = digits.pop
odd, even, _ = digits.inject([[], [], true]) do |(odd, even, isodd), digit|
isodd ? [odd << digit, even, !isodd] : [odd, even << digit, !isodd]
end
big, small = (odd.size == even.size) ? [even, odd] : [odd, even]
big.collect! { |d| d * 2}
sum = (big + small).inject(0) do |sum, d|
sum + ((d > 9) ? (d % 10 + d / 10) : d)
end
expected_check_digit = (10 - (sum % 10)) % 10
if actual_check_digit != expected_check_digit
record.errors.add(:isin_cusip, "The ISIN number seems invalid, check digit is #{actual_check_digit} but should be #{expected_check_digit}")
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment