custom_validations 0.0.1 → 1.0.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/lib/custom_validations/br_cnpj_validator.rb +72 -0
- data/lib/custom_validations/br_cpf_validator.rb +69 -0
- data/lib/custom_validations/br_postal_code_validator.rb +25 -0
- data/lib/custom_validations/client_side_validations_midleware/url.rb +38 -0
- data/lib/custom_validations/locale/en.yml +6 -1
- data/lib/custom_validations/url_validator.rb +52 -0
- data/lib/custom_validations/version.rb +1 -1
- data/lib/custom_validations.rb +11 -0
- data/vendor/assets/javascripts/rails.custom_validations.js +99 -2
- metadata +9 -4
@@ -0,0 +1,72 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
module Validations
|
3
|
+
|
4
|
+
|
5
|
+
class BrCnpjValidator < ActiveModel::EachValidator
|
6
|
+
BLACK_LIST = %w(00000000000000 11111111111111 22222222222222 33333333333333
|
7
|
+
44444444444444 55555555555555 66666666666666 77777777777777
|
8
|
+
88888888888888 99999999999999)
|
9
|
+
|
10
|
+
def validate_each(record, attribute, value)
|
11
|
+
return if value.to_s.blank? # it doesn't validate presence
|
12
|
+
record.errors.add(attribute, :br_cnpj, options) unless valid_cnpj?(value.to_s)
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid_cnpj? cnpj
|
16
|
+
|
17
|
+
begin
|
18
|
+
cnpj = (cnpj.is_a?(String) ? cnpj : cnpj.to_s)
|
19
|
+
rescue Exception => exc
|
20
|
+
return false
|
21
|
+
end
|
22
|
+
|
23
|
+
# could be 13 or 14 digits or with mask 99.999.999/9999-99
|
24
|
+
if cnpj !~ /^\d{13,14}$|\d{2}\.\d{3}\.\d{3}\/\d{4}\-\d{2}$/
|
25
|
+
return false
|
26
|
+
end
|
27
|
+
|
28
|
+
cnpj = cnpj.scan(/\d/).collect(&:to_i)
|
29
|
+
cnpj.unshift(0) if cnpj.length == 13
|
30
|
+
|
31
|
+
# filter black list
|
32
|
+
if BLACK_LIST.include? cnpj.join
|
33
|
+
return false
|
34
|
+
end
|
35
|
+
|
36
|
+
# calculate first digit
|
37
|
+
factor = [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]
|
38
|
+
|
39
|
+
sum = (0..11).inject(0) do |sum, i|
|
40
|
+
sum + cnpj[i] * factor[i]
|
41
|
+
end
|
42
|
+
|
43
|
+
result = sum % 11
|
44
|
+
result = result < 2 ? 0 : 11 - result
|
45
|
+
|
46
|
+
if result != cnpj[12]
|
47
|
+
return false
|
48
|
+
end
|
49
|
+
|
50
|
+
# calculate second digit
|
51
|
+
factor.unshift 6
|
52
|
+
|
53
|
+
sum = (0..12).inject(0) do |sum, i|
|
54
|
+
sum + cnpj[i] * factor[i]
|
55
|
+
end
|
56
|
+
|
57
|
+
result = sum % 11
|
58
|
+
result = result < 2 ? 0 : 11 - result
|
59
|
+
|
60
|
+
result == cnpj[13]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
module HelperMethods
|
66
|
+
def validates_br_cnpj_of(*attr_names)
|
67
|
+
validates_with BrCnpjValidator, _merge_attributes(attr_names)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
module Validations
|
3
|
+
|
4
|
+
|
5
|
+
class BrCpfValidator < ActiveModel::EachValidator
|
6
|
+
BLACK_LIST = %w(12345678909 11111111111 22222222222 33333333333 44444444444
|
7
|
+
55555555555 66666666666 77777777777 88888888888 99999999999
|
8
|
+
00000000000)
|
9
|
+
|
10
|
+
def validate_each(record, attribute, value)
|
11
|
+
return if value.to_s.blank? # it doesn't validate presence
|
12
|
+
record.errors.add(attribute, :br_cpf, options) unless valid_cpf?(value.to_s)
|
13
|
+
end
|
14
|
+
|
15
|
+
def valid_cpf? cpf
|
16
|
+
begin
|
17
|
+
cpf = (cpf.is_a?(String) ? cpf : cpf.to_s)
|
18
|
+
rescue
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
|
22
|
+
# could be 10 or 11 digits or with mask 999.999.999-99
|
23
|
+
if cpf !~ /^\d{10,11}$|\d{3}\.\d{3}\.\d{3}-\d{2}$/
|
24
|
+
return false
|
25
|
+
end
|
26
|
+
|
27
|
+
cpf = cpf.scan(/\d/).collect(&:to_i)
|
28
|
+
cpf.unshift(0) if cpf.length == 10
|
29
|
+
|
30
|
+
# filter black list
|
31
|
+
if BLACK_LIST.include? cpf.join
|
32
|
+
return false
|
33
|
+
end
|
34
|
+
|
35
|
+
# calculate first digit
|
36
|
+
sum = (0..8).inject(0) do |sum, i|
|
37
|
+
sum + cpf[i] * (10 - i)
|
38
|
+
end
|
39
|
+
|
40
|
+
result = sum % 11
|
41
|
+
result = result < 2 ? 0 : 11 - result
|
42
|
+
|
43
|
+
if result != cpf[9]
|
44
|
+
return false
|
45
|
+
end
|
46
|
+
|
47
|
+
# calculate second digit
|
48
|
+
sum = (0..8).inject(0) do |sum, i|
|
49
|
+
sum + cpf[i] * (11 - i)
|
50
|
+
end
|
51
|
+
|
52
|
+
sum += cpf[9] * 2
|
53
|
+
|
54
|
+
result = sum % 11
|
55
|
+
result = result < 2 ? 0 : 11 - result
|
56
|
+
|
57
|
+
result == cpf[10]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
module HelperMethods
|
63
|
+
def validates_br_cpf_of(*attr_names)
|
64
|
+
validates_with BrCpfValidator, _merge_attributes(attr_names)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
module Validations
|
3
|
+
|
4
|
+
|
5
|
+
class BrPostalCodeValidator < ActiveModel::EachValidator
|
6
|
+
|
7
|
+
REGEX = /^\d{5}\-?\d{3}$/
|
8
|
+
|
9
|
+
def validate_each(record, attribute, value)
|
10
|
+
return if value.to_s.blank? # it doesn't validate presence
|
11
|
+
unless value.to_s =~ REGEX
|
12
|
+
record.errors.add(attribute, :br_postal_code, options)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
module HelperMethods
|
19
|
+
def validates_br_postal_code_of(*attr_names)
|
20
|
+
validates_with BrPostalCodeValidator, _merge_attributes(attr_names)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module ClientSideValidations::Middleware
|
2
|
+
class Url < Base
|
3
|
+
|
4
|
+
class URLValidationClass
|
5
|
+
include ActiveModel::Validations
|
6
|
+
attr_accessor :url
|
7
|
+
validates_url_of :url
|
8
|
+
end
|
9
|
+
|
10
|
+
class URLAsHostValidationClass
|
11
|
+
include ActiveModel::Validations
|
12
|
+
attr_accessor :url
|
13
|
+
validates_url_of :url, as_host: true
|
14
|
+
end
|
15
|
+
|
16
|
+
def response
|
17
|
+
|
18
|
+
if request.params[:as_host] == 'true'
|
19
|
+
obj = URLAsHostValidationClass.new
|
20
|
+
else
|
21
|
+
obj = URLValidationClass.new
|
22
|
+
end
|
23
|
+
|
24
|
+
obj.url = request.params[:value]
|
25
|
+
obj.valid?
|
26
|
+
|
27
|
+
if obj.errors.has_key? :url
|
28
|
+
self.status = 400
|
29
|
+
self.body = {message: obj.errors[:url].first}.to_json
|
30
|
+
else
|
31
|
+
self.status = 200
|
32
|
+
self.body = 'true'
|
33
|
+
end
|
34
|
+
|
35
|
+
super
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -3,4 +3,9 @@ en:
|
|
3
3
|
# The values :model, :attribute and :value are always available for interpolation
|
4
4
|
# The value :count is available when applicable. Can be used for pluralization.
|
5
5
|
messages:
|
6
|
-
|
6
|
+
br_cpf: "is not a valid brazilian CPF"
|
7
|
+
br_cnpj: "is not a valid brazilian CNPJ"
|
8
|
+
br_postal_code: "is not a valid brazilian postal code"
|
9
|
+
email: "is not an email address"
|
10
|
+
url: "is an invalid url"
|
11
|
+
url_as_host: "is an invalid url (specify only the domain, without http and /)"
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
module Validations
|
3
|
+
|
4
|
+
|
5
|
+
class UrlValidator < ActiveModel::EachValidator
|
6
|
+
|
7
|
+
def initialize(options)
|
8
|
+
options[:as_host] = false if options[:as_host].blank?
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def validate_each(record, attribute, value)
|
13
|
+
return if value.to_s.blank? # it doesn't validate presence
|
14
|
+
|
15
|
+
valid = begin
|
16
|
+
uri = URI.parse(value)
|
17
|
+
uri.kind_of?(URI::HTTP) and !uri.host.to_s.match /^\./
|
18
|
+
rescue URI::InvalidURIError
|
19
|
+
false
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
if options[:as_host] and uri.kind_of?(URI::Generic)
|
24
|
+
if uri.scheme.present? or value.match(/\?|\/|\:|^\s*\./)
|
25
|
+
record.errors.add(attribute, :url_as_host, options)
|
26
|
+
end
|
27
|
+
|
28
|
+
elsif !valid
|
29
|
+
record.errors.add(attribute, :url, options)
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
module HelperMethods
|
37
|
+
def validates_url_of(*attr_names)
|
38
|
+
validates_with UrlValidator, _merge_attributes(attr_names)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
# URL validation is very difficult to perform. There are several points of view
|
47
|
+
# on what is a valid URL and what URLs should be considered in validations.
|
48
|
+
# We will do a pragmatic validation here. If the URL is parsable, then it's valid.
|
49
|
+
# See the tests to learn what we have considered as valid and invalid urls.
|
50
|
+
# Nice discussion here:
|
51
|
+
# http://stackoverflow.com/questions/7167895/whats-a-good-way-to-validate-links-urls-in-rails-3
|
52
|
+
#
|
data/lib/custom_validations.rb
CHANGED
@@ -4,7 +4,18 @@ require 'active_model'
|
|
4
4
|
# Require base code
|
5
5
|
require 'custom_validations/version'
|
6
6
|
require 'custom_validations/engine'
|
7
|
+
|
8
|
+
# Require validators
|
9
|
+
require 'custom_validations/br_postal_code_validator'
|
10
|
+
require 'custom_validations/br_cpf_validator'
|
11
|
+
require 'custom_validations/br_cnpj_validator'
|
7
12
|
require 'custom_validations/email_validator'
|
13
|
+
require 'custom_validations/url_validator'
|
14
|
+
|
15
|
+
# Require ClientSideValidations midlewares
|
16
|
+
if defined?(ClientSideValidations)
|
17
|
+
require 'custom_validations/client_side_validations_midleware/url'
|
18
|
+
end
|
8
19
|
|
9
20
|
# Load translations
|
10
21
|
require 'active_support/i18n'
|
@@ -12,12 +12,91 @@
|
|
12
12
|
(function() {
|
13
13
|
|
14
14
|
jQuery(function() {
|
15
|
-
var is_blank, validators;
|
15
|
+
var is_blank, validates_cnpj, validates_cpf, validators;
|
16
16
|
is_blank = function(element) {
|
17
17
|
return /^\s*$/.test(element.val() || '');
|
18
18
|
};
|
19
|
+
validates_cpf = function(cpf) {
|
20
|
+
var i, result, sum;
|
21
|
+
cpf = $.trim(cpf).replace(/\.|\-/g, '').split('');
|
22
|
+
sum = 0;
|
23
|
+
i = 10;
|
24
|
+
$.each(cpf.slice(0, 9), function() {
|
25
|
+
sum += parseInt(this) * i;
|
26
|
+
return i -= 1;
|
27
|
+
});
|
28
|
+
result = sum % 11;
|
29
|
+
if (result < 2) {
|
30
|
+
result = 0;
|
31
|
+
} else {
|
32
|
+
result = 11 - result;
|
33
|
+
}
|
34
|
+
if (result !== parseInt(cpf[9])) {
|
35
|
+
return false;
|
36
|
+
}
|
37
|
+
sum = 0;
|
38
|
+
i = 11;
|
39
|
+
$.each(cpf.slice(0, 10), function() {
|
40
|
+
sum += parseInt(this) * i;
|
41
|
+
return i -= 1;
|
42
|
+
});
|
43
|
+
result = sum % 11;
|
44
|
+
if (result < 2) {
|
45
|
+
result = 0;
|
46
|
+
} else {
|
47
|
+
result = 11 - result;
|
48
|
+
}
|
49
|
+
return result === parseInt(cpf[10]);
|
50
|
+
};
|
51
|
+
validates_cnpj = function(cnpj) {
|
52
|
+
var sum;
|
53
|
+
cnpj = $.trim(cnpj).replace(/[^0-9]/g, '').split('');
|
54
|
+
sum = 5 * parseInt(cnpj[0]) + 4 * parseInt(cnpj[1]) + 3 * parseInt(cnpj[2]) + 2 * parseInt(cnpj[3]);
|
55
|
+
sum += 9 * parseInt(cnpj[4]) + 8 * parseInt(cnpj[5]) + 7 * parseInt(cnpj[6]) + 6 * parseInt(cnpj[7]);
|
56
|
+
sum += 5 * parseInt(cnpj[8]) + 4 * parseInt(cnpj[9]) + 3 * parseInt(cnpj[10]) + 2 * parseInt(cnpj[11]);
|
57
|
+
sum = 11 - parseInt(sum % 11);
|
58
|
+
if (sum >= 10) {
|
59
|
+
sum = 0;
|
60
|
+
}
|
61
|
+
if (sum !== parseInt(cnpj[12])) {
|
62
|
+
return false;
|
63
|
+
}
|
64
|
+
sum = 6 * parseInt(cnpj[0]) + 5 * parseInt(cnpj[1]) + 4 * parseInt(cnpj[2]) + 3 * parseInt(cnpj[3]);
|
65
|
+
sum += 2 * parseInt(cnpj[4]) + 9 * parseInt(cnpj[5]) + 8 * parseInt(cnpj[6]) + 7 * parseInt(cnpj[7]);
|
66
|
+
sum += 6 * parseInt(cnpj[8]) + 5 * parseInt(cnpj[9]) + 4 * parseInt(cnpj[10]) + 3 * parseInt(cnpj[11]);
|
67
|
+
sum += 2 * parseInt(cnpj[12]);
|
68
|
+
sum = 11 - parseInt(sum % 11);
|
69
|
+
if (sum >= 10) {
|
70
|
+
sum = 0;
|
71
|
+
}
|
72
|
+
return sum === parseInt(cnpj[13]);
|
73
|
+
};
|
19
74
|
validators = window.ClientSideValidations.validators;
|
20
|
-
|
75
|
+
validators.local['br_cpf'] = function(element, options) {
|
76
|
+
if (is_blank(element)) {
|
77
|
+
return;
|
78
|
+
}
|
79
|
+
if (!validates_cpf(element.val())) {
|
80
|
+
return options.message;
|
81
|
+
}
|
82
|
+
};
|
83
|
+
validators.local['br_cnpj'] = function(element, options) {
|
84
|
+
if (is_blank(element)) {
|
85
|
+
return;
|
86
|
+
}
|
87
|
+
if (!validates_cnpj(element.val())) {
|
88
|
+
return options.message;
|
89
|
+
}
|
90
|
+
};
|
91
|
+
validators.local['br_postal_code'] = function(element, options) {
|
92
|
+
if (is_blank(element)) {
|
93
|
+
return;
|
94
|
+
}
|
95
|
+
if (!/^\d{5}\-?\d{3}$/.test(element.val())) {
|
96
|
+
return options.message;
|
97
|
+
}
|
98
|
+
};
|
99
|
+
validators.local['email'] = function(element, options) {
|
21
100
|
if (is_blank(element)) {
|
22
101
|
return;
|
23
102
|
}
|
@@ -25,6 +104,24 @@
|
|
25
104
|
return options.message;
|
26
105
|
}
|
27
106
|
};
|
107
|
+
return validators.remote['url'] = function(element, options) {
|
108
|
+
var response;
|
109
|
+
if (is_blank(element)) {
|
110
|
+
return;
|
111
|
+
}
|
112
|
+
response = $.ajax({
|
113
|
+
dataType: 'json',
|
114
|
+
url: '/validators/url',
|
115
|
+
data: {
|
116
|
+
value: element.val(),
|
117
|
+
as_host: options.as_host
|
118
|
+
},
|
119
|
+
async: false
|
120
|
+
});
|
121
|
+
if (response.status === 400) {
|
122
|
+
return JSON.parse(response.responseText)['message'];
|
123
|
+
}
|
124
|
+
};
|
28
125
|
});
|
29
126
|
|
30
127
|
}).call(this);
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: custom_validations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-02-
|
12
|
+
date: 2013-02-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -52,9 +52,14 @@ extra_rdoc_files: []
|
|
52
52
|
files:
|
53
53
|
- custom_validations.gemspec
|
54
54
|
- lib/custom_validations.rb
|
55
|
+
- lib/custom_validations/br_cnpj_validator.rb
|
56
|
+
- lib/custom_validations/br_cpf_validator.rb
|
57
|
+
- lib/custom_validations/br_postal_code_validator.rb
|
58
|
+
- lib/custom_validations/client_side_validations_midleware/url.rb
|
55
59
|
- lib/custom_validations/email_validator.rb
|
56
60
|
- lib/custom_validations/engine.rb
|
57
61
|
- lib/custom_validations/locale/en.yml
|
62
|
+
- lib/custom_validations/url_validator.rb
|
58
63
|
- lib/custom_validations/version.rb
|
59
64
|
- vendor/assets/javascripts/rails.custom_validations.js
|
60
65
|
homepage: https://github.com/kauplus/custom_validations
|
@@ -71,7 +76,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
71
76
|
version: '0'
|
72
77
|
segments:
|
73
78
|
- 0
|
74
|
-
hash:
|
79
|
+
hash: 2904212743417297461
|
75
80
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
76
81
|
none: false
|
77
82
|
requirements:
|
@@ -80,7 +85,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
85
|
version: '0'
|
81
86
|
segments:
|
82
87
|
- 0
|
83
|
-
hash:
|
88
|
+
hash: 2904212743417297461
|
84
89
|
requirements: []
|
85
90
|
rubyforge_project:
|
86
91
|
rubygems_version: 1.8.24
|