synapses-validators 0.1.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.
@@ -0,0 +1,3 @@
1
+ === 0.1.0 :: 2012-05-15
2
+
3
+ * First public release with CPF, CNPJ and Email Validations
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+ gemspec
3
+
data/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ Synapses-Validators is gem created by Tiago Machado and João Lucas for implement additional validations for Synapses Group.
2
+
3
+ Most part of CPF/CNPJ validations is available at https://github.com/tapajos/brazilian-rails
4
+
5
+
6
+ The MIT License
7
+
8
+ Permission is hereby granted, free of charge, to any person
9
+ obtaining a copy of this software and associated documentation
10
+ files (the "Software"), to deal in the Software without
11
+ restriction, including without limitation the rights to use,
12
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
13
+ copies of the Software, and to permit persons to whom the
14
+ Software is furnished to do so, subject to the following
15
+ conditions:
16
+
17
+ The above copyright notice and this permission notice shall be
18
+ included in all copies or substantial portions of the Software.
19
+
20
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27
+ OTHER DEALINGS IN THE SOFTWARE.
28
+
@@ -0,0 +1,74 @@
1
+ # Synapses Validators
2
+
3
+ ## Authors
4
+
5
+ * Tiago Machado (tiago@synapses.com.br)
6
+ * João Lucas (joaolucas@synapses.com.br)
7
+
8
+ Based on Brazilian Rails (https://github.com/tapajos/brazilian-rails)
9
+
10
+ ## How to use
11
+
12
+ Include "synapses-validators" in yor gemfile.
13
+
14
+ ```ruby
15
+ gem 'synapses-validators'
16
+ ```
17
+
18
+ Go to your models, and set your validators.
19
+
20
+ ### CPF
21
+
22
+ ```ruby
23
+ validates :cpf, :presence => true, :uniqueness => true, :cpf => true, :if => :is_person_br?
24
+ ```
25
+
26
+ Or
27
+
28
+ ```ruby
29
+ act_as_cpf :cpf
30
+ ```
31
+
32
+ ### CNPJ
33
+
34
+ ```ruby
35
+ validates :cnpj, :presence => true, :uniqueness => true, :cnpj => true, :if => :is_business_br?
36
+ ```
37
+
38
+ Or
39
+
40
+ ```ruby
41
+ act_as_cnpj :cpf
42
+ ```
43
+
44
+ ### Email
45
+
46
+ ```ruby
47
+ validates :email,
48
+ :presence => true,
49
+ :uniqueness => true,
50
+ :length => {:within => 5..50},
51
+ :email_format => true
52
+ ```
53
+
54
+
55
+ ### I18n
56
+
57
+ The error messages is localized. So, you must have this lines in your locale files:
58
+
59
+ ```ruby
60
+ activerecord:
61
+ errors:
62
+ messages:
63
+ invalid: inválido
64
+ not_formatted: não está no formato correto
65
+ ```
66
+
67
+ ### TODO
68
+
69
+ * Implement tests.
70
+
71
+
72
+ ## License
73
+
74
+ Synapses Validators is licensed for use under the terms of the MIT License.
@@ -0,0 +1,2 @@
1
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
2
+ task :default => :spec
@@ -0,0 +1,6 @@
1
+ # -*- encoding : utf-8 -*-
2
+ # Synapses Group
3
+
4
+ class Cnpj
5
+ include CpfCnpj
6
+ end
@@ -0,0 +1,9 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Synapses Group
3
+
4
+ class CnpjValidator < ActiveModel::EachValidator
5
+ def validate_each(record, attribute, value)
6
+ return if value.nil?
7
+ record.errors.add attribute, :invalid unless Cnpj.new(value).valid?
8
+ end
9
+ end
@@ -0,0 +1,6 @@
1
+ # -*- encoding : utf-8 -*-
2
+ # Synapses Group
3
+
4
+ class Cpf
5
+ include CpfCnpj
6
+ end
@@ -0,0 +1,89 @@
1
+ # -*- encoding : utf-8 -*-
2
+ # Synapses Group
3
+
4
+ module CpfCnpj
5
+
6
+ attr_reader :number
7
+
8
+ def initialize(number)
9
+ @number = number
10
+ @match = self.instance_of?(Cpf) ? @number =~ CPF_REGEX : @number =~ CNPJ_REGEX
11
+ @plain_number = $1
12
+ @verification_number = $2
13
+ @number = (@match ? format_number! : nil)
14
+ end
15
+
16
+ def to_s
17
+ @number || ""
18
+ end
19
+
20
+ def ==(value)
21
+ self.number == value.number
22
+ end
23
+
24
+ def valid?
25
+ return false unless @match
26
+ verify_number
27
+ end
28
+
29
+ private
30
+ DIVISOR = 11
31
+
32
+ CPF_LENGTH = 11
33
+ CPF_REGEX = /^(\d{3}\.?\d{3}\.?\d{3})-?(\d{2})$/
34
+ CPF_ALGS_1 = [10, 9, 8, 7, 6, 5, 4, 3, 2]
35
+ CPF_ALGS_2 = [11, 10, 9, 8, 7, 6, 5, 4, 3, 2]
36
+
37
+ CNPJ_LENGTH = 14
38
+ CNPJ_REGEX = /^(\d{2}\.?\d{3}\.?\d{3}\/?\d{4})-?(\d{2})$/ # <= 11.222.333/0001-XX
39
+ CNPJ_ALGS_1 = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
40
+ CNPJ_ALGS_2 = [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
41
+
42
+
43
+ def verify_number
44
+ unmasked_number = @number.gsub(/[\.\/-]/, "")
45
+ if self.instance_of? Cpf
46
+ return false if unmasked_number.length != 11
47
+ elsif self.instance_of? Cnpj
48
+ return false if unmasked_number.length != 14
49
+ end
50
+ return false if unmasked_number.scan(/\d/).uniq.length == 1
51
+ first_digit = first_verification_digit
52
+ second_digit = second_verification_digit(first_digit)
53
+ verif = first_digit + second_digit
54
+ verif == @verification_number
55
+ end
56
+
57
+ def multiply_and_sum(algs, number_str)
58
+ multiplied = []
59
+ number_str.scan(/\d{1}/).each_with_index { |e, i| multiplied[i] = e.to_i * algs[i] }
60
+ multiplied.inject { |s,e| s + e }
61
+ end
62
+
63
+ def verification_digit(rest)
64
+ rest < 2 ? 0 : DIVISOR - rest
65
+ end
66
+
67
+ def first_verification_digit
68
+ array = self.instance_of?(Cpf) ? CPF_ALGS_1 : CNPJ_ALGS_1
69
+ sum = multiply_and_sum(array, @plain_number)
70
+ verification_digit(sum%DIVISOR).to_s
71
+ end
72
+
73
+ def second_verification_digit(first_digit)
74
+ array = self.instance_of?(Cpf) ? CPF_ALGS_2 : CNPJ_ALGS_2
75
+ sum = multiply_and_sum(array, @plain_number + first_digit)
76
+ verification_digit(sum%DIVISOR).to_s
77
+ end
78
+
79
+ def format_number!
80
+ if self.instance_of? Cpf
81
+ @number =~ /(\d{3})\.?(\d{3})\.?(\d{3})-?(\d{2})/
82
+ @number = "#{$1}.#{$2}.#{$3}-#{$4}"
83
+ else
84
+ @number =~ /(\d{2})\.?(\d{3})\.?(\d{3})\/?(\d{4})-?(\d{2})/
85
+ @number = "#{$1}.#{$2}.#{$3}/#{$4}-#{$5}"
86
+ end
87
+ end
88
+
89
+ end
@@ -0,0 +1,63 @@
1
+ # -*- encoding : utf-8 -*-
2
+ # Synapses Group
3
+
4
+ module CpfCnpjActiveRecord
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ end
8
+ module ClassMethods
9
+ def act_as_cpf(*args)
10
+ init(args, 'Cpf')
11
+ end
12
+
13
+ def act_as_cnpj(*args)
14
+ init(args, 'Cnpj')
15
+ end
16
+
17
+ def init(args, klass)
18
+ unless args.size.zero?
19
+ args.each do |name|
20
+ add_composed_class(name, klass)
21
+ module_eval create_code(name.to_s, klass)
22
+ end
23
+ end
24
+ end
25
+
26
+ def add_composed_class(name, klass)
27
+ options = {:class_name => klass, :mapping => [name.to_s, "number"], :allow_nil => true}
28
+ constructor = Proc.new { |number| eval(klass).new(number) }
29
+ converter = Proc.new { |value| eval(klass).new(value) }
30
+ begin
31
+ composed_of name, options.merge( { :constructor => constructor, :converter => converter } )
32
+ rescue Exception
33
+ composed_of name, options { eval(klass).new(name[:number]) }
34
+ end
35
+ end
36
+
37
+ def create_code(name, klass)
38
+ str = <<-CODE
39
+ validate :#{name}_valid?
40
+ def #{name}_valid?
41
+ value = read_attribute('#{name}')
42
+ if !value.nil? && value.strip != '' && !#{name}.nil? && !#{name}.valid?
43
+ self.errors.add('#{name}', :invalid)
44
+ end
45
+ end
46
+ def #{name}=(value)
47
+ if value.blank?
48
+ write_attribute('#{name}', nil)
49
+ elsif value.kind_of?(#{eval(klass)})
50
+ write_attribute('#{name}', value.number)
51
+ else
52
+ begin
53
+ c = #{eval(klass)}.new(value)
54
+ c.valid? ? write_attribute('#{name}', c.number) : write_attribute('#{name}', value)
55
+ rescue
56
+ @#{name} = value
57
+ end
58
+ end
59
+ end
60
+ CODE
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,9 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Synapses Group
3
+
4
+ class CpfValidator < ActiveModel::EachValidator
5
+ def validate_each(record, attribute, value)
6
+ return if value.nil?
7
+ record.errors.add attribute, :invalid unless Cpf.new(value).valid?
8
+ end
9
+ end
@@ -0,0 +1,16 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Synapses Group
3
+
4
+ class EmailFormatValidator < ActiveModel::EachValidator
5
+ def validate_each(object, attribute, value)
6
+ unless EmailFormatValidator::validate_email(value)
7
+ object.errors.add attribute, :not_formatted
8
+ end
9
+ end
10
+
11
+ def self.validate_email(email)
12
+ email =~ /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
13
+ end
14
+ end
15
+
16
+
@@ -0,0 +1,20 @@
1
+ # -*- encoding : utf-8 -*-
2
+ $:.unshift(File.dirname(__FILE__)) unless
3
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
4
+
5
+ %w(cpf_cnpj cnpj cpf cpf_cnpj_activerecord cnpj_validator cpf_validator).each {
6
+ |req| require File.dirname(__FILE__) + "/cpf_cnpj/#{req}"
7
+ }
8
+
9
+ %w(email_format_validator).each {
10
+ |req| require File.dirname(__FILE__) + "/email/#{req}"
11
+ }
12
+
13
+ %w(rubygems active_record active_support).each {
14
+ |req| require req
15
+ }
16
+
17
+ ActiveRecord::Base.send :include, CpfCnpjActiveRecord
18
+
19
+ module SynapsesValidators
20
+ end
@@ -0,0 +1,15 @@
1
+ $gemspec = Gem::Specification.new do |s|
2
+ s.name = 'synapses-validators'
3
+ s.version = '0.1.0'
4
+ s.summary = "Implements additional validations required to Synapses Group"
5
+ s.description = "Adds CPF, CNPJ and Email validation"
6
+ s.authors = ["Synapses Group"]
7
+ s.email = ["tiago@synapses.com.br"]
8
+
9
+ s.files = [
10
+ "CHANGELOG", "LICENSE", "README.md", "Rakefile",
11
+ "lib/**/*.rb", "Gemfile", "synapses-validators.gemspec"
12
+ ].map{|p| Dir[p]}.flatten
13
+
14
+ s.homepage = 'https://github.com/synapsesgroup/synapses-validators'
15
+ end
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: synapses-validators
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Synapses Group
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-15 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Adds CPF, CNPJ and Email validation
15
+ email:
16
+ - tiago@synapses.com.br
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - CHANGELOG
22
+ - LICENSE
23
+ - README.md
24
+ - Rakefile
25
+ - lib/cpf_cnpj/cnpj.rb
26
+ - lib/cpf_cnpj/cnpj_validator.rb
27
+ - lib/cpf_cnpj/cpf.rb
28
+ - lib/cpf_cnpj/cpf_cnpj.rb
29
+ - lib/cpf_cnpj/cpf_cnpj_activerecord.rb
30
+ - lib/cpf_cnpj/cpf_validator.rb
31
+ - lib/email/email_format_validator.rb
32
+ - lib/synapses-validators.rb
33
+ - Gemfile
34
+ - synapses-validators.gemspec
35
+ homepage: https://github.com/synapsesgroup/synapses-validators
36
+ licenses: []
37
+ post_install_message:
38
+ rdoc_options: []
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ none: false
49
+ requirements:
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ requirements: []
54
+ rubyforge_project:
55
+ rubygems_version: 1.8.24
56
+ signing_key:
57
+ specification_version: 3
58
+ summary: Implements additional validations required to Synapses Group
59
+ test_files: []