class CreditCardValidations::Detector

Attributes

number[R]

Public Class Methods

add_brand(key, rules, options = {}) click to toggle source

add brand

CreditCardValidations.add_brand(:en_route, {length: 15, prefixes: ['2014', '2149']}, {skip_luhn: true}) #skip luhn
# File lib/credit_card_validations/detector.rb, line 91
def add_brand(key, rules, options = {})

  brands[key] = {rules: [], options: options || {}}

  Array.wrap(rules).each do |rule|
    add_rule(key, rule[:length], rule[:prefixes])
  end

  define_brand_method(key)

end
add_rule(key, length, prefixes) click to toggle source

create rule for detecting brand

# File lib/credit_card_validations/detector.rb, line 126
def add_rule(key, length, prefixes)
  unless brands.has_key?(key)
    raise Error.new("brand #{key} is undefined, please use #add_brand method")
  end
  length, prefixes = Array(length), Array(prefixes)
  brands[key][:rules] << {length: length, regexp: compile_regexp(prefixes), prefixes: prefixes}
end
brand_key(brand_name) click to toggle source
# File lib/credit_card_validations/detector.rb, line 112
def brand_key(brand_name)
  brands.detect do |_, brand|
    brand[:options][:brand_name] == brand_name
  end.try(:first)
end
brand_name(brand_key) click to toggle source
# File lib/credit_card_validations/detector.rb, line 103
def brand_name(brand_key)
  brand = brands[brand_key]
  if brand
    brand.fetch(:options, {})[:brand_name] || brand_key.to_s.titleize
  else
    nil
  end
end
delete_brand(key) click to toggle source

CreditCardValidations.delete_brand(:en_route)

# File lib/credit_card_validations/detector.rb, line 119
def delete_brand(key)
  key = key.to_sym
  undef_brand_method(key)
  brands.reject! { |k, _| k == key }
end
has_luhn_check_rule?(key) click to toggle source
# File lib/credit_card_validations/detector.rb, line 82
def has_luhn_check_rule?(key)
  !brands[key].fetch(:options, {}).fetch(:skip_luhn, false)
end
new(number) click to toggle source
# File lib/credit_card_validations/detector.rb, line 14
def initialize(number)
  @number = number.to_s.tr('- ', '')
end

Protected Class Methods

compile_regexp(prefixes) click to toggle source

create regexp by array of prefixes

# File lib/credit_card_validations/detector.rb, line 148
def compile_regexp(prefixes)
  Regexp.new("^((#{prefixes.join(")|(")}))")
end
define_brand_method(key) click to toggle source

create methods like visa?, maestro? etc

# File lib/credit_card_validations/detector.rb, line 137
def define_brand_method(key)
  define_method "#{key}?".to_sym do
    valid?(key)
  end unless method_defined? "#{key}?".to_sym
end
undef_brand_method(key) click to toggle source
# File lib/credit_card_validations/detector.rb, line 143
def undef_brand_method(key)
  undef_method "#{key}?".to_sym if method_defined? "#{key}?".to_sym
end

Public Instance Methods

brand(*keys) click to toggle source

brand name

# File lib/credit_card_validations/detector.rb, line 24
def brand(*keys)
  valid_number?(*keys)
end
brand_name() click to toggle source
# File lib/credit_card_validations/detector.rb, line 49
def brand_name
  self.class.brand_name(brand)
end
valid?(*brands) click to toggle source

credit card number validation

# File lib/credit_card_validations/detector.rb, line 19
def valid?(*brands)
  !!valid_number?(*brands)
end
valid_luhn?() click to toggle source

check if luhn valid

# File lib/credit_card_validations/detector.rb, line 45
def valid_luhn?
  @valid_luhn ||= Luhn.valid?(number)
end
valid_number?(*keys) click to toggle source
# File lib/credit_card_validations/detector.rb, line 28
def valid_number?(*keys)
  selected_brands = keys.blank? ? self.brands : resolve_keys(*keys)
  if selected_brands.any?
    matched_brands = []
    selected_brands.each do |key, brand|
      match_data = matches_brand?(brand)
      matched_brands << {brand: key, matched_prefix_length: match_data.to_s.length} if match_data
    end

    if matched_brands.present?
      return matched_brands.sort{|a, b| a[:matched_prefix_length] <=> b[:matched_prefix_length]}.last[:brand]
    end
  end
  nil
end

Protected Instance Methods

matches_brand?(brand) click to toggle source
# File lib/credit_card_validations/detector.rb, line 66
def matches_brand?(brand)
  rules = brand.fetch(:rules)
  options = brand.fetch(:options, {})

  rules.each do |rule|
    if (options[:skip_luhn] || valid_luhn?) &&
        rule[:length].include?(number.length) &&
        match_data = number.match(rule[:regexp])
      return match_data
    end
  end
  false
end
resolve_keys(*keys) click to toggle source
# File lib/credit_card_validations/detector.rb, line 55
def resolve_keys(*keys)
  brand_keys = keys.map do |el|
    if el.is_a? String
      #try to find key by name
      el = (self.class.brand_key(el) || el).to_sym
    end
    el.downcase
  end
  self.brands.slice(*brand_keys)
end