/lib/iban-tools/iban.rb

https://github.com/barsoom/iban-tools · Ruby · 80 lines · 58 code · 16 blank · 6 comment · 7 complexity · 71def8a6b9acbcebc37b9d6646a9bdd2 MD5 · raw file

  1. # vim:ts=2:sw=2:et:
  2. module IBANTools
  3. class IBAN
  4. def self.valid?( code, rules = nil )
  5. new(code).validation_errors(rules).empty?
  6. end
  7. def initialize( code )
  8. @code = IBAN.canonicalize_code(code)
  9. end
  10. def validation_errors( rules = nil )
  11. errors = []
  12. return [:too_short] if @code.size < 5
  13. return [:bad_chars] unless @code =~ /^[A-Z0-9]+$/
  14. errors += validation_errors_against_rules( rules || IBAN.default_rules )
  15. errors << :bad_check_digits unless valid_check_digits?
  16. errors
  17. end
  18. def validation_errors_against_rules( rules )
  19. errors = []
  20. return [:unknown_country_code] if rules[country_code].nil?
  21. errors << :bad_length if rules[country_code]["length"] != @code.size
  22. errors << :bad_format unless bban =~ rules[country_code]["bban_pattern"]
  23. errors
  24. end
  25. # The code in canonical form,
  26. # suitable for storing in a database
  27. # or sending over the wire
  28. def code
  29. @code
  30. end
  31. def country_code
  32. @code[0..1]
  33. end
  34. def check_digits
  35. @code[2..3]
  36. end
  37. def bban
  38. @code[4..-1]
  39. end
  40. def valid_check_digits?
  41. numerify.to_i % 97 == 1
  42. end
  43. def numerify
  44. if bad_match = @code.match(/[^A-Z0-9]/)
  45. raise RuntimeError.new("Unexpected byte '#{bad_match[0].bytes.first}' in IBAN code '#{prettify}'")
  46. end
  47. (@code[4..-1] + @code[0..3]).gsub(/[A-Z]/) { |let| (let.ord - 55).to_s }
  48. end
  49. def to_s
  50. "#<#{self.class}: #{prettify}>"
  51. end
  52. # The IBAN code in a human-readable format
  53. def prettify
  54. @code.gsub(/(.{4})/, '\1 ').strip
  55. end
  56. def self.canonicalize_code( code )
  57. code.strip.gsub(/\s+/, '').upcase
  58. end
  59. # Load and cache the default rules from rules.yml
  60. def self.default_rules
  61. @default_rules ||= IBANRules.defaults
  62. end
  63. end
  64. end