# Posted By

mabafu on 10/27/11

# Statistics

Viewed 1039 times
Favorited by 0 user(s)

# CPF and CNPJ validation classes using the Brazilian Government official algorithms

/ Published in: Ruby  CPF and CNPJ are self-validated codes generated by Brazilian government. Being the CPF used to identify persons and CNJP to enterprises, organizations and so on.

That said, I use to code the CPF/CNPJ algorithm when learning new programming languages. With Ruby, it got very clean and powerful because it's particular way to deal with "closures" (i.e. the ruby blocks, Procs and lambdas).

To use Cpf or Cnpj classes, just instantite the respective classes passing the numbers to be validated. CPF has 11 digits and CNPJ has 14. In both cases the last two digits are calculated based on the previous ones.

Module11 is the parent class of Cpf and Cnpj. You can use this class if you want to implement your own Module 11 validation algorithm. In this case, inherit from Module11 and initialize the new class with the proper parameters (i.e. input, formula, size, number_of_digits)

Copy this code and paste it in your HTML
`# Generic Module 11 validator class Module11protected   #returns the next validation 'digit' of the 'input'.    #It will calcultes the next 'digit' based on the    #given 'formula' (as block)      def Module11.getDigit (input, formula)      digit = 0      input.each_with_index do |item, index|         #passing the current item, its index and the whole array          #to the formula         digit += formula.call(item, index, input)          end         digit = 11 - (digit % 11)      digit = 0 if digit > 9       return digit   end          #calculates the new 'input' digits based on the given 'formula'    #and the 'size' of the desired 'output' array   def Module11.calculate (input, formula, size)            output = Array.new (input)      while output.size < size do         output << getDigit(output, formula)      end      return output   end public   attr_reader :value    def initialize(input, formula, size, number_of_digits)            if input.kind_of? String         @value = input.scan(/\d/).collect{ |item| item.to_i }             else         @value =       end       if formula.kind_of? Proc         @formula = formula      else         @formula = nil      end             if size.kind_of? Fixnum         @size = size      else         @size = 0      end       if number_of_digits.kind_of? Fixnum         @number_of_digits = number_of_digits      else         @number_of_digits = 0      end       if (@size > 0) and (@value.size > 0) and (@number_of_digits > 0) and (not @formula.nil?)         @result = Module11.calculate(@value[0,@size-@number_of_digits], @formula, @size)      else         @result = []      end   end    def inspect      "< @value = " + @value.to_s + ">"   end    def to_s      @value.join("")   end    def is_valid?      @value == @result   end    def validated      if is_valid?               self      else                 Module11.new @result.join, @formula, @size, @number_of_digits      end      end    def is_obvious?         @result.join("").to_i % ("1"*@size).to_i == 0   end    def digits      if @value.size == @size         @value[@size-@number_of_digits, @number_of_digits]      else         []      end   end end class Cpf < Module11private   def Cpf.formula      Proc.new do |item, index, updatedInput|         item * (updatedInput.size + 1 - index)      end   end public   def initialize(input)                  super input, Cpf.formula, 11, 2     end    def validated      if is_valid?               self      else                 Cpf.new @result.join      end      endend class Cnpj < Module11private   def Cnpj.formula      Proc.new do |item, index, updatedInput|         coefs = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]         item * coefs[index+13-updatedInput.size]      end   end public   def initialize(input)      super input, Cnpj.formula, 14, 2    end    def validated      if is_valid?               self      else                 Cnpj.new @result.join      end      endend` Subscribe to comments