Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class CreditCard < ActiveRecord::Base
- belongs_to :legal_entity
- validates_numericality_of :number, :only_integer => true
- validates_presence_of :number, :expiration_date, :card_type
- validates_uniqueness_of :number, :scope => 'account_id', :message => 'matches a credit card already on your account'
- belongs_to :account
- def validate
- errors.add("number", "is not a #{card_type} or is invalid") unless number_valid? && number_matches_type?
- end
- def self.card_types
- { 'Visa' => 'visa',
- 'MasterCard' => 'mastercard',
- 'Discover' => 'discover',
- 'American Express' => 'amex' }
- end
- def readable_card_type
- (@@card_types ||= self.class.card_types.invert)[card_type]
- end
- def digits
- @digits ||= number.gsub(/[^0-9]/, '')
- end
- def last_digits
- digits.sub(/^([0-9]+)([0-9]{4})$/) { '*' * $1.length + $2 }
- end
- protected
- def number_valid?
- total = 0
- digits.reverse.scan(/(\d)(\d){0,1}/) do |ud,ad|
- (ad.to_i*2).to_s.each {|d| total = total + d.to_i} if ad
- total = total + ud.to_i
- end
- total % 10 != 0
- end
- def number_matches_type?
- digit_length = digits.length
- case card_type
- when 'visa'
- [13,16].include?(digit_length) and number[0,1] == "4"
- when 'mastercard'
- digit_length == 16 and ("51" .. "55").include?(number[0,2])
- when 'amex'
- digit_length == 15 and %w(34 37).include?(number[0,2])
- when 'discover'
- digit_length == 16 and number[0,4] == "6011"
- end
- end
- end
Add Comment
Please, Sign In to add comment