ruby-on-railsrubyvalidationiban

Ruby on Rails IBAN validation in model file


I'm trying to do iban validation as any country iban code. I got some of help from stackoverflow for build that code but still I have some problem and I don't know where is it.

Always I get 'That is not a valid IBAN' error message. But sometimes I tried correct iban code as defined countries.

Is there anybody help me in that code for doing this validation, please?

The code is here:

  class BankAccount < ActiveRecord::Base
  belongs_to :user

  validates :bank_name, presence: true
  validate :iban, :valid_iban?, presence: true

  private

    def valid_iban?
            ibans = iban.upcase.scan(/\w/).join

            ibans = ibans.gsub(/_/, '')

            iban_length = ibans.length

            country = ibans.scan(/\A../).join

            length_correct_for_country = true

            case country
                when "IE"
                    if iban_length == 22
                        length_correct_for_country = true
                    else
                        length_correct_for_country = false      
                    end
                when "AL"
                    if iban_length == 28
                        length_correct_for_country = true
                    else
                        length_correct_for_country = false      
                    end
                when "TR"
                    if iban_length == 26
                        length_correct_for_country = true
                    else
                        length_correct_for_country = false      
                    end
                when "GB"
                    if iban_length == 22
                        length_correct_for_country = true
                    else
                        length_correct_for_country = false      
                    end
                when "VG"
                    if iban_length == 24
                        length_correct_for_country = true
                    else
                        length_correct_for_country = false      
                    end
            end

            first_four_characters = ibans.slice!(0..3)

            reordered_number = ibans + first_four_characters

            letters_removed = []
            reordered_number.scan(/./) do |character|
                case character
                when "A"
                    letters_removed << 10
                when "9"
                    letters_removed <<9
                end
            end

            letters_removed = letters_removed.join.to_i

            remainder = letters_removed % 97

            if remainder == 1 && length_correct_for_country

            else
                remainder = remainder.to_s
                errors.add(:iban, " That is not a valid IBAN. The IBAN that is being supplied")
            end

    end

end

Solution

  • The iban-tools gem is available for this purpose and it works very well.

    To use the gem in Rails I recommend to write a validator class.

    First put this in your Gemfile:

    gem 'iban-tools'
    

    and run bundle.

    Then create a new directory app/validators and inside that a file called iban_validator.rb with these contents:

    require 'iban-tools'
    
    class IbanValidator < ActiveModel::Validator
      def validate(record)
        unless IBANTools::IBAN.valid?(record.iban)
          record.errors.add :iban, record.errors.generate_message(:iban, :invalid)
        end
      end
    end
    

    In your model class put this:

    validates_with IbanValidator