activevalidators 2.1.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: de64a7aa6feb36cf4d57acc13a620b8b26ad7b14
4
- data.tar.gz: e9983a0c5dba7483e26f6594e704f0e01468c872
3
+ metadata.gz: 50acb6e676e5e32669572b48f94484fedef7fb82
4
+ data.tar.gz: ebef42c4c60c751e58305630094717d65e249930
5
5
  SHA512:
6
- metadata.gz: d5df00615461a33d2c4a71ee15cddbc99e69cdff6759421dfd4289b913b2b1b51c6481d27feb42a8f821a9a55b07c9615293583ab9792ba8679946767176d042
7
- data.tar.gz: 5908af5ffe6643ba5c8df5b981254c5652964833e1af5f8ee61acfc9ac493ead71f957ce5866c9a789ac417d357b18a48936e5185da4c7a9c164eaf967d491c3
6
+ metadata.gz: 2e1223d430d4cde1ef2918f77d22373e45f6652e8a12262e88678357faf6a90a1afe19958603fa18a597e8a2fc08e53f8615cdc3a1462324496fbed6a796e7a4
7
+ data.tar.gz: 4564020ef5cf74254bed1a98b25028c1cd8001b3d7432a15787402cab83e57886dc42c69b9367c14873a5b8146c7454eb986b4ef325b006777741e305d07fc58
data/.gitignore CHANGED
@@ -2,3 +2,6 @@
2
2
  *.gem
3
3
  *.rbc
4
4
  Gemfile.lock
5
+ .ruby-gemset
6
+ .ruby-version
7
+ .idea
@@ -3,6 +3,9 @@ rvm:
3
3
  - 1.9.3
4
4
  - 2.1.0
5
5
  - jruby-19mode
6
- - rbx
6
+ - rbx-2
7
7
  - ruby-head
8
8
  - jruby-head
