brid 0.1.3 → 0.2.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.
data/.rspec CHANGED
@@ -1 +1,2 @@
1
1
  --color
2
+ --debug
data/README.md CHANGED
@@ -5,7 +5,9 @@
5
5
 
6
6
  Add this line to your application's Gemfile:
7
7
 
8
- gem 'brid'
8
+ ``` ruby
9
+ gem 'brid'
10
+ ```
9
11
 
10
12
  And then execute:
11
13
 
@@ -15,9 +17,60 @@ Or install it yourself as:
15
17
 
16
18
  $ gem install brid
17
19
 
20
+ ## Components
21
+
22
+ * CPF object with validation (brazilian document)
23
+ * CNPJ object with validation (brazilian document)
24
+ * Título de Eleitor object with validation (brazilian document)
25
+ * PIS object with validation (brazilian document)
26
+ * Cred Card object with validation (generic)
27
+ * Generic ID validation (can validate bank account and other things)
28
+ * Luhn algorithms modulus 10 and 11 http://en.wikipedia.org/wiki/Luhn_algorithm
29
+
18
30
  ## Usage
19
31
 
20
- TODO: Write usage instructions here
32
+ ### Validating a CPF
33
+
34
+ ``` ruby
35
+ CPF.new('135246876-01').valid? # true
36
+ CPF.new('135.246.876-01').valid? # true
37
+ CPF.new('13524687601').valid? # true
38
+ CPF.new(13524687601).valid? # true
39
+ (Mod11.new('135246876') * 2).to_s == '13524687601' # true
40
+ '135246876'.mod11(2) == '13524687601' # true
41
+ ```
42
+
43
+ ### Validating a CNPJ
44
+
45
+ ``` ruby
46
+ CNPJ.new('18.781.203/0001-28').valid? # true
47
+ (Mod11.new('8.781.203/0001', :base => 2..9) * 2).to_s == '8781203000128' # true
48
+ '8.781.203/0001'.mod11(2, :base => 2..9) == '8781203000128' # true
49
+
50
+ ```
51
+
52
+ ### Validating a Bank Account
53
+
54
+ ``` ruby
55
+ GenericID.new('12345-5').valid? # true
56
+ (Mod11.new('12345') * 1).to_s == '123455' # true
57
+ '12345'.mod11 == '123455' # true
58
+
59
+ ```
60
+
61
+ ### Validating a Cred Card
62
+
63
+ ``` ruby
64
+ CredCard.new('411119876333502').valid? # true
65
+ (Mod10.new('41111987633350') * 1).to_s == '411119876333502' # true
66
+ '41111987633350'.mod10 == '411119876333502' # true
67
+ ```
68
+
69
+
70
+ ## Next Steps
71
+
72
+ * Develop a rails plugin built on top of ActiveRecord
73
+ * Develop a smart generator for fixture on tests (I thought of doing built on top of ffaker, like my othre gem: [ffaker-cpfcnpj](https://github.com/halan/ffaker-cpfcnpj) )
21
74
 
22
75
  ## Contributing
23
76
 
@@ -26,3 +79,28 @@ TODO: Write usage instructions here
26
79
  3. Commit your changes (`git commit -am 'Added some feature'`)
27
80
  4. Push to the branch (`git push origin my-new-feature`)
28
81
  5. Create new Pull Request
82
+
83
+ ## License
84
+
85
+ Copyright (c) 2012 Halan Pinheiro
86
+
87
+ MIT License
88
+
89
+ Permission is hereby granted, free of charge, to any person obtaining
90
+ a copy of this software and associated documentation files (the
91
+ "Software"), to deal in the Software without restriction, including
92
+ without limitation the rights to use, copy, modify, merge, publish,
93
+ distribute, sublicense, and/or sell copies of the Software, and to
94
+ permit persons to whom the Software is furnished to do so, subject to
95
+ the following conditions:
96
+
97
+ The above copyright notice and this permission notice shall be
98
+ included in all copies or substantial portions of the Software.
99
+
100
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
101
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
102
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
103
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
104
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
105
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
106
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,48 @@
1
+ class LuhnBase
2
+ def initialize number, options = {}
3
+ @mod, @base = 0, 0..100
4
+ @number = number.to_s.scan(/\d/).join
5
+ @base = options[:base] if options.has_key? :base
6
+ @mod = options[:mod] if options.has_key? :mod
7
+ end
8
+
9
+ def check_digit
10
+ sum / @mod
11
+ end
12
+
13
+ def * digits
14
+ digits.times.reduce(self) do |number, digit|
15
+ number += self.class.new(number, :base => @base, :mode => @mod).check_digit
16
+ end
17
+ end
18
+
19
+ def + digit
20
+ self.class.new(@number += digit.to_s.scan(/\d/).join, :base => @base, :mode => @mod)
21
+ end
22
+
23
+ def to_s
24
+ @number.to_s
25
+ end
26
+
27
+ def == other
28
+ self.to_s == other.to_s
29
+ end
30
+
31
+ protected
32
+ def bases
33
+ multipliers = ([*@base] * (@number.length/@base.count+1))[0..(@number.length-1)].reverse
34
+ end
35
+
36
+ def numbers_list
37
+ @number.chars.map &:to_i
38
+ end
39
+
40
+ def sum
41
+ bases.zip(numbers_list).reduce(0) {|total, n| total += before_sum(*n) }
42
+ end
43
+
44
+ def before_sum base, number
45
+ base * number
46
+ end
47
+ end
48
+
@@ -0,0 +1,20 @@
1
+ class Mod10 < LuhnBase
2
+ def initialize number, options = {}
3
+ super number, :base => [2, 1], :mod => 10
4
+ end
5
+
6
+ def check_digit
7
+ 10 - (sum % 10)
8
+ end
9
+
10
+ private
11
+ def before_sum base, number
12
+ super(base, number).to_s.chars.map(&:to_i).reduce(:+)
13
+ end
14
+ end
15
+
16
+ class String
17
+ def mod10 digits = 1, options = {}
18
+ (Mod10.new(self, options) * digits).to_s
19
+ end
20
+ end
@@ -0,0 +1,17 @@
1
+ class Mod11 < LuhnBase
2
+ def initialize number, options = {}
3
+ options[:mod] = 11
4
+ super number, {:base => 2..11}.merge(options)
5
+ end
6
+
7
+ def check_digit
8
+ ((10 * sum) % @mod) % 10
9
+ end
10
+ end
11
+
12
+ class String
13
+ def mod11 digits = 1, options = {}
14
+ (Mod11.new(self, options) * digits).to_s
15
+ end
16
+ end
17
+
data/lib/brid/ids/cnpj.rb CHANGED
@@ -13,8 +13,8 @@ module Brid
13
13
  end
14
14
 
15
15
  private
16
- def mod11 number
17
- Mod11.new(number, :base => 2..9)
16
+ def valid_number
17
+ sequential.mod11(check_digits_length, :base => 2..9)
18
18
  end
19
19
  end
20
20
  end
@@ -0,0 +1,37 @@
1
+ module Brid
2
+ class CredCard < GenericID
3
+ def initialize number
4
+ @number = clear_number(number)
5
+
6
+ raise ArgumentError.new "invalid number" unless (14..19).include? @number.length
7
+ end
8
+
9
+ def sequential
10
+ @sequential ||= begin
11
+ @number[/^(.*).$/, 1]
12
+ end
13
+ end
14
+
15
+ def association
16
+ return :dinners if @number.length == 14 and @number =~ /^3(0[0-5]|[68])/ # 300xxx-305xxx, 36xxxx, 38xxxx
17
+ return :amex if @number.length == 15 and @number =~ /^3[47]/ # 34xxxx, 37xxxx
18
+ return :visa if [13,16].include?(@number.length) and @number =~ /^4/ # 4xxxxx
19
+ return :master if @number.length == 16 and @number =~ /^5[1-5]/ # 51xxxx-55xxxx
20
+ return :discover if @number.length == 16 and @number =~ /^6011/ # 6011xx
21
+ return false
22
+ end
23
+
24
+ def invalid_sequential?
25
+ @invalid_sequential ||=begin
26
+ association != false
27
+ end
28
+ end
29
+
30
+ private
31
+ def valid_number
32
+ sequential.mod10
33
+ end
34
+ end
35
+ end
36
+
37
+ CredCard = Brid::CredCard if not defined? CredCard
@@ -41,12 +41,8 @@ class GenericID
41
41
  end
42
42
 
43
43
  protected
44
- def mod11 number
45
- Mod11.new(number)
46
- end
47
-
48
44
  def valid_number
49
- mod11(sequential) * check_digits_length
45
+ sequential.mod11(check_digits_length)
50
46
  end
51
47
 
52
48
  def clear_number number
data/lib/brid/ids/pis.rb CHANGED
@@ -20,12 +20,8 @@ module Brid
20
20
  end
21
21
 
22
22
  private
23
- def mod11 number
24
- Mod11.new(number, :base => 2..9)
25
- end
26
-
27
23
  def valid_number
28
- mod11(sequential) * 1
24
+ sequential.mod11(check_digits_length, :base => 2..9)
29
25
  end
30
26
  end
31
27
  end
@@ -1,11 +1,14 @@
1
1
  module Brid
2
2
  class TituloEleitor < GenericID
3
- def number_length; 10; end;
3
+ def number_length; 12; end;
4
4
 
5
5
  def initialize number
6
- @number = clear_number(number)
6
+ @number = clear_number(number).rjust number_length, '0'
7
+
8
+ raise ArgumentError.new "invalid number" if @number.length != number_length
7
9
  end
8
10
 
11
+
9
12
  def sequential
10
13
  @sequential ||= begin
11
14
  @number[/^(.*)....$/, 1]
@@ -33,9 +36,13 @@ module Brid
33
36
  end
34
37
 
35
38
  private
39
+ def mod number
40
+ Mod11.new number
41
+ end
42
+
36
43
  def valid_number
37
- first_check_digit = mod11(sequential).cdigi.to_s
38
- second_check_digit = mod11(uf_digit+first_check_digit).cdigi.to_s
44
+ first_check_digit = mod(sequential).check_digit.to_s
45
+ second_check_digit = mod(uf_digit+first_check_digit).check_digit.to_s
39
46
 
40
47
  sequential + uf_digit + first_check_digit + second_check_digit
41
48
  end
data/lib/brid/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Brid
2
- VERSION = "0.1.3"
2
+ VERSION = "0.2.0"
3
3
  end
data/lib/brid.rb CHANGED
@@ -1,11 +1,29 @@
1
- ['version.rb', 'mod11.rb', 'generic_id.rb'].each do |filename|
2
- require File.join(File.dirname(__FILE__), 'brid', filename)
3
- end
1
+ #requires
2
+
3
+ root_dir = File.join(File.dirname(__FILE__), 'brid')
4
4
 
5
- ['cpf.rb', 'cnpj.rb', 'titulo_eleitor.rb', 'pis.rb'].each do |filename|
6
- require File.join(File.dirname(__FILE__), 'brid', 'ids', filename)
5
+ require File.join(root_dir, 'version.rb')
6
+
7
+ #mod algorithms
8
+ [
9
+ 'luhn.rb',
10
+ 'mod10.rb',
11
+ 'mod11.rb'
12
+ ].each do |filename|
13
+ require File.join(root_dir, 'algorithms', filename)
7
14
  end
8
15
 
16
+ #ids and documents
17
+ [
18
+ 'generic_id',
19
+ 'cpf.rb',
20
+ 'cnpj.rb',
21
+ 'titulo_eleitor.rb',
22
+ 'pis.rb',
23
+ 'cred_card.rb'
24
+ ].each do |filename|
25
+ require File.join(root_dir, 'ids', filename)
26
+ end
9
27
 
10
28
  require File.join(File.dirname(__FILE__), 'brid', 'detector.rb')
11
29
 
@@ -0,0 +1,7 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'brid.rb')
2
+
3
+ describe Mod10 do
4
+ it { CredCard.new('411119876333502').should be_valid }
5
+ it { CredCard.new('211119876333501').should_not be_valid }
6
+
7
+ end
@@ -0,0 +1,7 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'brid.rb')
2
+
3
+ describe Mod10 do
4
+ it { Mod10.new('01230067896').check_digit.should == 3 }
5
+ it { Mod10.new('3011119876333').check_digit.should == 5 }
6
+ it { Mod10.new('2799811').check_digit.should == 1 }
7
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brid
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 1
9
- - 3
10
- version: 0.1.3
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Halan Pinheiro
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-07-18 00:00:00 Z
18
+ date: 2012-07-24 00:00:00 Z
19
19
  dependencies: []
20
20
 
21
21
  description: Brazilian identifications like CPF, CNPJ, Titulo de Eleitor
@@ -36,18 +36,23 @@ files:
36
36
  - Rakefile
37
37
  - brid.gemspec
38
38
  - lib/brid.rb
39
+ - lib/brid/algorithms/luhn.rb
40
+ - lib/brid/algorithms/mod10.rb
41
+ - lib/brid/algorithms/mod11.rb
39
42
  - lib/brid/detector.rb
40
- - lib/brid/generic_id.rb
41
43
  - lib/brid/ids/cnpj.rb
42
44
  - lib/brid/ids/cpf.rb
45
+ - lib/brid/ids/cred_card.rb
46
+ - lib/brid/ids/generic_id.rb
43
47
  - lib/brid/ids/pis.rb
44
48
  - lib/brid/ids/titulo_eleitor.rb
45
- - lib/brid/mod11.rb
46
49
  - lib/brid/version.rb
47
50
  - spec/brid_spec.rb
48
51
  - spec/cnpj_spec.rb
49
52
  - spec/cpf_spec.rb
53
+ - spec/cred_card_spec.rb
50
54
  - spec/generic_id_spec.rb
55
+ - spec/mod10_spec.rb
51
56
  - spec/mod11_spec.rb
