/ Published in: Ruby
#About#
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)
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)
Expand |
Embed | Plain Text
Copy this code and paste it in your HTML
# Generic Module 11 validator class Module11 protected #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 = [0] 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 < Module11 private 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 end end class Cnpj < Module11 private 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 end end