cpf_cnpj 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
[](https://travis-ci.org/fnando/cpf_cnpj)
|
4
|
+
[](https://codeclimate.com/github/fnando/cpf_cnpj)
|
5
|
+
[](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
|