unpack brazilian-rails

This commit is contained in:
2013-07-14 11:09:25 -04:00
parent 7d287fe530
commit e563725dc5
131 changed files with 5496 additions and 0 deletions

View File

View File

@@ -0,0 +1,20 @@
Copyright (c) 2008 [name of plugin creator]
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,49 @@
# Como usar a classe CNPJ no seu ActiveRecord
Objetos da classe CNPJ recebem strings representando números de CNPJ e verificam a validade destes números usando dois critérios:
1. O formato da string, que deve seguir o padrão xx.xxx.xxx/xxxx-xx, onde 'x' pode ser qualquer dígito de 0 a 9 e os traços (-), barra (/) e pontos (.) *são opcionais*.
2. O conteúdo numérico desta string, que é validado através do cálculo do 'módulo 11' dos dígitos que compõem a string.
Caso o conteúdo da string obedeça ao formato especificado acima, o mesmo será formatado para obedecer ao padrão xx.xxx.xxx/xxxx-xx
É importante observar que caso você associe um valor de CNPJ inválido ao seu model, o mesmo passará automaticamente a ser inválido, o que impede que valores de CNPJ incorretos sejam salvos no banco de dados.
Suponha que temos um model Empresa, com um atributo 'cnpj' que você quer usar como um número de documento para CNPJ. Basta usar o método `usar_como_cnpj`, assim:
```ruby
class Empresa < ActiveRecord::Base
usar_como_cnpj :cnpj
end
```
## Agora você pode usar o atributo para CNPJ da seguinte forma:
```ruby
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) # ==> 'não é válido' # de acordo com a I18n
c = Cnpj.new("69103604000160")
e.cnpj = "69.103.604/0001-60"
c == e.cnpj # ==> true
```
# Como usar a classe CPF no seu ActiveRecord
Objetos da classe CPF seguem especificações semelhantes as da classe CNPJ, possuindo apenas alterações na validação para acomodar o formato dos números de CPF e têm seus métodos alterados de `usar_como_cnpj` para `usar_como_cpf`, por exemplo.

View File

