Pular para o conteúdo
ValidadorCNPJ Gerar CNPJ

Ruby · código pronto

Validar CNPJ alfanumérico em Ruby

Validador de CNPJ alfanumérico em Ruby, com validator pronto para Rails.

Testar um CNPJ agora Gerar massa de teste

Módulo Ruby sem gems, mais o ActiveModel::EachValidator para plugar direto nos seus models do Rails.

O algoritmo é sempre o mesmo: cada caractere vale o seu código ASCII menos 48 (0=0 … 9=9, A=17 … Z=42), os pesos vão de 2 a 9 da direita para a esquerda, soma-se tudo, divide-se por 11 e o dígito é 0 quando o resto é menor que 2, ou 11 menos o resto. Ver a conta detalhada.

Código completo

validação de CNPJ alfanumérico em Ruby
# frozen_string_literal: true

module Cnpj
  FORMATO = /\A[0-9A-Z]{12}\d{2}\z/
  NAO_ALFANUMERICO = /[^0-9A-Z]/

  module_function

  # Remove máscara e normaliza para maiúsculas.
  def limpar(valor)
    valor.to_s.upcase.gsub(NAO_ALFANUMERICO, '')
  end

  # Calcula um dígito do módulo 11 (valor do caractere = ASCII - 48).
  def digito(sequencia)
    soma = sequencia.each_char.with_index.sum do |caractere, indice|
      peso = ((sequencia.length - 1 - indice) % 8) + 2
      (caractere.ord - 48) * peso
    end

    resto = soma % 11
    resto < 2 ? 0 : 11 - resto
  end

  # Devolve os dois dígitos verificadores da base de 12 caracteres.
  def calcular_dv(base)
    primeiro = digito(base)
    segundo = digito("#{base}#{primeiro}")
    "#{primeiro}#{segundo}"
  end

  # Valida CNPJ numérico ou alfanumérico, com ou sem máscara.
  def valido?(valor)
    cnpj = limpar(valor)
    return false unless cnpj.match?(FORMATO)
    return false if cnpj.chars.uniq.size == 1

    calcular_dv(cnpj[0, 12]) == cnpj[12, 2]
  end

  # Aplica a máscara 00.000.000/0000-00.
  def formatar(valor)
    cnpj = limpar(valor)
    return cnpj unless cnpj.length == 14

    format('%s.%s.%s/%s-%s', cnpj[0, 2], cnpj[2, 3], cnpj[5, 3], cnpj[8, 4], cnpj[12, 2])
  end
end

Testes e integração com o framework

Rails + RSpec
# app/validators/cnpj_validator.rb
class CnpjValidator < ActiveModel::EachValidator
  def validate_each(registro, atributo, valor)
    return if valor.blank?

    registro.errors.add(atributo, :invalid, message: 'não é um CNPJ válido') unless Cnpj.valido?(valor)
  end
end

# app/models/empresa.rb
class Empresa < ApplicationRecord
  validates :cnpj, presence: true, cnpj: true, uniqueness: true

  before_validation { self.cnpj = Cnpj.limpar(cnpj) }
end

# spec/lib/cnpj_spec.rb
RSpec.describe Cnpj do
  it 'calcula o DV do exemplo oficial' do
    expect(described_class.calcular_dv('12ABC34501DE')).to eq('35')
  end

  it 'aceita alfanumérico e numérico' do
    expect(described_class).to be_valido('12.ABC.345/01DE-35')
    expect(described_class).to be_valido('11.222.333/0001-81')
    expect(described_class).not_to be_valido('11.222.333/0001-82')
  end
end

Detalhes que costumam quebrar em Ruby

Casos de teste recomendados

Cubra pelo menos estes cenários — eles pegam praticamente todos os erros de implementação:

EntradaEsperadoO que testa
12.ABC.345/01DE-35válidoexemplo oficial, com máscara
12abc34501de35válidonormalização para maiúsculas
11.222.333/0001-81válidocompatibilidade com o formato numérico
11.222.333/0001-82inválidodígito verificador errado
12ABC34501DEABinválidoletra no dígito verificador
12ABC34501DE3inválidotamanho incorreto
00.000.000/0000-00inválidosequência repetida
"" / nullinválidoentrada vazia sem exceção

Precisa de mais massa de teste? O gerador produz até 500 CNPJs alfanuméricos válidos de uma vez, com opção de baixar em .txt.

O mesmo algoritmo em outras linguagens

Dúvidas sobre CNPJ alfanumérico em Ruby

Preciso de alguma biblioteca para validar CNPJ alfanumérico em Ruby?

Não. O código desta página usa apenas a biblioteca padrão de Ruby — são cerca de 30 linhas. Bibliotecas de terceiros só valem a pena se você também precisa de formatação, geração e validação de outros documentos; e, nesse caso, confira se a versão instalada já suporta o formato alfanumérico.

A mesma função valida CNPJ numérico e alfanumérico em Ruby?

Sim. Como o valor de cada dígito é o próprio dígito (código ASCII menos 48), o algoritmo alfanumérico produz o mesmo resultado do antigo para números. Você não precisa manter duas funções nem ramificar por formato.

Como testar se a implementação está certa?

Use o exemplo oficial da Receita Federal: a base 12ABC34501DE tem dígitos verificadores 35, formando 12.ABC.345/01DE-35. Confira também um CNPJ numérico conhecido, como 11.222.333/0001-81, e um inválido, como 11.222.333/0001-82.

O que mais precisa mudar além da função de validação?

O tipo da coluna no banco (de numérico para VARCHAR(14)), qualquer conversão para inteiro no caminho do dado, as máscaras de entrada e as regex espalhadas por validações e relatórios. A função de validação costuma ser a parte mais fácil da migração.