9
+ matrix:
10
+ allow_failures:
11
+ - rvm: jruby-head
@@ -0,0 +1,190 @@
1
+ # UNRELEASED (3.0.1)
2
+
3
+ ## FEATURES
4
+
5
+ * Remove default requiring
6
+
7
+ # 3.0.0
8
+
9
+ *TL;DR : deprecating default require's and introduced a way to activate them independently.*
10
+
11
+ ## BREAKING CHANGES for the 3.x versions
12
+
13
+ * Validators should be manually required using `ActiveValidators.activate`. See README for details on how to use it.
14
+
15
+ ## FEATURES
16
+
17
+ * Require all the validators by default until 3.0.1
18
+ * EAN13 barcode validation
19
+ * NINO validation (UK)
20
+ * SIN validation (Canada)
21
+ * SSN (Social Security Number) validation (USA)
22
+
23
+ # 2.1.0
24
+
25
+ * Loosen up the dependency on phony
26
+ * Cleaning up the test helper
27
+ * Some requires were obsolete and loading nothing.
28
+ * .travis.yml : Rework the list of supported Rubies
29
+ * Credit\_card\_validator : Change the luhn algorithm & code cleanup
30
+ * Email\_validator.rb : Extract method in the email validator
31
+ * Update .travis.yml
32
+ * Remove Rubies < 1.9.3
33
+ * Add activesupport requires needed to make tests pass
34
+ * Add tests for IPAddr
35
+ * Cast ip value to string before using string methods
36
+ * Countries (from 0.8.4 to 0.9.2), phony (from 1.7.12 to 1.9.0)
37
+ * Fix: :rubygems is deprecated because HTTP requests are insecure
38
+ * SIREN Validator
39
+
40
+ # 2.0.2
41
+
42
+ * Postal code for the Cayman Islands
43
+ * Add option to email validator to allow quick validation via a lambda function
44
+ * Rework the postal code validator to support 1.8 again.
45
+ * Convert to 1.8 syntax and reindent.
46
+
47
+ # 2.0.1
48
+
49
+ * Replace ^,$ with \A,\z in TrackingNumberValidator
50
+ * Like the fixes before, including all tests.
51
+ * Prevent string injection in postal codes via \A,\z
52
+ * Just corrected the regular expression to use \A and \z instead of ^ and $.
53
+ * Ensure to use \A and \z in twitter regexps
54
+ * Regular expressions for the twitter usernames.
55
+ * Wrap URL regexp with \A and \z
56
+ * Also added a test case to ensure this is not possible.
57
+
58
+ # 2.0.0
59
+
60
+ * Clean a bit the email validations' tests.
61
+ * Fix: phone validator accepts custom message
62
+ * Email validator accept only full address
63
+ * :strict changed to :only\_address due to :strict is registered word
64
+ * Fixed travis for 1.9x
65
+ * Fixes phone validator
66
+ * Tests for international format
67
+ * Phone validation dependency on Phony gem
68
+ * Transform @ as word character
69
+ * Added postal code validators by geonames.info
70
+ * Replace custom url regexp with URI.regexp
71
+
72
+ # 1.9.0
73
+
74
+ * Update the email validation example
75
+ * (Feature) Added strict email notion for email\_validator
76
+ * Uenamed duplicate test cases
77
+ * Umprove the email validator to be more restrictive
78
+ * Update .travis.yml
79
+
80
+ # 1.8.1
81
+
82
+ * Remove active\_record dependency
83
+ * Add Manuel to the list of contributors
84
+ * Improve the README a bit
85
+
86
+ # 1.8.0
87
+
88
+ * TrackingNumberValidator: fix in the USPS computation.
89
+ * Tests: removed turn because it was failing everywhere but on 1.9.x.
90
+ * PostalCodeValidator: Added Portuguese postal-code format.
91
+ * Remove turn.
92
+ * Corrected example of use of the postal code validator.
93
+ * Added a new option country\_method allowing the country to be obtained by calling a method of the record. Also added support for string in option 'contry'.
94
+ * Added Portuguese postal-code format.
95
+ * Properly handle checksums of '0' in usps mod10.
96
+ * Current implementation returns 10, which does not equal 0.
97
+ * Simplify the test and make sure Ruby 1.9x stop complaining
98
+
99
+ # 1.7.1
100
+
101
+ * Fix the usage of date\_validator
102
+
103
+ # 1.7.0
104
+
105
+ * Update the URL regex to support Basic Auth and port numbers
106
+ * check value#blank? in validations
107
+ * Fix the link to Travis
108
+ * Implemented :credit\_card => true
109
+ * Github's caching the build status image, so using https from now on.
110
+ * Let's require all the validations
111
+
112
+ # 1.6.0
113
+
114
+ * Added two new contributors
115
+ * Merged @utahstreetlabs' work on the tracking number validator.
116
+ * Added RBX, RBX 2.0 and JRuby to the build matrix
117
+ * We don't need to require the whole path here
118
+ * Silence some warnings, as we run with Ruby with the -w flag.
119
+ * Add 1.9.3 to the build matrix
120
+ * Dropped RSpec in favor of MiniTest
121
+ * Added Travis' build status logo.
122
+ * Added .travis.yml for testing against multiple Ruby VMs
123
+ * Added rake as a dependency
124
+
125
+ # 1.5.1
126
+
127
+ * Fix UPS tracking number's validation
128
+
129
+ # 1.5
130
+
131
+ * Fix copy-and-paste error with tracking number formats
132
+ * Add ups tracking number validation
133
+
134
+ # 1.4.0
135
+
136
+ * Add Renato and Brian in both README and Gemspec
137
+ * Feature: postal\_code validation is now available.
138
+ * Fixed Ruby 1.8.7 support
139
+ * Remove and ignore Gemfile.lock
140
+ * Add postal code validator
141
+ * Based on the phone validator, the only country it knows about is :us
142
+ * Implemented 'old-school' validator methods dynamically
143
+ * DRYed validator loading
144
+ * Fix 1.9 compatiblity
145
+ * Bump up date\_validator, version number and dependencies in the Gemfile
146
+ * Refactored phone validator
147
+ * ActiveValidators now supports Twitter urls (both URLs and usernames with @
148
+ * Added twitter username validator
149
+
150
+ # 1.2.3
151
+
152
+ * Added :blank error message
153
+ * Add spec for empty slug
154
+ * Fixed NoMethodError when the slug isnt set quite yet, but will still fail validation
155
+
156
+ # 1.2.2
157
+
158
+ * Added a password validator (based on regexes)
159
+ * Added the contributor section in the README
160
+ * The Luhn algorithm has been implemented, so no need for the Luhnacy gem
161
+
162
+ # 1.2.1
163
+
164
+ * Fix bug in Mail Validator when a complete email address was given
165
+ * Add spec for https urls
166
+ * Refactor URL Validator specs
167
+ * Refactor Slug Validator specs
168
+ * Refactor Respond To Validator specs
169
+ * Refactor Phone Validator specs
170
+ * Refactor Email Validator specs
171
+ * Refactor Credit Card specs
172
+ * Use generic TestRecord for IPValidator
173
+ * Add generic TestRecord
174
+ * Add validity check standard to IPValidator and refactor
175
+ * Fix IPv4 validation for all rubies
176
+ * Ignore rbx files
177
+
178
+ # 1.2.0
179
+
180
+ * Added the test file from DateValidator to make sure that the tests passes, or that at least the validations are available thru ActiveValidator
181
+ * Added date\_validator in order to support date validation
182
+ * Drop Luhnacy, very simple implementation, supports lots of cards.
183
+ * Add credit card validation for American Express, Visa, Switch, and MasterCard
184
+ * Added IP validators
185
+
186
+ # 1.1.0
187
+
188
+ * Add errors with the ActiveModel::Errors#add method -> i18n support
189
+ * Add phone format validator
190
+ * Public release
data/README.md CHANGED
@@ -10,6 +10,21 @@ ActiveValidators is a collection of off-the-shelf and tested ActiveModel/ActiveR
10
10
 
11
11
  This projects follows [Semantic Versioning a.k.a SemVer](http://semver.org). If you use Bundler, you can use the stabby specifier `~>` safely.
12
12
 
13
+ Once you have `require`'d the gem, you will have to activate the validators you
14
+ want to use as ActiveValidators doesn't force you to use them all :
15
+
16
+ # Activate all the validators
17
+ ActiveValidators.activate(:all)
18
+
19
+ # Activate only the email and slug validators
20
+ ActiveValidators.activate(:email, :slug)
21
+
22
+ # Activate only the phone
23
+ ActiveValidators.activate(:phone)
24
+
25
+ `ActiveValidators.activate` can be called as many times as one wants. It's only
26
+ a syntactic sugar on top a normal Ruby `require`.
27
+
13
28
  ## Usage
14
29
 
15
30
  In your models, the gem provides new validators like `email`, or `url`:
@@ -27,6 +42,12 @@ In your models, the gem provides new validators like `email`, or `url`:
27
42
  validates :postal_code, :postal_code => { :country => :us }
28
43
  end
29
44
 
45
+ class Identification
46
+ validates :ssn, :ssn => true
47
+ validates :sin, :sin => true
48
+ validates :nino, :nino => true
49
+ end
50
+
30
51
  class Article
31
52
  validates :slug, :slug => true
32
53
  validates :expiration_date,
@@ -50,6 +71,10 @@ In your models, the gem provides new validators like `email`, or `url`:
50
71
  class Order
51
72
  validates :tracking_num, :tracking_number => { :carrier => :ups }
52
73
  end
74
+
75
+ class Product
76
+ validates :code, :barcode => { :format => :ean13 }
77
+ end
53
78
  ```
54
79
 
55
80
  Exhaustive list of supported validators and their implementation:
@@ -58,15 +83,19 @@ Exhaustive list of supported validators and their implementation:
58
83
  * `date` : based on the `DateValidator` gem
59
84
  * `email` : based on the `mail` gem
60
85
  * `ip` : based on `Resolv::IPv[4|6]::Regex`
86
+ * `nino` : National Insurance number (only for UK). Please note that this validation will not accept temporary (such as 63T12345) or administrative numbers (with prefixes like OO, CR, FY, MW, NC, PP, PY, PZ).
61
87
  * `password` : based on a set of regular expressions
62
88
  * `phone` : based on a set of predefined masks
63
89
  * `postal_code`: based on a set of predefined masks
64
90
  * `respond_to`
65
91
  * `siren`
66
92
  * `slug` : based on `ActiveSupport::String#parameterize`
93
+ * `sin` : Social Insurance Number (only for Canada). You also can allow permanent residents cards (such cards start with '9'): `:sin => {:country => :canada, :country_options => {allow_permanent_residents: true}}`
94
+ * `ssn` : Social Security Number (only for USA). You also may pass type, instead of boolean: `:ssn => {:type => :usa_ssn}` as the alternative.
67
95
  * `tracking_number`: based on a set of predefined masks
68
96
  * `twitter` : based on a regular expression
69
97
  * `url` : based on a regular expression
98
+ * `barcode` : based on known formats (default: EAN 13)
70
99
 
71
100
  ## Todo
72
101
 
@@ -97,6 +126,8 @@ Lots of improvements can be made:
97
126
  * Travis Vachon
98
127
  * Rob Zuber
99
128
  * Manuel Menezes de Sequeira
129
+ * Serj L aka Loremaster
130
+ * Pierre-Baptiste Béchu
100
131
 
101
132
  ## Copyright
102
133
 
@@ -1,9 +1,9 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  Gem::Specification.new do |s|
3
3
  s.name = 'activevalidators'
4
- s.version = '2.1.0'
4
+ s.version = '3.0.0'
5
5
  s.platform = Gem::Platform::RUBY
6
- s.authors = ['Franck Verrot', 'Paco Guzmán', 'Oriol Gual', 'Garrett Bjerkhoel', 'Renato Riccieri Santos Zannon', 'Brian Moseley']
6
+ s.authors = ['Franck Verrot', 'Paco Guzmán', 'Oriol Gual', 'Garrett Bjerkhoel', 'Renato Riccieri Santos Zannon', 'Brian Moseley', 'Serj L aka Loremaster']
7
7
  s.email = ['franck@verrot.fr']
8
8
  s.homepage = 'http://github.com/franckverrot/activevalidators'
9
9
  s.summary = %q{Collection of ActiveModel/ActiveRecord validations}
@@ -21,4 +21,19 @@ Gem::Specification.new do |s|
21
21
 
22
22
  s.files = `git ls-files`.split("\n")
23
23
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
+
25
+ s.post_install_message = """
26
+ ######################################################################
27
+ # ActiveValidators v3.0.0 #
28
+ ######################################################################
29
+ # #
30
+ # Version 3 of ActiveValidators stopped requiring all the validators #
31
+ # for you. So you will have to use `ActiveValidators.activate`. #
32
+ # #
33
+ # By default, v3.0.0 does `ActiveValidators.activate(:all)` to help #
34
+ # transitioning to v3, but 3.0.1 won't do that anymore. #
35
+ # #
36
+ # Thanks for using ActiveValidators ! #
37
+ # #
38
+ ######################################################################"""
24
39
  end
@@ -0,0 +1,33 @@
1
+ module ActiveModel
2
+ module Validations
3
+ class BarcodeValidator < EachValidator
4
+ def validate_each(record, attribute, value)
5
+ # EAN13 by default
6
+ format = options.fetch(:format, :ean13)
7
+ method = "valid_#{format.to_s}?"
8
+ raise "Barcode format not supported (#{format})" unless self.respond_to?(method)
9
+ record.errors.add(attribute) if value.blank? || !self.send(method, value)
10
+ end
11
+
12
+ def valid_ean13?(value)
13
+ if value =~ /^\d{13}$/
14
+ ean13_check_digit(value.slice(0,12)) == value.slice(12)
15
+ end
16
+ end
17
+
18
+ private
19
+ # Comes from http://fr.wikipedia.org/wiki/Code-barres_EAN
20
+ def ean13_check_digit(value)
21
+ even_sum, uneven_sum = 0, 0
22
+ value.split('').each_with_index do |digit, index|
23
+ if (index+1).even?
24
+ even_sum += digit.to_i
25
+ else
26
+ uneven_sum += digit.to_i
27
+ end
28
+ end
29
+ (10 - ((even_sum*3 + uneven_sum) % 10)).to_s
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,3 +1,5 @@
1
+ require 'active_model/validations/shared/luhn_checker'
2
+
1
3
  module ActiveModel
2
4
  module Validations
3
5
 
@@ -14,14 +16,14 @@ module ActiveModel
14
16
  class Luhn
15
17
  def self.valid?(card_type,number)
16
18
  if card_type == :any
17
- self.luhn_valid?(number)
19
+ LuhnChecker.valid?(number)
18
20
  else
19
21
  self.send("#{card_type.to_s}?", number)
20
22
  end
21
23
  end
22
24
 
23
25
  def self.mastercard?(number)
24
- self.luhn_valid?(number) and !(number !~ /^5[1-5].{14}/)
26
+ LuhnChecker.valid?(number) and !(number !~ /^5[1-5].{14}/)
25
27
  end
26
28
 
27
29
  class << self
@@ -29,40 +31,21 @@ module ActiveModel
29
31
  end
30
32
 
31
33
  def self.visa?(number)
32
- self.luhn_valid?(number) and !(number !~ /^4.{15}/)
34
+ LuhnChecker.valid?(number) and !(number !~ /^4.{15}/)
33
35
  end
34
36
 
35
37
  def self.amex?(number)
36
- self.luhn_valid?(number) and !(number !~ /^3[47].{13}/)
38
+ LuhnChecker.valid?(number) and !(number !~ /^3[47].{13}/)
37
39
  end
38
40
 
39
41
  [:diners_club, :en_route, :discover, :jcb, :carte_blanche, :switch,
40
42
  :solo, :laser].each do |card_type|
41
43
  class_eval <<-VALIDATOR, __FILE__, __LINE__ + 1
42
44
  def self.#{card_type}?(number)
43
- self.luhn_valid?(number)
45
+ LuhnChecker.valid?(number)
44
46
  end
45
47
  VALIDATOR
46
48
  end
47
-
48
- def self.luhn_valid?(s)
49
- value = s.gsub(/\D/, '').reverse
50
-
51
- sum = i = 0
52
-
53
- value.each_char do |ch|
54
- n = ch.to_i
55
-
56
- n *= 2 if i.odd?
57
-
58
- n = 1 + (n - 10) if n >= 10
59
-
60
- sum += n
61
- i += 1
62
- end
63
-
64
- (sum % 10).zero?
65
- end
66
49
  end
67
50
  end
68
51
 
@@ -0,0 +1 @@
1
+ require 'date_validator'
@@ -0,0 +1,70 @@
1
+ module ActiveModel
2
+ module Validations
3
+ class NinoValidator < EachValidator
4
+ def validate_each(record, attribute, value)
5
+ record.errors.add(attribute) if value.blank? || !NinoValidatorUK.new(value).valid?
6
+ end
7
+ end
8
+
9
+ # The National Insurance number is a number used in the United Kingdom.
10
+ # The format of the number is two prefix letters, six digits, and one suffix letter. The example used is typically AB123456C.
11
+ # Where AB - prefix, 123456 - number, C - suffix.
12
+ # More details: http://en.wikipedia.org/wiki/National_Insurance_number
13
+ class NinoValidatorUK
14
+ def initialize(value)
15
+ @nino = value.gsub(/\s/, '').upcase # Remove spaces (they may be) and make text to be same.
16
+ @first_char = @nino[0]
17
+ @second_char = @nino[1]
18
+ @prefix = @nino[0..1]
19
+ @number = @nino[2..7]
20
+ @suffix = @nino[-1]
21
+ end
22
+
23
+ def valid?
24
+ size_is?(9) && first_char_valid? && second_char_valid? && prefix_valid? &&
25
+ prefix_not_allocated? && prefix_not_administrative_number? && number_valid? && suffix_valid?
26
+ end
27
+
28
+ private
29
+
30
+ def size_is?(count)
31
+ @nino.size == count
32
+ end
33
+
34
+ def first_char_valid?
35
+ forbidden_chars = %w[D F I Q U V]
36
+ !forbidden_chars.include?(@first_char)
37
+ end
38
+
39
+ def second_char_valid?
40
+ forbidden_chars = %w[D F I Q U V O]
41
+ !forbidden_chars.include?(@second_char)
42
+ end
43
+
44
+ def prefix_valid?
45
+ prefix_rule = /[a-zA-Z]{2}/ # Exactly 2 alphabet chars.
46
+ !!(prefix_rule =~ @prefix)
47
+ end
48
+
49
+ def number_valid?
50
+ number_rule = /^[0-9]{6}$/ # Exactly 6 digits.
51
+ !!(number_rule =~ @number)
52
+ end
53
+
54
+ def suffix_valid?
55
+ allowed_chars = %w[A B C D]
56
+ allowed_chars.include?(@suffix)
57
+ end
58
+
59
+ def prefix_not_allocated?
60
+ forbidden_prefixes = %w[BG, GB, NK, KN, TN, NT, ZZ]
61
+ !forbidden_prefixes.include?(@prefix)
62
+ end
63
+
64
+ def prefix_not_administrative_number?
65
+ administrative_prefixes = %w[OO, CR, FY, MW, NC, PP, PY, PZ]
66
+ !administrative_prefixes.include?(@prefix)
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,22 @@
1
+ module LuhnChecker
2
+ # This method implements Luhn algorythm.
3
+ # Details about it's work may be founded here: http://en.wikipedia.org/wiki/Luhn_Algorithm
4
+ def self.valid?(s)
5
+ value = s.gsub(/\D/, '').reverse
6
+
7
+ sum = i = 0
8
+
9
+ value.each_char do |ch|
10
+ n = ch.to_i
11
+
12
+ n *= 2 if i.odd?
13
+
14
+ n = 1 + (n - 10) if n >= 10
15
+
16
+ sum += n
17
+ i += 1
18
+ end
19
+
20
+ (sum % 10).zero?
21
+ end
22
+ end
@@ -0,0 +1,62 @@
1
+ require 'active_model/validations/shared/luhn_checker'
2
+
3
+ module ActiveModel
4
+ module Validations
5
+ class SinValidator < EachValidator
6
+ def validate_each(record, attribute, value)
7
+ country = options.fetch(:country, :canada) # :canada is default.
8
+ record.errors.add(attribute) if value.blank? || !SinValidatorGeneral.valid?(country, value, options)
9
+ end
10
+ end
11
+
12
+ class SinValidatorGeneral
13
+ def self.valid?(country, value, options)
14
+ if country == :canada
15
+ SinValidatorCanada.new(value, options).valid?
16
+ end
17
+ end
18
+ end
19
+
20
+ # The Social Insurance Number is a nine-digit number in the format "AAA BBB CCC".
21
+ # The number is divided into three parts.
22
+ # AAA - is the first, BBB - is the second and the CCC is the third.
23
+ # Numbers that begin with the number "9" are issued to temporary residents who are not Canadian citizens
24
+ # More details: http://en.wikipedia.org/wiki/Social_Insurance_Number
25
+ #
26
+ # Possible flags:
27
+ # allow_permanent_residents - citizens with cars, which begins with "9" are valid. By default it is false.
28
+ #
29
+ # validates :sin, :sin => {:country => :canada, :country_options => {:allow_permanent_residents => true}}
30
+ class SinValidatorCanada
31
+ def initialize(str_value, options)
32
+ @sin = str_value.gsub(/\D/, '') # keep only integers
33
+ @allow_permanent_residents = false
34
+
35
+ country_options = options.fetch(:country_options, {})
36
+ allow_permanent_residents = country_options.fetch(:allow_permanent_residents, :nil)
37
+
38
+ if allow_permanent_residents == true
39
+ @allow_permanent_residents = true
40
+ end
41
+ end
42
+
43
+ def valid?
44
+ size_is?(9) && allow_permanent_residents? && LuhnChecker.valid?(@sin)
45
+ end
46
+
47
+ def size_is?(count)
48
+ @sin.size == count
49
+ end
50
+
51
+ def allow_permanent_residents?
52
+ permanent_residents_indentifier = "9"
53
+
54
+ if @allow_permanent_residents == false && @sin.start_with?(permanent_residents_indentifier)
55
+ false
56
+ else
57
+ true
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,54 @@
1
+ module ActiveModel
2
+ module Validations
3
+ class SsnValidator < EachValidator
4
+ def validate_each(record, attribute, value)
5
+ type = options.fetch(:type, :usa_ssn) # :usa_ssn is default.
6
+ record.errors.add(attribute) if value.blank? || !SsnValidatorGeneral.valid?(type, value)
7
+ end
8
+ end
9
+
10
+ class SsnValidatorGeneral
11
+ def self.valid?(type, value)
12
+ if type == :usa_ssn
13
+ SsnValidatorUSA.new(value).valid?
14
+ end
15
+ end
16
+ end
17
+
18
+ # The Social Security number is a nine-digit number in the format "AAA-GG-SSSS". The number is divided into three parts.
19
+ # AAA - is the first, GG - is the second and the SSSS is the third.
20
+ # More details: http://en.wikipedia.org/wiki/Social_Security_number
21
+ class SsnValidatorUSA
22
+ def initialize(value)
23
+ @value = value
24
+ @first_group_num = value[0..2].to_i
25
+ @second_group_num = value[3..4].to_i
26
+ @third_group_num = value[5..8].to_i
27
+ end
28
+
29
+ def valid?
30
+ all_groups_integers? && first_group_valid? && second_group_valid? && third_group_valid?
31
+ end
32
+
33
+ def all_groups_integers?
34
+ begin
35
+ !!Integer(@value)
36
+ rescue ArgumentError, TypeError
37
+ false
38
+ end
39
+ end
40
+
41
+ def first_group_valid?
42
+ @first_group_num != 0 && @first_group_num != 666 && (@first_group_num < 900 || @first_group_num > 999)
43
+ end
44
+
45
+ def second_group_valid?
46
+ @second_group_num != 0
47
+ end
48
+
49
+ def third_group_valid?
50
+ @third_group_num != 0
51
+ end
52
+ end
53
+ end
54
+ end
@@ -3,27 +3,33 @@ require 'phony'
3
3
  require 'countries'
4
4
  require 'active_validators/one_nine_shims/one_nine_string'
5
5
 
6
- module ActiveModel
7
- module Validations
8
- def self.activevalidators
9
- %w(email url respond_to phone slug ip credit_card date password twitter postal_code tracking_number siren)
10
- end
6
+ module ActiveValidators
7
+ def self.activevalidators
8
+ %w(email url respond_to phone slug ip credit_card date password twitter postal_code tracking_number siren ssn sin nino barcode date)
9
+ end
10
+
11
+ # Require each validator independently or just pass :all
12
+ #
13
+ # call-seq:
14
+ # ActiveValidators.activate(:phone, :email, :date)
15
+ # ActiveValidators.activate(:all)
16
+ def self.activate(*validators)
17
+ syms = validators.include?(:all) ? activevalidators : validators.map(&:to_s) & activevalidators
11
18
 
12
- activevalidators.each do |validator_name|
19
+ syms.each do |validator_name|
13
20
  require "active_model/validations/#{validator_name}_validator"
14
21
  end
22
+ end
15
23
 
16
- require 'date_validator'
17
-
18
- #Defines methods like validates_credit_card
19
- module HelperMethods
20
- ActiveModel::Validations.activevalidators.each do |validator|
21
- define_method('validates_'+validator) do |*fields|
22
- options ||= (fields.delete fields.find { |f| f.kind_of? Hash}) || true
23
- args = fields.push({ validator => options })
24
- validates(*args)
25
- end
26
- end
24
+ # Defines methods like validates_credit_card
25
+ def define_helper_method_for_validator(validator)
26
+ define_method('validates_'+validator) do |*fields|
27
+ options ||= (fields.delete fields.find { |f| f.kind_of? Hash}) || true
28
+ args = fields.push({ validator => options })
29
+ validates(*args)
27
30
  end
28
31
  end
29
32
  end
33
+
34
+ # Deprecated
35
+ warn "[deprecated] ActiveValidators.activate is the recommended solution to require your validators. Please check instructions in the README. Thanks a lot !"
@@ -14,7 +14,7 @@ class TestRecord
14
14
  include ActiveModel::Validations
15
15
  attr_accessor :ip, :url, :slug, :responder, :global_condition,
16
16
  :local_condition, :phone, :email, :card, :password, :twitter_username,
17
- :postal_code, :carrier, :tracking_number, :start_date, :end_date, :siren
17
+ :postal_code, :carrier, :tracking_number, :start_date, :end_date, :siren, :ssn, :sin, :nino, :barcode
18
18
 
19
19
  def initialize(attrs = {})
20
20
  attrs.each_pair { |k,v| send("#{k}=", v) }
@@ -0,0 +1,38 @@
1
+ require 'test_helper'
2
+ ActiveValidators.activate(:barcode)
3
+
4
+ describe "Barcode Validation" do
5
+ describe "EAN13 Validation" do
6
+ it "accepts valid EAN13s" do
7
+ subject = build_barcode_record :ean13, :barcode => "9782940199617"
8
+ subject.valid?.must_equal true
9
+ subject.errors.size.must_equal 0
10
+ end
11
+
12
+ describe "for invalid EAN13s" do
13
+ it "rejects invalid EAN13s" do
14
+ subject = build_barcode_record :ean13, :barcode => "9782940199616"
15
+ subject.valid?.must_equal false
16
+ subject.errors.size.must_equal 1
17
+ end
18
+
19
+ it "rejects EAN13s with invalid length" do
20
+ subject = build_barcode_record :ean13, :barcode => "50239201872045879"
21
+ subject.valid?.must_equal false
22
+ subject.errors.size.must_equal 1
23
+ end
24
+
25
+ it "rejects EAN13S with invalid format" do
26
+ subject = build_barcode_record :ean13, :barcode => "502392de872e4"
27
+ subject.valid?.must_equal false
28
+ subject.errors.size.must_equal 1
29
+ end
30
+ end
31
+ end
32
+
33
+ def build_barcode_record(type, attrs = {})
34
+ TestRecord.reset_callbacks(:validate)
35
+ TestRecord.validates :barcode, :barcode => { :format => type }
36
+ TestRecord.new attrs
37
+ end
38
+ end
@@ -1,4 +1,5 @@
1
- require 'test_helper.rb'
1
+ require 'test_helper'
2
+ ActiveValidators.activate(:credit_card)
2
3
 
3
4
  describe "Credit Card Validation" do
4
5
  # Here are some valid credit cards
@@ -1,5 +1,6 @@
1
1
  require 'test_helper'
2
2
  require 'active_support/core_ext/hash/reverse_merge'
3
+ ActiveValidators.activate(:date)
3
4
 
4
5
  # ActiveValidators relies on another gem called "date_validator" edited
5
6
  # by the fine folks at Codegram.
@@ -1,4 +1,5 @@
1
- require 'test_helper.rb'
1
+ require 'test_helper'
2
+ ActiveValidators.activate(:email)
2
3
 
3
4
  describe "Email Validation" do
4
5
  describe "strict: true" do
@@ -1,5 +1,6 @@
1
- require 'test_helper.rb'
1
+ require 'test_helper'
2
2
  require 'ipaddr'
3
+ ActiveValidators.activate(:ip)
3
4
 
4
5
  describe "IP Validation" do
5
6
  describe "IPv4 Validation" do
@@ -0,0 +1,110 @@
1
+ require 'test_helper'
2
+ ActiveValidators.activate(:nino)
3
+
4
+ describe "NINO validations" do
5
+ describe "for UK" do
6
+ describe "for invalid" do
7
+ it "rejects empty nino" do
8
+ subject = build_nino_record({:nino => ''})
9
+ subject.valid?.must_equal false
10
+ end
11
+
12
+ it "rejects nino, which has invalid first letter" do
13
+ invalid_first_letter = %w[d f i q u v]
14
+ invalid_first_letter.each do |letter|
15
+ invalid_nino = letter + 'B123456C'
16
+ subject = build_nino_record({:nino => invalid_nino})
17
+ subject.valid?.must_equal false
18
+ end
19
+ end
20
+
21
+ it "rejects nino, which has invalid second letter" do
22
+ invalid_second_letter = %w[d f i q u v o]
23
+ invalid_second_letter.each do |letter|
24
+ invalid_nino = 'a' + letter + '123456C'
25
+ subject = build_nino_record({:nino => invalid_nino})
26
+ subject.valid?.must_equal false
27
+ end
28
+ end
29
+
30
+ it "rejects too long nino" do
31
+ subject = build_nino_record({:nino => 'AB123456C100200'})
32
+ subject.valid?.must_equal false
33
+ end
34
+
35
+ it "rejects nino with invalid prefix" do
36
+ subject = build_nino_record({:nino => '#$123456C'})
37
+ subject.valid?.must_equal false
38
+ end
39
+
40
+ it "rejects nino with invalid chars in number section" do
41
+ subject = build_nino_record({:nino => 'AB@2%4#6C'})
42
+ subject.valid?.must_equal false
43
+ end
44
+
45
+ it "rejects wrong suffixes" do
46
+ invalid_suffix = %w[E F G H] # and etc
47
+ invalid_suffix.each do |suffix|
48
+ invalid_nino = 'AB123456' + suffix
49
+ subject = build_nino_record({:nino => invalid_nino})
50
+ subject.valid?.must_equal false
51
+ end
52
+ end
53
+
54
+ it "rejects non allocated prefixes" do
55
+ non_allocated_prefixes = %w[bg, gb, nk, kn, tn, nt, zz]
56
+ non_allocated_prefixes.each do |suffix|
57
+ invalid_nino = suffix + '123456C'
58
+ subject = build_nino_record({:nino => invalid_nino})
59
+ subject.valid?.must_equal false
60
+ end
61
+ end
62
+
63
+ it "rejects administrative numbers" do
64
+ administrative_numbers = %w[oo, cr, fy, mw, nc, pp, py, pz]
65
+ administrative_numbers.each do |suffix|
66
+ invalid_nino = suffix + '123456C'
67
+ subject = build_nino_record({:nino => invalid_nino})
68
+ subject.valid?.must_equal false
69
+ end
70
+ end
71
+
72
+ it "rejects temporary numbers" do
73
+ subject = build_nino_record({:nino => '63T12345'})
74
+ subject.valid?.must_equal false
75
+ end
76
+ end
77
+
78
+ describe "for valid" do
79
+ it "acepts correct nino" do
80
+ subject = build_nino_record({:nino => 'AB123456C'})
81
+ subject.valid?.must_equal true
82
+ end
83
+
84
+ it "acepts nino, divided by spaces" do
85
+ subject = build_nino_record({:nino => 'AB 12 34 56 C'})
86
+ subject.valid?.must_equal true
87
+ end
88
+
89
+ it "acepts downcase nino" do
90
+ subject = build_nino_record({:nino => 'ab 12 34 56 c'})
91
+ subject.valid?.must_equal true
92
+ end
93
+
94
+ it "acepts correct suffixes" do
95
+ valid_suffix = %w[A B C D]
96
+ valid_suffix.each do |suffix|
97
+ valid_nino = 'AB123456' + suffix
98
+ subject = build_nino_record({:nino => valid_nino})
99
+ subject.valid?.must_equal true
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ def build_nino_record(attrs = {})
106
+ TestRecord.reset_callbacks(:validate)
107
+ TestRecord.validates :nino, :nino => true
108
+ TestRecord.new attrs
109
+ end
110
+ end
@@ -1,4 +1,5 @@
1
- require 'test_helper.rb'
1
+ require 'test_helper'
2
+ ActiveValidators.activate(:password)
2
3
 
3
4
  describe "Password Validation" do
4
5
  STRENGTHS = {
@@ -1,4 +1,5 @@
1
- require 'test_helper.rb'
1
+ require 'test_helper'
2
+ ActiveValidators.activate(:phone)
2
3
 
3
4
  describe "Phone Validation" do
4
5
  def build_phone_validation phone, attrs = {}
@@ -1,4 +1,5 @@
1
- require 'test_helper.rb'
1
+ require 'test_helper'
2
+ ActiveValidators.activate(:postal_code)
2
3
 
3
4
  describe "Postal Code Validation" do
4
5
  def build_postal_code_record postal_code, attrs = {}
@@ -1,4 +1,5 @@
1
- require 'test_helper.rb'
1
+ require 'test_helper'
2
+ ActiveValidators.activate(:respond_to)
2
3
 
3
4
  describe "Respond To Validation" do
4
5
  def build_respond_to_record attrs = {}
@@ -0,0 +1,62 @@
1
+ require 'test_helper'
2
+ ActiveValidators.activate(:sin)
3
+
4
+ describe "SIN validations" do
5
+ describe "for Canada" do
6
+ describe "for invalid" do
7
+ it "rejects empty sin" do
8
+ subject = build_sin_record({:sin => ''})
9
+ subject.valid?.must_equal false
10
+ end
11
+
12
+ it "rejects empty sin when country is provided" do
13
+ subject = build_sin_record({:sin => ''}, {:country => :canada })
14
+ subject.valid?.must_equal false
15
+ end
16
+
17
+ it "rejects too long sin" do
18
+ subject = build_sin_record({:sin => '123 456 789 0'}, {:country => :canada })
19
+ subject.valid?.must_equal false
20
+ end
21
+
22
+ it "rejects too short sin" do
23
+ subject = build_sin_record({:sin => '123'}, {:country => :canada })
24
+ subject.valid?.must_equal false
25
+ end
26
+
27
+ it "rejects valid sin for temporary residents by default" do
28
+ subject = build_sin_record({:sin => '996 454 286'}, {:country => :canada })
29
+ subject.valid?.must_equal false
30
+ end
31
+
32
+ it "rejects invalid sin for permanent residents" do
33
+ subject = build_sin_record({:sin => '123 456 789'}, {:country => :canada })
34
+ subject.valid?.must_equal false
35
+ end
36
+ end
37
+
38
+ describe "for valid" do
39
+ it "accept valid sin for permanent residents without flags (Canada by default)" do
40
+ subject = build_sin_record({:sin => '046 454 286'}, true)
41
+ subject.valid?.must_equal true
42
+ end
43
+
44
+ it "accept valid sin for permanent residents" do
45
+ subject = build_sin_record({:sin => '046 454 286'}, {:country => :canada })
46
+ subject.valid?.must_equal true
47
+ end
48
+
49
+ it "accept valid sin for temporary residents when flag is provided" do
50
+ subject = build_sin_record({:sin => '996 454 286'},
51
+ {:country => :canada, :country_options => { allow_permanent_residents: true } })
52
+ subject.valid?.must_equal true
53
+ end
54
+ end
55
+ end
56
+
57
+ def build_sin_record(attrs = {}, validator)
58
+ TestRecord.reset_callbacks(:validate)
59
+ TestRecord.validates :sin, :sin => validator
60
+ TestRecord.new attrs
61
+ end
62
+ end
@@ -1,4 +1,5 @@
1
- require 'test_helper.rb'
1
+ require 'test_helper'
2
+ ActiveValidators.activate(:siren)
2
3
 
3
4
  describe "Siren Validation" do
4
5
  it "Rejects if not supplied" do
@@ -1,4 +1,5 @@
1
- require 'test_helper.rb'
1
+ require 'test_helper'
2
+ ActiveValidators.activate(:slug)
2
3
 
3
4
  describe "Slug Validation" do
4
5
  def build_slug_validation attrs = {}
@@ -0,0 +1,70 @@
1
+ require 'test_helper'
2
+ ActiveValidators.activate(:ssn)
3
+
4
+ describe "SSN validations" do
5
+ describe "USA ssn" do
6
+ describe "for invalid" do
7
+ it "rejects empty ssn" do
8
+ subject = build_ssn_record({:ssn => ''}, {:type => :usa_ssn})
9
+ subject.valid?.must_equal false
10
+ end
11
+
12
+ it "rejects ssn when it doesn't consist of numbers" do
13
+ subject = build_ssn_record({:ssn => 'aaabbcccc'}, {:type => :usa_ssn})
14
+ subject.valid?.must_equal false
15
+ end
16
+
17
+ it "rejects ssn when the first group of digits is 000" do
18
+ subject = build_ssn_record({:ssn => '000112222'}, {:type => :usa_ssn})
19
+ subject.valid?.must_equal false
20
+ end
21
+
22
+ it "rejects ssn when the first group of digits is 666" do
23
+ subject = build_ssn_record({:ssn => '666112222'}, {:type => :usa_ssn})
24
+ subject.valid?.must_equal false
25
+ end
26
+
27
+ (900..999).each do |first_group_num|
28
+ it "rejects ssn when the first group of digits is #{first_group_num}" do
29
+ subject = build_ssn_record({:ssn => "#{first_group_num}112222"}, {:type => :usa_ssn})
30
+ subject.valid?.must_equal false
31
+ end
32
+ end
33
+
34
+ it "reject ssn when the second group of digits is 00" do
35
+ subject = build_ssn_record({:ssn => "555002222"}, {:type => :usa_ssn})
36
+ subject.valid?.must_equal false
37
+ end
38
+
39
+ it "reject ssn when the third group of digits is 0000" do
40
+ subject = build_ssn_record({:ssn => "555660000"}, {:type => :usa_ssn})
41
+ subject.valid?.must_equal false
42
+ end
43
+
44
+ (987654320..987654329).each do |reserved_ssn|
45
+ it "rejects reserved ssn such as #{reserved_ssn}" do
46
+ subject = build_ssn_record({:ssn => "#{reserved_ssn}"}, {:type => :usa_ssn})
47
+ subject.valid?.must_equal false
48
+ end
49
+ end
50
+ end
51
+
52
+ describe "for valid" do
53
+ it "accept ssn when it contains correct numbers" do
54
+ subject = build_ssn_record({:ssn => '444556666'}, {:type => :usa_ssn})
55
+ subject.valid?.must_equal true
56
+ end
57
+
58
+ it "accept ssn without type (and use by default 'usa_ssn')" do
59
+ subject = build_ssn_record({:ssn => '444556666'}, true)
60
+ subject.valid?.must_equal true
61
+ end
62
+ end
63
+ end
64
+
65
+ def build_ssn_record(attrs = {}, validator)
66
+ TestRecord.reset_callbacks(:validate)
67
+ TestRecord.validates :ssn, :ssn => validator
68
+ TestRecord.new attrs
69
+ end
70
+ end
@@ -1,4 +1,5 @@
1
- require 'test_helper.rb'
1
+ require 'test_helper'
2
+ ActiveValidators.activate(:tracking_number)
2
3
 
3
4
  describe "Tracking Number Validation" do
4
5
  def build_tracking_number_record carrier_opts, attrs = {}
@@ -1,5 +1,6 @@
1
1
  # coding: utf-8
2
- require 'test_helper.rb'
2
+ require 'test_helper'
3
+ ActiveValidators.activate(:twitter)
3
4
 
4
5
  describe "Twitter Validation" do
5
6
  def build_twitter_record format, attrs = {}
@@ -1,4 +1,5 @@
1
- require 'test_helper.rb'
1
+ require 'test_helper'
2
+ ActiveValidators.activate(:url)
2
3
 
3
4
  describe "Url Validation" do
4
5
  def build_url_record
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activevalidators
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Franck Verrot
@@ -10,10 +10,11 @@ authors:
10
10
  - Garrett Bjerkhoel
11
11
  - Renato Riccieri Santos Zannon
12
12
  - Brian Moseley
13
+ - Serj L aka Loremaster
13
14
  autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
- date: 2014-03-09 00:00:00.000000000 Z
17
+ date: 2014-09-06 00:00:00.000000000 Z
17
18
  dependencies:
18
19
  - !ruby/object:Gem::Dependency
19
20
  name: bundler
@@ -136,36 +137,47 @@ extra_rdoc_files: []
136
137
  files:
137
138
  - ".gitignore"
138
139
  - ".travis.yml"
140
+ - ChangeLog.md
139
141
  - Gemfile
140
142
  - LICENSE
141
143
  - README.md
142
144
  - Rakefile
143
145
  - activevalidators.gemspec
146
+ - lib/active_model/validations/barcode_validator.rb
144
147
  - lib/active_model/validations/credit_card_validator.rb
148
+ - lib/active_model/validations/date_validator.rb
145
149
  - lib/active_model/validations/email_validator.rb
146
150
  - lib/active_model/validations/ip_validator.rb
151
+ - lib/active_model/validations/nino_validator.rb
147
152
  - lib/active_model/validations/password_validator.rb
148
153
  - lib/active_model/validations/phone_validator.rb
149
154
  - lib/active_model/validations/postal_code_validator.rb
150
155
  - lib/active_model/validations/respond_to_validator.rb
156
+ - lib/active_model/validations/shared/luhn_checker.rb
157
+ - lib/active_model/validations/sin_validator.rb
151
158
  - lib/active_model/validations/siren_validator.rb
152
159
  - lib/active_model/validations/slug_validator.rb
160
+ - lib/active_model/validations/ssn_validator.rb
153
161
  - lib/active_model/validations/tracking_number_validator.rb
154
162
  - lib/active_model/validations/twitter_validator.rb
155
163
  - lib/active_model/validations/url_validator.rb
156
164
  - lib/active_validators/one_nine_shims/one_nine_string.rb
157
165
  - lib/activevalidators.rb
158
166
  - test/test_helper.rb
167
+ - test/validations/barcode_test.rb
159
168
  - test/validations/credit_card_test.rb
160
169
  - test/validations/date_test.rb
161
170
  - test/validations/email_test.rb
162
171
  - test/validations/ip_test.rb
172
+ - test/validations/nino_test.rb
163
173
  - test/validations/password_test.rb
164
174
  - test/validations/phone_test.rb
165
175
  - test/validations/postal_code_test.rb
166
176
  - test/validations/respond_to_test.rb
177
+ - test/validations/sin_test.rb
167
178
  - test/validations/siren_test.rb
168
179
  - test/validations/slug_test.rb
180
+ - test/validations/ssn_test.rb
169
181
  - test/validations/tracking_number_test.rb
170
182
  - test/validations/twitter_test.rb
171
183
  - test/validations/url_test.rb
@@ -173,7 +185,21 @@ homepage: http://github.com/franckverrot/activevalidators
173
185
  licenses:
174
186
  - MIT
175
187
  metadata: {}
176
- post_install_message:
188
+ post_install_message: |2-
189
+
190
+ ######################################################################
191
+ # ActiveValidators v3.0.0 #
192
+ ######################################################################
193
+ # #
194
+ # Version 3 of ActiveValidators stopped requiring all the validators #
195
+ # for you. So you will have to use `ActiveValidators.activate`. #
196
+ # #
197
+ # By default, v3.0.0 does `ActiveValidators.activate(:all)` to help #
198
+ # transitioning to v3, but 3.0.1 won't do that anymore. #
199
+ # #
200
+ # Thanks for using ActiveValidators ! #
201
+ # #
202
+ ######################################################################
177
203
  rdoc_options: []
178
204
  require_paths:
179
205
  - lib
@@ -195,16 +221,21 @@ specification_version: 4
195
221
  summary: Collection of ActiveModel/ActiveRecord validations
196
222
  test_files:
197
223
  - test/test_helper.rb
224
+ - test/validations/barcode_test.rb
198
225
  - test/validations/credit_card_test.rb
199
226
  - test/validations/date_test.rb
200
227
  - test/validations/email_test.rb
201
228
  - test/validations/ip_test.rb
229
+ - test/validations/nino_test.rb
202
230
  - test/validations/password_test.rb
203
231
  - test/validations/phone_test.rb
204
232
  - test/validations/postal_code_test.rb
205
233
  - test/validations/respond_to_test.rb
234
+ - test/validations/sin_test.rb
206
235
  - test/validations/siren_test.rb
207
236
  - test/validations/slug_test.rb
237
+ - test/validations/ssn_test.rb
208
238
  - test/validations/tracking_number_test.rb
209
239
  - test/validations/twitter_test.rb
210
240
  - test/validations/url_test.rb
241
+ has_rdoc: