From: Jeffrey Moss Date: 2005-03-24T08:41:48+09:00 Subject: Re: Credit Card Verification as an exercise free your mind neo right, there is no spoon yeah ----- Original Message ----- From: "Florian Gross" Newsgroups: comp.lang.ruby To: "ruby-talk ML" Sent: Wednesday, March 23, 2005 4:34 PM Subject: Re: Credit Card Verification as an exercise > Jeffrey Moss wrote: > >> Couldn't find any credit card verification code written in ruby so I >> wrote up my own. This code turns out a lot smaller than the perl >> version I have been using. I thought it was an interesting exercise, >> here is how its done, if anybody can improve on what I've done I'd be >> impressed. %* > > Nice code and I guess it will be quite useful as well! Thanks for > posting this here. > >> class CreditCard < ActiveRecord::Base >> >> def before_save >> if number_is_valid && number_matches_type >> ... >> end >> end >> >> def number_is_valid > > Guess, I'd rename this to 'number_valid?'. :) > >> total = 0 >> number.gsub(/[^0-9]/, '').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 ? false : true > > Hm, why not simply "total % 10 != 0"? > >> end >> >> def number_matches_type > > Might be nice to append a question mark here as well. > >> digit_length = number.length >> if card_type == 'visa' >> if (digit_length == 16) || (digit_length == 13) >> return true if number[/^\d/].to_i == 4 >> end >> elsif card_type == 'mastercard' >> if digit_length == 16 >> return true if (51..55).to_a.include?(number[0..1].to_i) > > Hmmm, why the .to_a call? > >> end >> elsif card_type == 'amex' >> if digit_length == 15 >> return true if [34,37].include?(number[0..1].to_i) >> end >> elsif card_type == 'discover' >> if digit_length == 16 >> return true if number[0..3].to_i == 6011 >> end >> end >> end >> end > > I think all this returns are superfluous -- after all Ruby will return > the result of evaluating the matching if clause. > > Oh, and I think this is a good case for the case construct: > > case card_type > when 'visa' then > [13, 16].include?(digit_length) and number[0, 1] == "4" > when 'mastercard' then > digit_length == 16 and ("51" .. "55").include?(number[0, 2]) > when 'amex' then > digit_length == 15 and %w(34 37).include?(number[0, 2]) > when 'discover' then > digit_length == 16 and number[0, 4] == "6011" > end >