Yet another Great Ruby Quiz ;)
Well I thought this was a Quiz particularly suited to write *nice*
code. I guess I somehow failed as it is too long, but I put some of
the features I like most of Ruby, well I guess it is a solution which
is consistent with my style ;)
And as I feel that this is not said frequently enough, I'll just say
it: "Thank you James for all these Quizzes, and thanks to the Quiz
creators too of course."

Cheers
Robert

#!/usr/bin/ruby
# vim: sts=2 sw=2 expandtab nu tw=0:

class String
  def to_rgx
    Regexp.new self
  end

  def ccc
    Checker.new{
      amex [34,37], 15
      discover 6011, 16
      master 50..55, 16
      visa 4, [13,16]
      jcb 3528..3589, 16
    }.check self
  end
end

class Checker
  UsageException = Class.new Exception
  def initialize &blk
    @cards = {}
    instance_eval &blk
  end

  def check str
    s = str.gsub(/\s/,"")
    @cards.each do
      |card, check_values|
      return [ luhn( s ), card.to_s.capitalize ] if
        check_values.first === s && check_values.last.include?( s.length )
    end
    [ nil, "Unknown" ]
  end

  def luhn s
    sum = 0
    s.split(//).reverse.each_with_index{
      | digit, idx |
      sum += (idx%2).succ * digit.to_i
    }
    (sum % 10).zero? ? " Valid" : "n Invalid"
  end
  # This is one of the rare examples where
  # the method_missing parametes are not
  # id, *args, &blk, trust me I know what
  # I am doing ;)
  def method_missing credit_card_name, regs, lens
      raise UsageException, "#{card_name} defined twice" if
        @cards[credit_card_name]
      ### Unifying Integer, Array and Range parameters
      lens = [lens] if Integer === lens
      lens = lens.to_a
      ### Genereating regular expressions
      regs = [regs] if Integer === regs
      regs = regs.map{ |r| "^#{r}" }.join("|").to_rgx
      @cards[credit_card_name] = [ regs, lens ]
  end
end

ARGV.each do
  | number |
  puts "Card with number #{number} is a%s %s card" %
    number.ccc

end # ARGV.each do