activevalidators 1.6.0 → 1.7.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/README.md +4 -2
- data/lib/active_model/validations/credit_card_validator.rb +15 -2
- data/lib/active_model/validations/ip_validator.rb +1 -1
- data/lib/active_model/validations/phone_validator.rb +1 -3
- data/lib/active_model/validations/postal_code_validator.rb +1 -1
- data/lib/active_model/validations/tracking_number_validator.rb +1 -1
- data/lib/active_model/validations/url_validator.rb +6 -1
- data/lib/active_validators/version.rb +1 -1
- data/lib/activevalidators.rb +3 -11
- data/test/validations/credit_card_test.rb +27 -10
- data/test/validations/url_test.rb +26 -11
- metadata +4 -4
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
ActiveValidators [](http://travis-ci.org/cesario/activevalidators)
|
2
2
|
================
|
3
3
|
|
4
4
|
Collection of ActiveModel/ActiveRecord validations
|
@@ -12,6 +12,7 @@ In your Gemfile ( >>= 1.1.0 ):
|
|
12
12
|
|
13
13
|
In your models, the gem provides new validators like `email`, or `url`:
|
14
14
|
|
15
|
+
```ruby
|
15
16
|
class User
|
16
17
|
validates :email_address, :email => true
|
17
18
|
validates :link_url, :url => true
|
@@ -38,6 +39,7 @@ In your models, the gem provides new validators like `email`, or `url`:
|
|
38
39
|
end
|
39
40
|
|
40
41
|
class Account
|
42
|
+
validates :any_card, :credit_card => true
|
41
43
|
validates :visa_card, :credit_card => { :type => :visa }
|
42
44
|
validates :credit_card, :credit_card => { :type => :any }
|
43
45
|
end
|
@@ -45,7 +47,7 @@ In your models, the gem provides new validators like `email`, or `url`:
|
|
45
47
|
class Order
|
46
48
|
validates :tracking_num, :tracking_number => { :carrier => :ups }
|
47
49
|
end
|
48
|
-
|
50
|
+
```
|
49
51
|
|
50
52
|
Exhaustive list of supported validators and their implementation:
|
51
53
|
|
@@ -3,7 +3,8 @@ module ActiveModel
|
|
3
3
|
|
4
4
|
class CreditCardValidator < EachValidator
|
5
5
|
def validate_each(record, attribute, value)
|
6
|
-
|
6
|
+
type = options.fetch(:type, :any)
|
7
|
+
record.errors.add(attribute) if value.blank? || !Luhn.valid?(type, sanitize_card(value))
|
7
8
|
end
|
8
9
|
|
9
10
|
def sanitize_card(value)
|
@@ -23,6 +24,10 @@ module ActiveModel
|
|
23
24
|
self.luhn_valid?(number) and !(number !~ /^5[1-5].{14}/)
|
24
25
|
end
|
25
26
|
|
27
|
+
class << self
|
28
|
+
alias :master_card? :mastercard?
|
29
|
+
end
|
30
|
+
|
26
31
|
def self.visa?(number)
|
27
32
|
self.luhn_valid?(number) and !(number !~ /^4.{15}/)
|
28
33
|
end
|
@@ -31,6 +36,15 @@ module ActiveModel
|
|
31
36
|
self.luhn_valid?(number) and !(number !~ /^3[47].{13}/)
|
32
37
|
end
|
33
38
|
|
39
|
+
[:diners_club, :en_route, :discover, :jcb, :carte_blanche, :switch,
|
40
|
+
:solo, :laser].each do |card_type|
|
41
|
+
class_eval <<-VALIDATOR, __FILE__, __LINE__ + 1
|
42
|
+
def self.#{card_type}?(number)
|
43
|
+
self.luhn_valid?(number)
|
44
|
+
end
|
45
|
+
VALIDATOR
|
46
|
+
end
|
47
|
+
|
34
48
|
def self.luhn_valid?(s)
|
35
49
|
return false unless s && s.is_a?(String)
|
36
50
|
return false if s.empty?
|
@@ -49,7 +63,6 @@ module ActiveModel
|
|
49
63
|
end
|
50
64
|
} % 10 == 0
|
51
65
|
end
|
52
|
-
|
53
66
|
end
|
54
67
|
end
|
55
68
|
|
@@ -2,7 +2,7 @@ module ActiveModel
|
|
2
2
|
module Validations
|
3
3
|
class IpValidator < EachValidator
|
4
4
|
def validate_each(record, attribute, value)
|
5
|
-
record.errors.add(attribute)
|
5
|
+
record.errors.add(attribute) if value.blank? || !regex.match(value)
|
6
6
|
end
|
7
7
|
|
8
8
|
def check_validity!
|
@@ -4,9 +4,7 @@ module ActiveModel
|
|
4
4
|
def validate_each(record, attribute, value)
|
5
5
|
@value = value
|
6
6
|
@formats = PhoneValidator.known_formats[options[:country]] || PhoneValidator.known_formats[:us]
|
7
|
-
|
8
|
-
record.errors.add(attribute)
|
9
|
-
end
|
7
|
+
record.errors.add(attribute) if value.blank? || !matches_any?
|
10
8
|
end
|
11
9
|
|
12
10
|
def self.known_formats
|
@@ -6,7 +6,7 @@ module ActiveModel
|
|
6
6
|
country = options[:country] || :us
|
7
7
|
@formats = PostalCodeValidator.known_formats[country]
|
8
8
|
raise "No known postal code formats for country #{country}" unless @formats
|
9
|
-
record.errors.add(attribute)
|
9
|
+
record.errors.add(attribute) if value.blank? || !matches_any?
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.known_formats
|
@@ -6,7 +6,7 @@ module ActiveModel
|
|
6
6
|
raise "Carrier option required" unless carrier
|
7
7
|
method = "valid_#{carrier.to_s}?"
|
8
8
|
raise "Tracking number validation not supported for carrier #{carrier}" unless self.respond_to?(method)
|
9
|
-
record.errors.add(attribute)
|
9
|
+
record.errors.add(attribute) if value.blank? || !self.send(method, value)
|
10
10
|
end
|
11
11
|
|
12
12
|
# UPS:
|
@@ -1,8 +1,13 @@
|
|
1
1
|
module ActiveModel
|
2
2
|
module Validations
|
3
3
|
class UrlValidator < EachValidator
|
4
|
+
class << self
|
5
|
+
attr_accessor :url_regex
|
6
|
+
end
|
7
|
+
# Damn complex regex found on GWave https://wave.google.com/wave/?pli=1#restored:wave:googlewave.com!w%252BsFbGJUukA
|
8
|
+
self.url_regex = /^(?#Protocol)(?:(?:ht|f)tp(?:s?)\:\/\/|~\/|\/)?(?#Username:Password)(?:\w+:\w+@)?(?#Subdomains)(?:(?:[-\w]+\.)+(?#TopLevel Domains)(?:com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|travel|[a-z]{2}))(?#Port)(?::[\d]{1,5})?(?#Directories)(?:(?:(?:\/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|\/)+|\?|#)?(?#Query)(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?#Anchor)(?:#(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)?$/
|
4
9
|
def validate_each(record, attribute, value)
|
5
|
-
unless value =~
|
10
|
+
unless value =~ self.class.url_regex
|
6
11
|
record.errors.add(attribute)
|
7
12
|
end
|
8
13
|
end
|
data/lib/activevalidators.rb
CHANGED
@@ -1,26 +1,18 @@
|
|
1
|
-
require 'active_support'
|
2
1
|
require 'active_model'
|
3
|
-
require 'active_record'
|
4
|
-
require 'active_support/all'
|
5
|
-
require 'active_model/validations'
|
6
2
|
|
7
3
|
module ActiveModel
|
8
4
|
module Validations
|
9
|
-
extend ActiveSupport::Autoload
|
10
|
-
|
11
5
|
def self.activevalidators
|
12
|
-
|
13
|
-
'TrackingNumber']
|
6
|
+
%w(email url respond_to phone slug ip credit_card date password twitter postal_code tracking_number)
|
14
7
|
end
|
15
8
|
|
16
|
-
#Eager autoload the library's validators into AR::Validations
|
17
9
|
activevalidators.each do |validator_name|
|
18
|
-
|
10
|
+
require "active_model/validations/#{validator_name}_validator"
|
19
11
|
end
|
20
12
|
|
21
13
|
#Defines methods like validates_credit_card
|
22
14
|
module HelperMethods
|
23
|
-
ActiveModel::Validations.activevalidators.
|
15
|
+
ActiveModel::Validations.activevalidators.each do |validator|
|
24
16
|
define_method('validates_'+validator) do |*fields|
|
25
17
|
options ||= (fields.delete fields.find { |f| f.kind_of? Hash}) || true
|
26
18
|
args = fields.push({ validator => options })
|
@@ -29,26 +29,43 @@ describe "Credit Card Validation" do
|
|
29
29
|
}
|
30
30
|
|
31
31
|
VALID_CARDS.each_pair do |card, number|
|
32
|
-
it
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
describe "it accepts #{card} cards" do
|
33
|
+
it "using a specific card type" do
|
34
|
+
subject = build_card_record({:card => number}, {:type => card})
|
35
|
+
assert card_is_valid?(subject)
|
36
|
+
end
|
37
|
+
it "using :credit_card => { :type => :any }" do
|
38
|
+
subject = build_card_record({:card => number}, {:type => :any})
|
39
|
+
assert card_is_valid?(subject)
|
40
|
+
end
|
41
|
+
it "using :credit_card => true" do
|
42
|
+
subject = build_card_record({:card => number}, true)
|
43
|
+
assert card_is_valid?(subject)
|
44
|
+
end
|
36
45
|
end
|
37
46
|
end
|
38
47
|
|
39
48
|
describe "for invalid cards" do
|
40
49
|
it "rejects invalid cards and generates an error message of type invalid" do
|
41
50
|
subject = build_card_record :card => '99999'
|
42
|
-
subject
|
43
|
-
subject.errors.size.must_equal 1
|
44
|
-
|
45
|
-
subject.errors[:card].include?(subject.errors.generate_message(:card, :invalid)).must_equal true
|
51
|
+
assert card_is_invalid?(subject)
|
46
52
|
end
|
47
53
|
end
|
48
54
|
|
49
|
-
def build_card_record(attrs = {})
|
55
|
+
def build_card_record(attrs = {}, validator = {:type => :any})
|
50
56
|
TestRecord.reset_callbacks(:validate)
|
51
|
-
TestRecord.validates :card, :credit_card =>
|
57
|
+
TestRecord.validates :card, :credit_card => validator
|
52
58
|
TestRecord.new attrs
|
53
59
|
end
|
60
|
+
|
61
|
+
def card_is_valid?(subject)
|
62
|
+
subject.valid?.must_equal true
|
63
|
+
subject.errors.size.must_equal 0
|
64
|
+
end
|
65
|
+
|
66
|
+
def card_is_invalid?(subject)
|
67
|
+
subject.valid?.must_equal false
|
68
|
+
subject.errors.size.must_equal 1
|
69
|
+
subject.errors[:card].include?(subject.errors.generate_message(:card, :invalid)).must_equal true
|
70
|
+
end
|
54
71
|
end
|
@@ -7,18 +7,33 @@ describe "Url Validation" do
|
|
7
7
|
TestRecord.new
|
8
8
|
end
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
10
|
+
describe "valid urls" do
|
11
|
+
it "accepts urls without port number" do
|
12
|
+
subject = build_url_record
|
13
|
+
subject.url = 'http://www.verrot.fr'
|
14
|
+
subject.valid?.must_equal true
|
15
|
+
subject.errors.size.must_equal 0
|
16
|
+
end
|
17
|
+
|
18
|
+
it "accepts urls with port number" do
|
19
|
+
subject = build_url_record
|
20
|
+
subject.url = 'http://www.verrot.fr:1234'
|
21
|
+
subject.valid?.must_equal true
|
22
|
+
subject.errors.size.must_equal 0
|
23
|
+
end
|
16
24
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
25
|
+
it "accepts urls with basic auth" do
|
26
|
+
subject = build_url_record
|
27
|
+
subject.url = 'http://foo:bar@www.verrot.fr'
|
28
|
+
subject.valid?.must_equal true
|
29
|
+
subject.errors.size.must_equal 0
|
30
|
+
end
|
31
|
+
it "accepts valid SSL urls" do
|
32
|
+
subject = build_url_record
|
33
|
+
subject.url = 'https://www.verrot.fr'
|
34
|
+
subject.valid?.must_equal true
|
35
|
+
subject.errors.size.must_equal 0
|
36
|
+
end
|
22
37
|
end
|
23
38
|
|
24
39
|
describe "for invalid urls" do
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activevalidators
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 11
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
8
|
+
- 7
|
9
9
|
- 0
|
10
|
-
version: 1.
|
10
|
+
version: 1.7.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Franck Verrot
|
@@ -20,7 +20,7 @@ autorequire:
|
|
20
20
|
bindir: bin
|
21
21
|
cert_chain: []
|
22
22
|
|
23
|
-
date: 2011-09-
|
23
|
+
date: 2011-09-27 00:00:00 Z
|
24
24
|
dependencies:
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: bundler
|