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.
@@ -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
- email: "not an email address"
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
+ #
@@ -1,3 +1,3 @@
1
1
  module CustomValidations
2
- VERSION = '0.0.1'
2
+ VERSION = '1.0.0'
3
3
  end
@@ -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
- return validators.local['email'] = function(element, options) {
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.1
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-24 00:00:00.000000000 Z
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: -2993300514968256952
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: -2993300514968256952
88
+ hash: 2904212743417297461
84
89
  requirements: []
85
90
  rubyforge_project:
86
91
  rubygems_version: 1.8.24