cpf_cnpj 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +7 -0
- data/README.md +24 -8
- data/Rakefile +10 -1
- data/bin/cnpj +2 -1
- data/bin/cpf +2 -1
- data/cpf_cnpj.gemspec +2 -1
- data/lib/cnpj.rb +27 -23
- data/lib/cnpj/formatter.rb +5 -2
- data/lib/cpf.rb +29 -25
- data/lib/cpf/formatter.rb +5 -2
- data/lib/cpf_cnpj.rb +3 -0
- data/lib/cpf_cnpj/cli.rb +109 -0
- data/lib/cpf_cnpj/generator.rb +12 -0
- data/lib/cpf_cnpj/version.rb +6 -2
- data/test/support/capture_syscall.rb +14 -0
- data/test/test_helper.rb +8 -0
- data/test/unit/cnpj/cli_test.rb +132 -0
- data/test/unit/cnpj/formatter_test.rb +13 -0
- data/test/unit/cnpj/generator_test.rb +11 -0
- data/test/unit/cnpj_test.rb +46 -0
- data/test/unit/cpf/cli_test.rb +134 -0
- data/test/unit/cpf/formatter_test.rb +13 -0
- data/test/unit/cpf/generator_test.rb +11 -0
- data/test/unit/cpf_test.rb +71 -0
- metadata +42 -33
- data/.rspec +0 -1
- data/Gemfile.lock +0 -47
- data/lib/cnpj/cli.rb +0 -102
- data/lib/cnpj/generator.rb +0 -12
- data/lib/cpf/cli.rb +0 -103
- data/lib/cpf/generator.rb +0 -12
- data/spec/cnpj/cli_spec.rb +0 -119
- data/spec/cnpj/formatter_spec.rb +0 -13
- data/spec/cnpj/generator_spec.rb +0 -15
- data/spec/cnpj_spec.rb +0 -46
- data/spec/cpf/cli_spec.rb +0 -119
- data/spec/cpf/formatter_spec.rb +0 -13
- data/spec/cpf/generator_spec.rb +0 -15
- data/spec/cpf_spec.rb +0 -73
- data/spec/spec_helper.rb +0 -6
- data/spec/support/capture_exit.rb +0 -10
- data/spec/support/validation_shared.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d13c9e2acfdc0d60eb9ffeb2c9008fdd6bad5d0f
|
4
|
+
data.tar.gz: bf59d4b1eb0c251086bc8d241b2811b61f7cefec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 778b36870ff6afc4ad0b4c5ba65aa148aef45ba8b8005c2e277808c5559d8e7b7ef4b8e06ff1036aef81b188ce765f5befea46901cbedf84e940a85d672755b2
|
7
|
+
data.tar.gz: c5a4bd47257e4afa53b44bbf514b17bb4c8b2b0726b8cb4157895f42184db1713201ace9c75550a0d566efb4bf65d9497479f1d134c678d5ffae36197177631b
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,9 +1,15 @@
|
|
1
1
|
# CPF/CNPJ
|
2
2
|
|
3
|
+
[![Build Status](https://travis-ci.org/fnando/cpf_cnpj.svg)](https://travis-ci.org/fnando/cpf_cnpj)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/fnando/cpf_cnpj/badges/gpa.svg)](https://codeclimate.com/github/fnando/cpf_cnpj)
|
5
|
+
[![Gem Version](https://badge.fury.io/rb/cpf_cnpj.svg)](http://badge.fury.io/rb/cpf_cnpj)
|
6
|
+
|
3
7
|
This gem does some [CPF](http://en.wikipedia.org/wiki/Cadastro_de_Pessoas_F%C3%ADsicas)/[CNPJ](http://en.wikipedia.org/wiki/CNPJ) magic. It allows you to create, validate and format CPF/CNPJ, even through the command-line.
|
4
8
|
|
5
9
|
Just making my life easier when filling these damn numbers on internet bankings and government sites.
|
6
10
|
|
11
|
+
For ActiveModel/ActiveRecord validations, please check <https://github.com/fnando/validators>.
|
12
|
+
|
7
13
|
## Installation
|
8
14
|
|
9
15
|
Add this line to your application's Gemfile:
|
@@ -24,16 +30,26 @@ Or install it yourself as:
|
|
24
30
|
|
25
31
|
This library has the same API for both CNPJ/CPF, so only one of them is documented below.
|
26
32
|
|
27
|
-
|
33
|
+
```ruby
|
34
|
+
require "cpf_cnpj"
|
35
|
+
|
36
|
+
CPF.valid?(number) # Check if a CPF is valid
|
37
|
+
CPF.generate # Generate a random CPF number
|
38
|
+
CPF.generate(true) # Generate a formatted number
|
39
|
+
|
40
|
+
cpf = CPF.new(number)
|
41
|
+
cpf.formatted # Return formatted CPF (xxx.xxx.xxx-xx)
|
42
|
+
cpf.stripped # Return stripped CPF (xxxxxxxxxxx)
|
43
|
+
cpf.valid? # Check if CPF is valid
|
44
|
+
```
|
45
|
+
|
46
|
+
#### Strict Validation
|
28
47
|
|
29
|
-
|
30
|
-
CPF.generate # Generate a random CPF number
|
31
|
-
CPF.generate(true) # Generate a formatted number
|
48
|
+
By default, validations will strip any characters that aren't numbers. This means that `532#####820------857\n96` is considered a valid number. To perform a strict validation use `strict: true`.
|
32
49
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
cpf.valid? # Check if CPF is valid
|
50
|
+
```ruby
|
51
|
+
CPF.valid?(number, strict: true)
|
52
|
+
```
|
37
53
|
|
38
54
|
### Command-line
|
39
55
|
|
data/Rakefile
CHANGED
data/bin/cnpj
CHANGED
data/bin/cpf
CHANGED
data/cpf_cnpj.gemspec
CHANGED
@@ -14,6 +14,7 @@ Gem::Specification.new do |gem|
|
|
14
14
|
gem.require_paths = ["lib"]
|
15
15
|
gem.version = CPF::VERSION
|
16
16
|
|
17
|
-
gem.add_development_dependency "rspec"
|
18
17
|
gem.add_development_dependency "pry-meta"
|
18
|
+
gem.add_development_dependency "rake"
|
19
|
+
gem.add_development_dependency "minitest-utils"
|
19
20
|
end
|
data/lib/cnpj.rb
CHANGED
@@ -1,37 +1,40 @@
|
|
1
1
|
class CNPJ
|
2
|
-
require "
|
2
|
+
require "cpf_cnpj"
|
3
3
|
require "cnpj/formatter"
|
4
|
-
require "cnpj/generator"
|
5
4
|
require "cnpj/verifier_digit"
|
6
5
|
|
7
6
|
attr_reader :number
|
7
|
+
attr_reader :strict
|
8
8
|
|
9
9
|
REGEX = /\A\d{2}\.\d{3}.\d{3}\/\d{4}-\d{2}\Z/
|
10
|
+
NUMBER_SIZE = 12
|
10
11
|
|
11
|
-
BLACKLIST = [
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
]
|
12
|
+
BLACKLIST = %w[
|
13
|
+
00000000000000
|
14
|
+
11111111111111
|
15
|
+
22222222222222
|
16
|
+
33333333333333
|
17
|
+
44444444444444
|
18
|
+
55555555555555
|
19
|
+
66666666666666
|
20
|
+
77777777777777
|
21
|
+
88888888888888
|
22
|
+
9999999999999
|
23
|
+
].freeze
|
23
24
|
|
24
|
-
def self.valid?(number)
|
25
|
-
new(number).valid?
|
25
|
+
def self.valid?(number, strict: false)
|
26
|
+
new(number, strict).valid?
|
26
27
|
end
|
27
28
|
|
28
29
|
def self.generate(formatted = false)
|
29
|
-
|
30
|
+
number = CpfCnpj::Generator.generate(NUMBER_SIZE, VerifierDigit)
|
31
|
+
cnpj = new(number)
|
30
32
|
formatted ? cnpj.formatted : cnpj.stripped
|
31
33
|
end
|
32
34
|
|
33
|
-
def initialize(number)
|
35
|
+
def initialize(number, strict = false)
|
34
36
|
@number = number.to_s
|
37
|
+
@strict = strict
|
35
38
|
end
|
36
39
|
|
37
40
|
def number=(number)
|
@@ -42,7 +45,7 @@ class CNPJ
|
|
42
45
|
end
|
43
46
|
|
44
47
|
def stripped
|
45
|
-
@stripped ||= Formatter.strip(number)
|
48
|
+
@stripped ||= Formatter.strip(number, strict)
|
46
49
|
end
|
47
50
|
|
48
51
|
def formatted
|
@@ -53,14 +56,15 @@ class CNPJ
|
|
53
56
|
return unless stripped.size == 14
|
54
57
|
return if BLACKLIST.include?(stripped)
|
55
58
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
+
digits = numbers[0...12]
|
60
|
+
digits << VerifierDigit.generate(digits)
|
61
|
+
digits << VerifierDigit.generate(digits)
|
59
62
|
|
60
|
-
|
63
|
+
digits[-2, 2] == numbers[-2, 2]
|
61
64
|
end
|
62
65
|
|
63
66
|
private
|
67
|
+
|
64
68
|
def numbers
|
65
69
|
@numbers ||= stripped.each_char.to_a.map(&:to_i)
|
66
70
|
end
|
data/lib/cnpj/formatter.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
class CNPJ
|
2
2
|
class Formatter
|
3
|
+
STRICT_REGEX = /[\/.-]/
|
4
|
+
LOOSE_REGEX = /[^\d]/
|
5
|
+
|
3
6
|
def self.format(number)
|
4
7
|
strip(number).gsub(/\A(\d{2})(\d{3})(\d{3})(\d{4})(\d{2})\Z/, "\\1.\\2.\\3/\\4-\\5")
|
5
8
|
end
|
6
9
|
|
7
|
-
def self.strip(number)
|
8
|
-
number.to_s.gsub(
|
10
|
+
def self.strip(number, strict = false)
|
11
|
+
number.to_s.gsub(strict ? STRICT_REGEX : LOOSE_REGEX, "")
|
9
12
|
end
|
10
13
|
end
|
11
14
|
end
|
data/lib/cpf.rb
CHANGED
@@ -1,38 +1,41 @@
|
|
1
1
|
class CPF
|
2
|
-
require "
|
2
|
+
require "cpf_cnpj"
|
3
3
|
require "cpf/formatter"
|
4
|
-
require "cpf/generator"
|
5
4
|
require "cpf/verifier_digit"
|
6
5
|
|
7
6
|
attr_reader :number
|
7
|
+
attr_reader :strict
|
8
8
|
|
9
9
|
REGEX = /\A\d{3}\.\d{3}\.\d{3}-\d{2}\Z/
|
10
|
+
NUMBER_SIZE = 9
|
10
11
|
|
11
|
-
BLACKLIST = [
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
]
|
12
|
+
BLACKLIST = %w[
|
13
|
+
00000000000
|
14
|
+
11111111111
|
15
|
+
22222222222
|
16
|
+
33333333333
|
17
|
+
44444444444
|
18
|
+
55555555555
|
19
|
+
66666666666
|
20
|
+
77777777777
|
21
|
+
88888888888
|
22
|
+
99999999999
|
23
|
+
12345678909
|
24
|
+
].freeze
|
24
25
|
|
25
|
-
def self.valid?(number)
|
26
|
-
new(number).valid?
|
26
|
+
def self.valid?(number, strict: false)
|
27
|
+
new(number, strict).valid?
|
27
28
|
end
|
28
29
|
|
29
30
|
def self.generate(formatted = false)
|
30
|
-
|
31
|
+
number = CpfCnpj::Generator.generate(NUMBER_SIZE, VerifierDigit)
|
32
|
+
cpf = new(number)
|
31
33
|
formatted ? cpf.formatted : cpf.stripped
|
32
34
|
end
|
33
35
|
|
34
|
-
def initialize(number)
|
36
|
+
def initialize(number, strict = false)
|
35
37
|
@number = number.to_s
|
38
|
+
@strict = strict
|
36
39
|
end
|
37
40
|
|
38
41
|
def number=(number)
|
@@ -43,25 +46,26 @@ class CPF
|
|
43
46
|
end
|
44
47
|
|
45
48
|
def stripped
|
46
|
-
@stripped ||= Formatter.strip(number)
|
49
|
+
@stripped ||= Formatter.strip(number, strict)
|
47
50
|
end
|
48
51
|
|
49
52
|
def formatted
|
50
53
|
@formatted ||= Formatter.format(number)
|
51
54
|
end
|
52
55
|
|
53
|
-
def valid?
|
56
|
+
def valid?(strict: false)
|
54
57
|
return unless stripped.size == 11
|
55
58
|
return if BLACKLIST.include?(stripped)
|
56
59
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
+
digits = numbers[0...9]
|
61
|
+
digits << VerifierDigit.generate(digits)
|
62
|
+
digits << VerifierDigit.generate(digits)
|
60
63
|
|
61
|
-
|
64
|
+
digits[-2, 2] == numbers[-2, 2]
|
62
65
|
end
|
63
66
|
|
64
67
|
private
|
68
|
+
|
65
69
|
def numbers
|
66
70
|
@numbers ||= stripped.each_char.to_a.map(&:to_i)
|
67
71
|
end
|
data/lib/cpf/formatter.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
class CPF
|
2
2
|
class Formatter
|
3
|
+
STRICT_REGEX = /[.-]/
|
4
|
+
LOOSE_REGEX = /[^\d]/
|
5
|
+
|
3
6
|
def self.format(number)
|
4
7
|
strip(number).gsub(/\A(\d{3})(\d{3})(\d{3})(\d{2})\Z/, "\\1.\\2.\\3-\\4")
|
5
8
|
end
|
6
9
|
|
7
|
-
def self.strip(number)
|
8
|
-
number.to_s.gsub(
|
10
|
+
def self.strip(number, strict = false)
|
11
|
+
number.to_s.gsub(strict ? STRICT_REGEX : LOOSE_REGEX, "")
|
9
12
|
end
|
10
13
|
end
|
11
14
|
end
|
data/lib/cpf_cnpj.rb
CHANGED
data/lib/cpf_cnpj/cli.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
module CpfCnpj
|
2
|
+
class CLI
|
3
|
+
attr_reader :document_class, :arguments, :stdin, :stdout, :stderr
|
4
|
+
|
5
|
+
def initialize(document_class, arguments, stdin, stdout, stderr)
|
6
|
+
@document_class = document_class
|
7
|
+
@arguments = arguments
|
8
|
+
@stdin = stdin
|
9
|
+
@stdout = stdout
|
10
|
+
@stderr = stderr
|
11
|
+
end
|
12
|
+
|
13
|
+
def bin_name
|
14
|
+
document_name.downcase
|
15
|
+
end
|
16
|
+
|
17
|
+
def document_name
|
18
|
+
document_class.name
|
19
|
+
end
|
20
|
+
|
21
|
+
def start
|
22
|
+
options = {}
|
23
|
+
|
24
|
+
opts.banner = "Usage: #{bin_name} [options] [#{document_name} number]"
|
25
|
+
opts.separator ""
|
26
|
+
opts.separator "Specific options:"
|
27
|
+
|
28
|
+
opts.on("-c", "--check", "Check if #{document_name} is valid") do
|
29
|
+
options[:check] = true
|
30
|
+
end
|
31
|
+
|
32
|
+
opts.on("-g", "--generate", "Generate a new #{document_name}") do
|
33
|
+
options[:generate] = true
|
34
|
+
end
|
35
|
+
|
36
|
+
opts.on("-f", "--format", "Format #{document_name} with separators") do
|
37
|
+
options[:format] = true
|
38
|
+
end
|
39
|
+
|
40
|
+
opts.on("-s", "--strip", "Remove #{document_name} separators") do
|
41
|
+
options[:strip] = true
|
42
|
+
end
|
43
|
+
|
44
|
+
opts.on("-v", "--version", "Show version") do
|
45
|
+
stdout << VERSION
|
46
|
+
exit
|
47
|
+
end
|
48
|
+
|
49
|
+
opts.on_tail("-h", "--help", "Show help") do
|
50
|
+
help
|
51
|
+
exit
|
52
|
+
end
|
53
|
+
|
54
|
+
opts.parse!(arguments)
|
55
|
+
opts.permute!(arguments)
|
56
|
+
|
57
|
+
help if options.empty?
|
58
|
+
generate(options) if options[:generate]
|
59
|
+
input = stdin.tty? ? arguments.first : stdin.read
|
60
|
+
document = document_class.new(input)
|
61
|
+
validate(document)
|
62
|
+
format(document) if options[:format]
|
63
|
+
strip(document) if options[:strip]
|
64
|
+
check(document) if options[:check]
|
65
|
+
end
|
66
|
+
|
67
|
+
def validate(document)
|
68
|
+
return if document.valid?
|
69
|
+
stderr << "Error: Invalid number\n"
|
70
|
+
exit 1
|
71
|
+
end
|
72
|
+
|
73
|
+
# No-op method. CPF is always validated on CpfCnpj::CLI#start.
|
74
|
+
def check(_document)
|
75
|
+
exit
|
76
|
+
end
|
77
|
+
|
78
|
+
def generate(options)
|
79
|
+
document = document_class.new(document_class.generate)
|
80
|
+
|
81
|
+
if options[:strip]
|
82
|
+
stdout << document.stripped
|
83
|
+
else
|
84
|
+
stdout << document.formatted
|
85
|
+
end
|
86
|
+
|
87
|
+
exit
|
88
|
+
end
|
89
|
+
|
90
|
+
def format(document)
|
91
|
+
stdout << document.formatted
|
92
|
+
exit
|
93
|
+
end
|
94
|
+
|
95
|
+
def strip(document)
|
96
|
+
stdout << document.stripped
|
97
|
+
exit
|
98
|
+
end
|
99
|
+
|
100
|
+
def help
|
101
|
+
stderr << opts.to_s
|
102
|
+
exit 1
|
103
|
+
end
|
104
|
+
|
105
|
+
def opts
|
106
|
+
@opts ||= OptionParser.new
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|