52
57
  - spec/pis_spec.rb
53
58
  - spec/titulo_spec.rb
@@ -88,7 +93,9 @@ test_files:
88
93
  - spec/brid_spec.rb
89
94
  - spec/cnpj_spec.rb
90
95
  - spec/cpf_spec.rb
96
+ - spec/cred_card_spec.rb
91
97
  - spec/generic_id_spec.rb
98
+ - spec/mod10_spec.rb
92
99
  - spec/mod11_spec.rb
93
100
  - spec/pis_spec.rb
94
101
  - spec/titulo_spec.rb
data/lib/brid/mod11.rb DELETED
@@ -1,55 +0,0 @@
1
- class Mod11
2
- def initialize number, options = {}
3
- options = {:base => 2..11, :mod => 11}.merge options
4
-
5
- @number = number.to_s.scan(/\d/).join
6
- @base = options[:base]
7
- @mod = options[:mod]
8
- end
9
-
10
- def check_digit
11
- if block_given?
12
- yield sum, @mod
13
- else
14
- ((10 * sum) % @mod) % 10
15
- end
16
- end
17
-
18
- alias :cdigi :check_digit
19
-
20
- def * digits
21
- digits.times.reduce(self) do |number, digit|
22
- number += Mod11.new(number, :base => @base, :mode => @mod).cdigi
23
- end
24
- end
25
-
26
- alias :>> :*
27
-
28
- def + digit
29
- Mod11.new(@number += digit.to_s.scan(/\d/).join, :base => @base, :mode => @mod)
30
- end
31
-
32
- alias :<< :+
33
-
34
- def to_s
35
- @number.to_s
36
- end
37
-
38
- def == other
39
- self.to_s == other.to_s
40
- end
41
-
42
- private
43
- def bases
44
- multipliers = ([*@base] * (@number.length/@base.count+1))[0..(@number.length-1)].reverse
45
- end
46
-
47
- def numbers_list
48
- @number.chars.map &:to_i
49
- end
50
-
51
- def sum
52
- bases.zip(numbers_list).reduce(0) {|total, n| total += n[0] * n[1]}
53
- end
54
- end
55
-