@@ -0,0 +1,75 @@
# encoding: UTF-8
require "rubygems"
require "rake"
require "rdoc/task"
require "rake/packagetask"
require "rake/gempackagetask"
require File.join(File.dirname(__FILE__), "lib", "brcpfcnpj", "version")
PKG_BUILD = ENV["PKG_BUILD"] ? "." + ENV["PKG_BUILD"] : ""
PKG_NAME = "brcpfcnpj"
PKG_VERSION = BrCpfCnpj::VERSION::STRING + PKG_BUILD
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
begin
require "rspec/core/rake_task"
RSpec::Core::RakeTask.new
desc "Default Task"
task :default => [ :spec ]
task :test do
system("rake spec")
end
rescue LoadError
puts "To execute tests for brcnpjcpf gem, you want to install rspec gem before"
end
#Generate the RDoc documentation
Rake::RDocTask.new { |rdoc|
rdoc.rdoc_dir = "doc"
rdoc.title = "Brazilian Rails -- CPF/CNPJ"
rdoc.options << "--line-numbers" << "--inline-source" << "-A cattr_accessor=object"
rdoc.options << "--charset" << "utf-8"
rdoc.template = "#{ENV["template"]}.rb" if ENV["template"]
rdoc.rdoc_files.include("README.mkdn", "CHANGELOG")
rdoc.rdoc_files.include("lib/**/*")
}
# Create compressed packages
spec = Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = PKG_NAME
s.summary = "brcpfcnpj é uma das gems que compoem o Brazilian Rails"
s.description = %q{brcpfcnpj é uma das gems que compoem o Brazilian Rails}
s.version = PKG_VERSION
s.authors = ["Marcos Tapajós", "Celestino Gomes", "Andre Kupkosvki", "Vinícius Teles", "Felipe Barreto", "Rafael Walter", "Cassio Marques"]
s.email = %w"tapajos@gmail.com tinorj@gmail.com kupkovski@gmail.com vinicius.m.teles@gmail.com felipebarreto@gmail.com rafawalter@gmail.com cassiommc@gmail.com"
s.rubyforge_project = "brcpfcnpj"
s.homepage = "http://www.improveit.com.br/software_livre/brazilian_rails"
s.add_dependency("actionpack", ">= 3.0.0")
s.add_dependency("activesupport", ">= 3.0.0")
s.add_development_dependency "rake"
s.add_development_dependency "rspec", ">= 2.4.0"
s.has_rdoc = true
s.requirements << "none"
s.require_path = "lib"
s.files = [ "Rakefile", "README.mkdn", "CHANGELOG", "MIT-LICENSE" ]
s.files = s.files + Dir.glob( "lib/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
s.files = s.files + Dir.glob( "test/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
end
Rake::GemPackageTask.new(spec) do |p|
p.gem_spec = spec
end
desc "Publish the release files to RubyForge."
task :release => [ :package ] do
`gem push pkg/#{PKG_FILE_NAME}.gem`
end

View File

@@ -0,0 +1,13 @@
# -*- encoding : utf-8 -*-
$:.unshift(File.dirname(__FILE__)) unless
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
%w(cpf_cnpj cnpj cpf cpf_cnpj_activerecord cnpj_validator cpf_validator).each {|req| require File.dirname(__FILE__) + "/brcpfcnpj/#{req}"}
%w(rubygems active_record active_support).each {|req| require req }
ActiveRecord::Base.send :include, CpfCnpjActiveRecord
module BrCpfCnpj
end

View File

@@ -0,0 +1,46 @@
# -*- encoding : utf-8 -*-
# Representa um numero de CNPJ. Objetos da classe Cnpj recebem strings representando numeros de cnpj e verificam a validade destes numeros usando dois criterios:
# 1. O formato da string, que deve seguir o padrao xx.xxx.xxx/xxxx-xx, onde 'x' pode ser qualquer digito de 0 a 9 e os tracos (-), barra (/) e pontos (.) *sao opcionais*.
# 2. O conteudo numerico desta string, que eh validado atraves do calculo do 'modulo 11' dos digitos que compoe a string.
#
# Caso o conteudo da string obedeca ao formato especificado acima, o mesmo sera formatado para obedecer ao padrao xx.xxx.xxx/xxxx-xx
#
# Eh importante observar que caso voce associe um valor de cnpj invalido ao seu model, o mesmo passara automaticamente a ser invalido, o que impede que valores de cpf incorretos sejam salvos no banco de dados.
#
# Como usar a classe Cnpj no seu ActiveRecord:
#
# 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 <tt>usar_como_cnpj</tt>, assim:
#
# class Empresa < ActiveRecord::Base
# usar_como_cnpj :cnpj
# end
#
# 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) # ==> 'não é válido' # de acordo com a I18n
#
# c = Cnpj.new("69103604000160")
# e.cnpj = "69.103.604/0001-60"
# c == e.cnpj # ==> true
class Cnpj
include CpfCnpj
end

View File

@@ -0,0 +1,6 @@
class CnpjValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
return if value.nil?
record.errors.add attribute, :invalid unless Cnpj.new(value).valido?
end
end

View File

@@ -0,0 +1,52 @@
# -*- encoding : utf-8 -*-
# Representa um numero de CPF. Objetos da classe Cpf recebem strings representando
# numeros de cpf e verificam a validade destes numeros usando dois criterios:
# 1. O formato da string, que deve seguir o padrao xxx.xxx.xxx-xx, onde 'x' pode ser qualquer digito de 0 a 9 e os tracos (-) e pontos (.) *sao opcionais*.
# 2. O conteudo numerico desta string, que eh validado atraves do calculo do 'modulo 11' dos digitos que compoe a string.
#
# Caso o conteudo da string obedeca ao formato especificado acima, o mesmo sera formatado para obedecer ao padrao xxx.xxx.xxx-xx
#
# Eh importante observar que caso voce associe um valor de cpf invalido ao seu model, o mesmo passara automaticamente a ser invalido, o que impede que valores de cpf incorretos sejam salvos no banco de dados.
#
# Como usar a classe Cpf no seu ActiveRecord:
#
# 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 <tt>usar_como_cpf</tt>, 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) # ==> 'não é válido' # de acordo com o I18n
#
# c = Cpf.new("11144477735")
# p.cpf = "111.444.777-35"
# c == p.cpf # ==> true
#
class Cpf
include CpfCnpj
end

View File

@@ -0,0 +1,90 @@
# -*- encoding : utf-8 -*-
module CpfCnpj
attr_reader :numero
def initialize(numero)
@numero = numero
@match = self.instance_of?(Cpf) ? @numero =~ CPF_REGEX : @numero =~ CNPJ_REGEX
@numero_puro = $1
@para_verificacao = $2
@numero = (@match ? format_number! : nil)
end
def to_s
@numero || ""
end
def ==(outro_doc)
self.numero == outro_doc.numero
end
# Verifica se o numero possui o formato correto e se
# constitui um numero de documento valido, dependendo do seu
# tipo (Cpf ou Cnpj).
def valido?
return false unless @match
verifica_numero
end
private
DIVISOR = 11
CPF_LENGTH = 11
CPF_REGEX = /^(\d{3}\.?\d{3}\.?\d{3})-?(\d{2})$/
CPF_ALGS_1 = [10, 9, 8, 7, 6, 5, 4, 3, 2]
CPF_ALGS_2 = [11, 10, 9, 8, 7, 6, 5, 4, 3, 2]
CNPJ_LENGTH = 14
CNPJ_REGEX = /^(\d{2}\.?\d{3}\.?\d{3}\/?\d{4})-?(\d{2})$/ # <= 11.222.333/0001-XX
CNPJ_ALGS_1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
CNPJ_ALGS_2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
def verifica_numero
limpo = @numero.gsub(/[\.\/-]/, "")
if self.instance_of? Cpf
return false if limpo.length != 11
elsif self.instance_of? Cnpj
return false if limpo.length != 14
end
return false if limpo.scan(/\d/).uniq.length == 1
primeiro_verificador = primeiro_digito_verificador
segundo_verificador = segundo_digito_verificador(primeiro_verificador)
verif = primeiro_verificador + segundo_verificador
verif == @para_verificacao
end
def multiplica_e_soma(algs, numero_str)
multiplicados = []
numero_str.scan(/\d{1}/).each_with_index { |e, i| multiplicados[i] = e.to_i * algs[i] }
multiplicados.inject { |s,e| s + e }
end
def digito_verificador(resto)
resto < 2 ? 0 : DIVISOR - resto
end
def primeiro_digito_verificador
array = self.instance_of?(Cpf) ? CPF_ALGS_1 : CNPJ_ALGS_1
soma = multiplica_e_soma(array, @numero_puro)
digito_verificador(soma%DIVISOR).to_s
end
def segundo_digito_verificador(primeiro_verificador)
array = self.instance_of?(Cpf) ? CPF_ALGS_2 : CNPJ_ALGS_2
soma = multiplica_e_soma(array, @numero_puro + primeiro_verificador)
digito_verificador(soma%DIVISOR).to_s
end
def format_number!
if self.instance_of? Cpf
@numero =~ /(\d{3})\.?(\d{3})\.?(\d{3})-?(\d{2})/
@numero = "#{$1}.#{$2}.#{$3}-#{$4}"
else
@numero =~ /(\d{2})\.?(\d{3})\.?(\d{3})\/?(\d{4})-?(\d{2})/
@numero = "#{$1}.#{$2}.#{$3}/#{$4}-#{$5}"
end
end
end

View File

@@ -0,0 +1,61 @@
# -*- encoding : utf-8 -*-
module CpfCnpjActiveRecord #:nodoc:
def self.included(base) #:nodoc:
base.extend ClassMethods
end
module ClassMethods #:nodoc:
def usar_como_cpf(*args) #:nodoc:
init(args, 'Cpf')
end
def usar_como_cnpj(*args) #:nodoc:
init(args, 'Cnpj')
end
def init(args, klass)
unless args.size.zero?
args.each do |name|
add_composed_class(name, klass)
module_eval create_code(name.to_s, klass)
end
end
end
def add_composed_class(name, klass)
options = {:class_name => klass, :mapping => [name.to_s, "numero"], :allow_nil => true}
constructor = Proc.new { |numero| eval(klass).new(numero) }
converter = Proc.new { |value| eval(klass).new(value) }
begin
composed_of name, options.merge( { :constructor => constructor, :converter => converter } )
rescue Exception
composed_of name, options { eval(klass).new(name[:numero]) }
end
end
def create_code(name, klass)
str = <<-CODE
validate :#{name}_valido?
def #{name}_valido?
value = read_attribute('#{name}')
if !value.nil? && value.strip != '' && !#{name}.nil? && !#{name}.valido?
self.errors.add('#{name}', :invalid)
end
end
def #{name}=(value)
if value.blank?
write_attribute('#{name}', nil)
elsif value.kind_of?(#{eval(klass)})
write_attribute('#{name}', value.numero)
else
begin
c = #{eval(klass)}.new(value)
c.valido? ? write_attribute('#{name}', c.numero) : write_attribute('#{name}', value)
rescue
@#{name} = value
end
end
end
CODE
end
end
end

View File

@@ -0,0 +1,6 @@
class CpfValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
return if value.nil?
record.errors.add attribute, :invalid unless Cpf.new(value).valido?
end
end

View File

@@ -0,0 +1,10 @@
module BrCpfCnpj
module VERSION #:nodoc:
MAJOR = 3
MINOR = 3
TINY = 0
STRING = "#{MAJOR}.#{MINOR}.#{TINY}"
end
end

View File

@@ -0,0 +1,2 @@
# -*- encoding : utf-8 -*-
require File.dirname(__FILE__) + '/../lib/brcpfcnpj'

View File

@@ -0,0 +1,33 @@
# -*- encoding : utf-8 -*-
require 'active_record'
module ActiveRecord
class BaseWithoutTable < Base
self.abstract_class = true
def create_or_update
errors.empty?
end
def save
self.valid?
end
class << self
def columns()
@columns ||= []
end
def column(name, sql_type = nil, default = nil, null = true)
columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
reset_column_information
end
# Do not reset @columns
def reset_column_information
generated_methods.each { |name| undef_method(name) }
@column_names = @columns_hash = @content_columns = @dynamic_methods_hash = @read_methods = nil
end
end
end
end

View File

@@ -0,0 +1,114 @@
# -*- encoding : utf-8 -*-
require File.dirname(__FILE__) + '/spec_helper'
require File.dirname(__FILE__) + '/active_record/base_without_table'
class Empresa < ActiveRecord::Base
usar_como_cnpj :cnpj
end
describe "Using a model attribute as Cnpj" do
before(:each) do
@company = Empresa.new
end
it "should format the received number" do
@company.cnpj = "69103604000160"
@company.cnpj.numero.should == "69.103.604/0001-60"
end
it "should respond to cnpj_valido?" do
@company.respond_to?('cnpj_valido?').should be_true
end
it "should be invalid with an invalid cnpj number" do
@company.cnpj = "123545"
@company.should_not be_valid
end
it "should be invalid with a too long number" do
@company.cnpj = "12323456678654454"
@company.should_not be_valid
end
it "should not save the instance with an invalid cnpj" do
@company.cnpj = "sdwewe"
@company.save.should be_false
end
it "should have an error in the cnpj field when invalid" do
@company.cnpj = "232df"
@company.save
@company.errors[:cnpj].should == ["is invalid"]
end
it "should be valid with a null cnpj number" do
@company.cnpj = nil
@company.should be_valid
end
it "should be valid with an empty string in the constructor of an instance of cnpj" do
@company.cnpj = Cnpj.new("")
@company.should be_valid
end
it "should be valid with an empty string as the cnpj number" do
@company.cnpj = ""
@company.should be_valid
end
it "should accept an instance of Cnpj" do
@company.cnpj = Cnpj.new("69103604000160")
@company.cnpj.should be_instance_of(Cnpj)
end
it "should be able to receive parameters at initialization" do
@company = Empresa.new(:cnpj => "69103604000160")
@company.cnpj.numero.should == "69.103.604/0001-60"
end
end
describe "when validating" do
before do
Empresa.validates_presence_of :cnpj
end
describe "presence" do
it "should be invalid with a new cnpj number" do
e = Empresa.new(:nome => "Bla")
e.should_not be_valid
e.errors[:cnpj].should eql(["can't be blank"])
end
it "should be invalid using an empty string as the cnpj number" do
e = Empresa.new(:nome => "Bla", :cnpj => "")
e.should_not be_valid
e.errors[:cnpj].should_not be_empty
end
it "should be valid with a cnpj" do
Empresa.new(:nome => "Bla", :cnpj => "00012345000165").should be_valid
end
end
describe "uniqueness" do
before(:each) do
Empresa.validates_uniqueness_of :cnpj
@e1 = Empresa.new(:nome => "Bla", :cnpj => "69103604000160")
@e1.save
end
it "should validate uniqueness of cnpj" do
e2 = Empresa.new(:nome => "Ble", :cnpj => "69103604000160")
e2.should_not be_valid
e2.errors[:cnpj].should_not be_empty
end
it "should be valid using a new cnpj" do
e2 = Empresa.new(:nome => "Ble", :cnpj => "00012345000165")
e2.should be_valid
end
end
end

View File

@@ -0,0 +1,51 @@
# -*- encoding : utf-8 -*-
require File.dirname(__FILE__) + '/spec_helper'
describe Cnpj do
it "should be invalid with malformed number" do
numeros = %w(04.22A.284/0001-11 04.222-284.0001-11 04222/284/0001-11)
numeros.each do |n|
cnpj = Cnpj.new(n)
cnpj.should_not be_valido
end
end
it "should be invalid with invalid number" do
numeros = %w(69103604020160 00000000000000 69.103.604/0001-61 01618211000264)
numeros.each do |n|
cnpj = Cnpj.new(n)
cnpj.should_not be_valido
end
end
it "should be invalid with a number longer than 14 chars, even if the first 14 represent a valid number" do
%w(691036040001-601 69103604000160a 69103604000160ABC 6910360400016000).each do |n|
Cnpj.new(n).should_not be_valido
end
end
it "should be valid with correct number" do
numeros = %w(69103604000160 69.103.604/0001-60 01518211/000264 01.5182110002-64 00.000.000/1447-89)
numeros.each do |n|
cnpj = Cnpj.new(n)
cnpj.should be_valido
end
end
it "should return the formated cnpj" do
cnpj = Cnpj.new("69103604000160")
cnpj.to_s.should == "69.103.604/0001-60"
end
it "should format the received number at instantiation" do
cnpj = Cnpj.new("69103604000160")
cnpj.numero.should == "69.103.604/0001-60"
end
it "should be equal to another instance with the same number" do
Cnpj.new("69103604000160").should == Cnpj.new("69.103.604/0001-60")
end
end

View File

@@ -0,0 +1,22 @@
require File.dirname(__FILE__) + '/spec_helper'
require File.dirname(__FILE__) + '/active_record/base_without_table'
class Company < ActiveRecord::Base
validates :cnpj, :cnpj => true
end
describe CnpjValidator do
it "should isn't valid when the cnpj isn't valid" do
@empresa = Company.new(:cnpj => "12345")
@empresa.valid?.should be_false
@empresa.errors[:cnpj].should == ["is invalid"]
end
it "should accept a nil cnpj" do
@empresa = Company.new(:cnpj => nil)
@empresa.valid?.should be_true
end
it "should be valid with a valid CNPJ" do
@empresa = Company.new(:cnpj => "69103604000160")
@empresa.valid?.should be_true
end
end

View File

@@ -0,0 +1,120 @@
# -*- encoding : utf-8 -*-
require File.dirname(__FILE__) + '/spec_helper'
require File.dirname(__FILE__) + '/active_record/base_without_table'
class Pessoa < ActiveRecord::Base
usar_como_cpf :cpf
end
describe "Using a model attribute as Cpf" do
before(:each) do
@person = Pessoa.new(:nome => "Fulano")
end
it "should format the received number" do
@person.cpf = "11144477735"
@person.cpf.numero.should == "111.444.777-35"
end
it "should respond to cpf_valido?" do
@person.respond_to?('cpf_valido?').should be_true
end
it "should be invalid with an invalid cpf number" do
@person.cpf = "123545"
@person.should_not be_valid
end
it "should be invalid with a too long number" do
@person.cpf = "123456678654454"
@person.should_not be_valid
end
it "should be valid with an empty string in the constructor of an instance of Cpf" do
@person.cpf = Cpf.new("")
@person.should be_valid
end
it "should be valid with an empty string as the cpf number" do
@person.cpf = ""
@person.should be_valid
end
it "should not save the instance with an invalid cpf" do
@person.cpf = "sdwewe"
@person.save.should be_false
end
it "should have an error in the cpf field when invalid" do
@person.cpf = "232df"
@person.save.should be_false
@person.errors[:cpf].should == ["is invalid"]
end
it "should be valid with a null cpf number" do
@person.cpf = nil
@person.should be_valid
end
it "should accept an instance of Cpf" do
@person.cpf = Cpf.new("11144477735")
@person.cpf.should be_instance_of(Cpf)
end
it "should be able to receive parameters at initialization" do
@person = Pessoa.new(:cpf => "111.44477735")
@person.cpf.numero.should == "111.444.777-35"
end
it "should change the current attribute's value" do
@person.cpf = Cpf.new("13434")
lambda {
@person.cpf = Cpf.new("111.444.777-35")
}.should change(@person, :cpf)
end
end
describe "when validating" do
describe "presence" do
before do
Pessoa.validates_presence_of :cpf
end
it "should be invalid with a nil cpf number" do
p = Pessoa.new(:nome => "Fulano", :cpf => nil)
p.should_not be_valid
p.errors[:cpf].should eql(["can't be blank"])
end
it "should be invalid with an empty string as the cpf number" do
p = Pessoa.new(:nome => "Fulano", :cpf => "")
p.should_not be_valid
p.errors[:cpf].should_not be_empty
end
it "should be valid with a cpf" do
Pessoa.new(:nome => "Fulano", :cpf => "11144477735").should be_valid
end
end
describe "uniqueness" do
before(:each) do
Pessoa.validates_uniqueness_of :cpf
@p1 = Pessoa.new(:nome => "Beltrano", :cpf => "11144477735")
@p1.save
end
it "should validate uniqueness of cpf" do
p2 = Pessoa.new(:nome => "Beltrano", :cpf => "11144477735")
p2.should_not be_valid
p2.errors[:cpf].should_not be_empty
end
it "should be valid using a new cpf" do
p2 = Pessoa.new(:nome => "Fulano", :cpf => "00123456797")
p2.should be_valid
end
end
end

View File

@@ -0,0 +1,50 @@
# -*- encoding : utf-8 -*-
require File.dirname(__FILE__) + '/spec_helper'
describe Cpf do
it "should be invalid with malformed number" do
numeros = %w(345.65.67.3 567.765-87698 345456-654-01 123456)
numeros.each do |n|
cpf = Cpf.new(n)
cpf.should_not be_valido
end
end
it "should be invalid with invalid number" do
numeros = %w(23342345699 34.543.567-98 456.676456-87 333333333-33 00000000000 000.000.000-00)
numeros.each do |n|
cpf = Cpf.new(n)
cpf.should_not be_valido
end
end
it "should be valid with correct number" do
numeros = %w(111.444.777-35 11144477735 111.444777-35 111444.777-35 111.444.77735)
numeros.each do |n|
cpf = Cpf.new(n)
cpf.should be_valido
end
end
it "should be invalid with a number longer than 11 chars, even if the first 11 char represent a valid cpf number" do
%w(111.444.777-3500 11144477735AB).each do |n|
Cpf.new(n).should_not be_valido
end
end
it "should return the formated cpf" do
cpf = Cpf.new("11144477735")
cpf.to_s.should == "111.444.777-35"
end
it "should format the received number at instantiation" do
cpf = Cpf.new("11144477735")
cpf.numero.should == "111.444.777-35"
end
it "should be equal to another instance with the same number" do
Cpf.new("11144477735").should == Cpf.new("111.444.777-35")
end
end

View File

@@ -0,0 +1,21 @@
require File.dirname(__FILE__) + '/spec_helper'
require File.dirname(__FILE__) + '/active_record/base_without_table'
class Person < ActiveRecord::Base
validates :cpf, :cpf => true
end
describe CpfValidator do
it "should isn't valid when the cpf isn't valid" do
@pessoa = Person.new(:cpf => "12345")
@pessoa.valid?.should be_false
@pessoa.errors[:cpf].should == ["is invalid"]
end
it "should accept a nil cpf" do
@pessoa = Person.new(:cpf => nil)
@pessoa.valid?.should be_true
end
it "should be valid with a valid cpf" do
@pessoa = Person.new(:cpf => "11144477735")
@pessoa.valid?.should be_true
end
end

View File

@@ -0,0 +1,29 @@
# -*- encoding : utf-8 -*-
class CreateTestingStructure < ActiveRecord::Migration
def self.up
create_table :empresas do |t|
t.string :nome
t.string :cnpj
end
create_table :pessoas do |t|
t.string :nome
t.string :cpf
end
create_table :companies do |t|
t.string :nome
t.string :cnpj
end
create_table :people do |t|
t.string :nome
t.string :cpf
end
end
def self.down
drop_table :pessoas
drop_table :empresas
drop_table :companies
drop_table :people
end
end

View File

@@ -0,0 +1,11 @@
# -*- encoding : utf-8 -*-
require "rubygems"
require "rspec"
require "active_record"
require File.expand_path(File.dirname(__FILE__) + "/../lib/brcpfcnpj")
ActiveRecord::Base.establish_connection(:adapter=>"sqlite3", :database => ":memory:")
require File.dirname(__FILE__) + "/db/create_testing_structure"
CreateTestingStructure.migrate(:up)