Recently as part of the course work through Viking Code School we have been designing data models and their relationships. As practice we designed a basic model of all the entities, attributes, and relationships that you might have to set up for a site similar to Amazon. One question, or point of interest really, that came up was how to handle credit card data. While it was outside of the scope of the project we were informed that companies really don’t store customers’ credit card data. Instead they pass it along to a company that specializes in payment processing. That isn’t to say that these companies don’t provide any checks of their own. You may have entered your card on a website and gotten a notification that the card number you entered was invalid. How does the site know? Do they forward your input to a payment processing company who informs them?
At least for credit card numbers there is a simple check that companies can employ to make sure that entered card numbers are valid. They can do so by utilizing the Luhn Algorithm. The Luhn Algorithm checks a numbers validity by starting with the last digit, moving towards the first, doubling every even digit, and adding up the resulting product’s digits if the product is greater than 9, and then adding all even and odd digits and checking if the last digit of the total is a 0 (valid) or not (invalid). For instance, if you were given 2683, you would start with 4 (an odd digit), move to 8 (an even digit), double 8, resulting in 16, sum the digits, resulting in 7, and then repeat the process moving forward.
This process would look something like this:
- 3 stays 3 since it is an odd number
- 8 becomes 16 after being doubled because it is an even number
- 16 becomes 7 because you sum the digits if it is over 9
- 6 stays 6 since it is an odd number
- 2 becomes 4 after being doubled because it is an even number
- 6 stays 6 because it is less than 9 after doubling
- the resulting numbers are (4673)
- the sum of all these is 20
- 20 ends in 0 (is evenly divisible by 10)
- the number is valid
An elegant check that can apply to any credit card of any length (obviously companies have their own standards regarding card length and leading digits).
To implement the Luhn algorithm in Ruby we can do this by:
- reversing the original number
- use two separate sums (one for the even digits and one for the odds)
- slicing the number by an increment of 2 (a handy array method in Ruby)
- adding the odd digits to the first sum
- manipulating the even digits accordingly and then adding them to the second sum
- adding the two sums together
- and finally, checking whether the total is evenly divisible by 10
The code for this would look something like this:
def luhn(code) if code[/[0-9]+/] != code false else s1 = s2 = 0 code.to_s.reverse.chars.each_slice(2) do |odd, even| odd = odd.to_i even = even.to_i s1 += odd even * 2 >= 10 ? s2 += even * 2 - 9 : s2 += even * 2 end (s1 + s2) % 10 == 0 end end
Look at that each_slice method helping us out a ton!
There are many different ways to implement the Luhn algorithm. I preferred this method because it doesn’t utilize any additional memory, besides the two sums, and because it iterates through the number once.