/* CODIFICANDO */

Relatos de um programador em contínua aprendizagem.

Brazilian Rails agora com suporte a CPF e CNPJ

com 4 comentários

Terminei há pouco tempo uma pequena aplicação financeira escrita em Rails e usei o Brazilian Rails para diversas funcionalidades. Uma das coisas que o Brazilian Rails não tinha e que acabei tendo que criar foi um suporte a CPF e CNPJ, com validações do formato das strings e do seu conteúdo numérico (utilizando módulo 11).

Achei que a solução ficou boa e tive a idéia de adicionar esta funcionalidade ao Brazilian Rails. Depois que o plugin foi adaptado para funcionar como um conjunto de gems ficou realmente simples integrar o que eu havia escrito. E assim surgiu a gem brcpfcnpj!

Com o brcpfcnpj, você pode criar campos que funcionem como um CPF ou um CNPJ de forma totalmente automática, de maneira semelhante ao que já é feito com a classe Dinheiro do Brazilian Rails.

As classes Cpf e Cnpj formatam e validam strings no formato xxx.xxx.xxx-xx (para os CPFs) e xx.xxx.xxx/xxxx-xx (para os CNPJs), onde x pode ser qualquer digito de 0 a 9. Os caracteres ‘.’, ‘/’ e ‘-’ são totalmente opcionais. Caso um atributo do seu model seja declarado para que funcione como Cpf ou Cnpj e você tente salvar um objeto deste model contendo uma string inválida para o cpf ou o cnpj, um novo erro será inserido em errors e o objeto passará a ser inválido.
Além disso, caso associe um valor não formatado a este atributo, seu conteúdo será automaticamente formatado.

A forma de usar é praticamente a mesma tanto para o CPF quanto para o CNPJ.

Como usar o Cpf:

Suponha que temos um model Pessoa, com um atributo ‘cpf’ que voce quer usar como um numero de documento para cpf. Basta usar o metodo usar_como_cpf, assim:

class Pessoa < ActiveRecord::Base
  usar_como_cpf :cpf
end

O atributo que sera usado como cpf pode ter qualquer nome e nao apenas ‘cpf’. Agora voce pode usar o atributo para cpf da seguinte forma:

p = Pessoa.new
p.cpf = "11144477735"
puts p.cpf # ==> 111.444.777-35
p.cpf.valido? # ==> true
p.cpf_valido? # ==> true

p = Pessoa.new(:cpf => "111.444.777-35")
puts p.cpf # ==> 111.444.777-35

p = Pessoa.new
p.cpf = Cpf.new("111444777-35")
puts p.cpf # ==> 111.444.777-35

p = Pessoa.new
p.cpf = "12345" # ==> um cpf invalido
puts p.valid? # ==> false
p.save # ==> false
p.errors.on(:cpf) # ==> 'numero invalido'

c = Cpf.new("11144477735")
p.cpf = "111.444.777-35"
c == p.cpf # ==> true

Como usar o Cnpj

Suponha que temos um model Empresa, com um atributo ‘cnpj’ que voce quer usar como um numero de documento para cnpj. Basta usar o metodo usar_como_cnpj, assim:

class Empresa < ActiveRecord::Base
  usar_como_cnpj :cnpj
end

O atributo que sera usado como cnpj pode ter qualquer nome e nao apenas ‘cnpj’. Agora voce pode usar o atributo para cnpj da seguinte forma:

e = Empresa.new
e.cnpj = "69103604000160"
puts e.cnpj # ==> 69.103.604/0001-60
e.cnpj.valido? # ==> true
e.cnpj_valido? # ==> true

e = Empresa.new(:cnpj => "69.103.604/0001-60")
puts e.cnpj # ==> 69.103.604/0001-60

e = Empresa.new
e.cnpj = Cnpj.new("691036040001-60")
puts e.cnpj # ==> 69.103.604/0001-60

e = Empresa.new
e.cnpj = "12343" # ==> um cnpj invalido
puts e.valid? # ==> false
e.save # ==> false
e.errors.on(:cnpj) # ==> 'numero invalido'

c = Cnpj.new("69103604000160")
e.cnpj = "69.103.604/0001-60"
c == e.cnpj # ==> true

As novas alterações já foram integradas ao projeto principal. Você pode instalar o projeto utilizando o GitHub. Mais informações em http://www.improveit.com.br/software_livre/brazilian_rails
Espero que seja útil!

Escrito por cassiomarques

Setembro 24, 2008 às 5:16 am

Publicado em rails, ruby

4 Respostas

Subscreva aos comentários comRSS.

  1. Olá Cássio.

    Bela iniciativa para adicionar a validação de CPF/CNPJ no brazilian-rails.
    Estivemos trabalhando aqui também numa validação para esses campos, já temos ela funcionando também em um projeto, contudo imagino que logo vamos atualizar para a nova versão do brazilian-rails e vamos utilizar o novo suporte do plugin.

    Com isso fica uma pergunta, é possível utilizar as duas validações em conjunto? Por exemplo, se eu tiver um model Pessoa, que precise analisar se é CPF ou CNPJ de acordo com o tipo (Física, Jurídica).

    Abraços.
    Carlos

    Carlos

    Setembro 24, 2008 em 3:51 pm

  2. Olá Carlos,

    Eu não testei nada nesse sentido, mas o que acontece é que quando você faz usar_como_cpf ou usar_como_cnpj, nada impede que seu objeto seja salvo com este atributo vazio. Assim, acho que você poderia por exemplo criar duas colunas na sua tabela, uma para cpf e outra para cnpj, com dois atributos independentes. Dessa forma, se for PF, você recebe, valida e grava o cpf; se for PJ, você recebe, valida e grava o cnpj.

    cassiomarques

    Setembro 24, 2008 em 4:00 pm

  3. Acho que seria possível trabalhar dessa maneira sim, sem problemas.

    Vou aproveitar e trabalhar em algo que permita validar os dois em uma mesma coluna, como já temos hoje funcionando aqui, imagino que seria interessante ter também essa funcionalidade.

    Carlos

    Setembro 24, 2008 em 4:05 pm

  4. Carlos,

    Pensando aqui, acho que poderia ser feito algo com before_validation… Considerando que você tenha alguma coluna que indique se é PF ou PJ e uma única coluna (por exemplo documento), o método associado ao before_validation poderia fazer o seguinte:

    - Verificar se é PF ou PJ
    - se for pj: usar_como_cnpj :documento
    - se for PF: usar_como_cpf :documento

    Acho que deve funcionar sem maiores problemas.

    cassiomarques

    Setembro 24, 2008 em 4:16 pm


Deixe uma resposta