validators 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -22,6 +22,12 @@ Then add it to your Gemfile:
22
22
  validates :email, :email => true
23
23
  end
24
24
 
25
+ === validates_url_format_of
26
+
27
+ class User < ActiveRecord::Base
28
+ validates_url_format_of :site
29
+ end
30
+
25
31
  === validates_ownership_of
26
32
 
27
33
  class Task < ActiveRecord::Base
@@ -45,6 +51,14 @@ Then add it to your Gemfile:
45
51
  task.valid?
46
52
  #=> false
47
53
 
54
+ === validates_ip_address
55
+
56
+ class Server < ActiveRecord::Base
57
+ validates_ip_address :address
58
+ validates_ip_address :address, :only => :v4
59
+ validates_ip_address :address, :only => :v6
60
+ end
61
+
48
62
  == Maintainer
49
63
 
50
64
  * Nando Vieira - http://simplesideias.com.br
@@ -0,0 +1,30 @@
1
+ module Validators
2
+ EMAIL_FORMAT = /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
3
+
4
+ # Source: https://github.com/henrik/validates_url_format_of
5
+ IPv4_PART = /\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]/ # 0-255
6
+
7
+ if RUBY_VERSION >= "1.9"
8
+ URL_FORMAT = %r[
9
+ \A
10
+ https?:// # http:// or https://
11
+ ([^\s:@]+:[^\s:@]*@)? # optional username:pw@
12
+ ( (([^\W_]+\.)*xn--)?[^\W_]+([-.][^\W_]+)*\.[a-z]{2,6}\.? | # domain (including Punycode/IDN)...
13
+ #{IPv4_PART}(\.#{IPv4_PART}){3} ) # or IPv4
14
+ (:\d{1,5})? # optional port
15
+ ([/?]\S*)? # optional /whatever or ?whatever
16
+ \Z
17
+ ]ixs
18
+ else
19
+ URL_FORMAT = %r[
20
+ \A
21
+ https?:// # http:// or https://
22
+ ([^\s:@]+:[^\s:@]*@)? # optional username:pw@
23
+ ( (([^\W_]+\.)*xn--)?[^\W_]+([-.][^\W_]+)*\.[a-z]{2,6}\.? | # domain (including Punycode/IDN)...
24
+ #{IPv4_PART}(\.#{IPv4_PART}){3} ) # or IPv4
25
+ (:\d{1,5})? # optional port
26
+ ([/?]\S*)? # optional /whatever or ?whatever
27
+ \Z
28
+ ]ixu
29
+ end
30
+ end
@@ -0,0 +1,29 @@
1
+ module Validators
2
+ module Ip
3
+ extend self
4
+
5
+ # Extracted from Ruby 1.8.7
6
+ def v4?(addr)
7
+ matches = addr.match(/\A(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\Z/)
8
+ matches && matches.captures.all? {|i| i.to_i < 256}
9
+ end
10
+
11
+ # Extracted from Ruby 1.8.7
12
+ def v6?(addr)
13
+ # IPv6 (normal)
14
+ return true if /\A[\da-f]{1,4}(:[\da-f]{1,4})*\Z/i =~ addr
15
+ return true if /\A[\da-f]{1,4}(:[\da-f]{1,4})*::([\da-f]{1,4}(:[\da-f]{1,4})*)?\Z/i =~ addr
16
+ return true if /\A::([\da-f]{1,4}(:[\da-f]{1,4})*)?\Z/i =~ addr
17
+ # IPv6 (IPv4 compat)
18
+ return true if /\A[\da-f]{1,4}(:[\da-f]{1,4})*:/i =~ addr && v4?($')
19
+ return true if /\A[\da-f]{1,4}(:[\da-f]{1,4})*::([\da-f]{1,4}(:[\da-f]{1,4})*:)?/i =~ addr && v4?($')
20
+ return true if /\A::([\da-f]{1,4}(:[\da-f]{1,4})*:)?/i =~ addr && v4?($')
21
+
22
+ false
23
+ end
24
+
25
+ def valid?(addr)
26
+ v4?(addr) || v6?(addr)
27
+ end
28
+ end
29
+ end
@@ -21,6 +21,8 @@ module ActiveModel
21
21
  def validates_email_format_of(*attr_names)
22
22
  validates_with EmailValidator, _merge_attributes(attr_names)
23
23
  end
24
+
25
+ alias_method :validates_email, :validates_email_format_of
24
26
  end
25
27
  end
26
28
  end
@@ -0,0 +1,47 @@
1
+ module ActiveModel
2
+ module Validations
3
+ class IpAddressValidator < EachValidator
4
+ def validate_each(record, attribute, value)
5
+ return if value.blank? && options[:allow_blank]
6
+ return if value.nil? && options[:allow_nil]
7
+
8
+ valid = false
9
+
10
+ case options[:only]
11
+ when :v4
12
+ valid = Validators::Ip.v4?(value.to_s)
13
+ scope = :invalid_ipv4_address
14
+ when :v6
15
+ valid = Validators::Ip.v6?(value.to_s)
16
+ scope = :invalid_ipv6_address
17
+ else
18
+ valid = Validators::Ip.valid?(value.to_s)
19
+ scope = :invalid_ip_address
20
+ end
21
+
22
+ unless valid
23
+ record.errors.add(
24
+ attribute, scope,
25
+ :message => options[:message], :value => value
26
+ )
27
+ end
28
+ end
29
+
30
+ def check_validity!
31
+ raise ArgumentError, ":only accepts a symbol that can be either :v6 or :v4" if options.key?(:only) && ![:v4, :v6].include?(options[:only])
32
+ end
33
+ end
34
+
35
+ module ClassMethods
36
+ # Validates weather or not the specified URL is valid.
37
+ #
38
+ # validates_ip_address :ip #=> accepts both v4 and v6
39
+ # validates_ip_address :ip, :only => :v4
40
+ # validates_ip_address :ip, :only => :v6
41
+ #
42
+ def validates_ip_address(*attr_names)
43
+ validates_with IpAddressValidator, _merge_attributes(attr_names)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,28 @@
1
+ module ActiveModel
2
+ module Validations
3
+ class UrlValidator < EachValidator
4
+ def validate_each(record, attribute, value)
5
+ if value.to_s !~ Validators::URL_FORMAT
6
+ record.errors.add(
7
+ attribute, :invalid_url,
8
+ :message => options[:message], :value => value
9
+ )
10
+ end
11
+ end
12
+ end
13
+
14
+ module ClassMethods
15
+ # Validates weather or not the specified URL is valid.
16
+ #
17
+ # class User < ActiveRecord::Base
18
+ # validates_url_format_of :site
19
+ # end
20
+ #
21
+ def validates_url_format_of(*attr_names)
22
+ validates_with UrlValidator, _merge_attributes(attr_names)
23
+ end
24
+
25
+ alias_method :validates_url, :validates_url_format_of
26
+ end
27
+ end
28
+ end
@@ -2,7 +2,7 @@ module Validators
2
2
  module Version
3
3
  MAJOR = 0
4
4
  MINOR = 1
5
- PATCH = 0
5
+ PATCH = 1
6
6
  STRING = "#{MAJOR}.#{MINOR}.#{PATCH}"
7
7
  end
8
8
  end
data/lib/validators.rb CHANGED
@@ -1,7 +1,10 @@
1
1
  require "active_record"
2
+ require "validators/constants"
3
+ require "validators/validates_ip_address"
2
4
  require "validators/validates_email_format_of"
5
+ require "validators/validates_url_format_of"
3
6
  require "validators/validates_ownership_of"
4
7
 
5
8
  module Validators
6
- EMAIL_FORMAT = /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
9
+ autoload :Ip, "validators/ip"
7
10
  end
data/spec/schema.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  ActiveRecord::Schema.define(:version => 0) do
2
2
  create_table :users do |t|
3
- t.string :email, :corporate_email
3
+ t.string :email, :corporate_email, :url
4
4
  end
5
5
 
6
6
  create_table :categories do |t|
@@ -0,0 +1,20 @@
1
+ VALID_IPV4 = [
2
+ "192.168.1.1",
3
+ "64.233.163.104",
4
+ "127.0.0.1",
5
+ "0.0.0.0"
6
+ ]
7
+
8
+ VALID_IPV6 = [
9
+ "FE80:0000:0000:0000:0202:B3FF:FE1E:8329",
10
+ "fe80:0000:0000:0000:0202:b3ff:fe1e:8329",
11
+ "FE80::0202:B3FF:FE1E:8329",
12
+ "1050:0000:0000:0000:0005:0600:300c:326b",
13
+ "1050:0:0:0:5:600:300c:326b",
14
+ "ff06:0:0:0:0:0:0:c3",
15
+ "ff06::c3",
16
+ "0:0:0:0:0:0:192.1.56.10",
17
+ "3ffe:1900:4545:3:200:f8ff:fe21:67cf",
18
+ "fe80:0:0:0:200:f8ff:fe21:67cf",
19
+ "fe80::200:f8ff:fe21:67cf"
20
+ ]
@@ -4,6 +4,10 @@ en:
4
4
  messages:
5
5
  record_invalid: "Errors: %{errors}"
6
6
  invalid_email: "is not a valid address"
7
+ invalid_url: "is not a valid address"
8
+ invalid_ipv4_address: "is not a valid IPv4 address"
9
+ invalid_ipv6_address: "is not a valid IPv6 address"
10
+ invalid_address: "is not a valid IP address"
7
11
  invalid_owner: "is not associated with your user"
8
12
 
9
13
  pt-BR:
@@ -12,4 +16,5 @@ pt-BR:
12
16
  messages:
13
17
  record_invalid: "Erros: %{errors}"
14
18
  invalid_email: "não parece ser um e-mail válido"
19
+ invalid_url: "não parece ser uma URL válida"
15
20
  invalid_owner: "não está associado ao seu usuário"
@@ -0,0 +1,43 @@
1
+ # encoding: utf-8
2
+ VALID_URLS = [
3
+ 'http://example.com',
4
+ 'http://example.com/',
5
+ 'http://www.example.com/',
6
+ 'http://sub.domain.example.com/',
7
+ 'http://bbc.co.uk',
8
+ 'http://example.com?foo',
9
+ 'http://example.com?url=http://example.com',
10
+ 'http://example.com:8000',
11
+ 'http://www.sub.example.com/page.html?foo=bar&baz=%23#anchor',
12
+ 'http://user:pass@example.com',
13
+ 'http://user:@example.com',
14
+ 'http://example.com/~user',
15
+ 'http://example.xy', # Not a real TLD, but we're fine with anything of 2-6 chars
16
+ 'http://example.museum',
17
+ 'http://1.0.255.249',
18
+ 'http://1.2.3.4:80',
19
+ 'HttP://example.com',
20
+ 'https://example.com',
21
+ # 'http://räksmörgås.nu', # IDN
22
+ 'http://xn--rksmrgs-5wao1o.nu', # Punycode
23
+ 'http://www.xn--rksmrgs-5wao1o.nu',
24
+ 'http://foo.bar.xn--rksmrgs-5wao1o.nu',
25
+ 'http://example.com.', # Explicit TLD root period
26
+ 'http://example.com./foo'
27
+ ]
28
+
29
+ INVALID_URLS = [
30
+ "url",
31
+ "www.example.com",
32
+ "http://ex ample.com",
33
+ "http://example.com/foo bar",
34
+ 'http://256.0.0.1',
35
+ 'http://u:u:u@example.com',
36
+ 'http://r?ksmorgas.com',
37
+
38
+ # These can all be valid local URLs, but should not be considered valid
39
+ # for public consumption.
40
+ "http://example",
41
+ "http://example.c",
42
+ 'http://example.toolongtld'
43
+ ]
@@ -0,0 +1,25 @@
1
+ require "spec_helper"
2
+
3
+ describe Validators::Ip do
4
+ context "IPv4" do
5
+ VALID_IPV4.each do |ip|
6
+ it "should accept #{ip.inspect} as ip address" do
7
+ Validators::Ip.should be_v4(ip)
8
+ end
9
+ end
10
+ end
11
+
12
+ context "IPv6" do
13
+ VALID_IPV6.each do |ip|
14
+ it "should accept #{ip.inspect} as ip address" do
15
+ Validators::Ip.should be_v6(ip)
16
+ end
17
+ end
18
+ end
19
+
20
+ (VALID_IPV4 + VALID_IPV6).each do |ip|
21
+ it "should accept #{ip.inspect} as ip address" do
22
+ Validators::Ip.should be_valid(ip)
23
+ end
24
+ end
25
+ end
@@ -31,41 +31,41 @@ describe ".validates_email_format_of" do
31
31
  it "should use default error message" do
32
32
  user = User.new(:email => "invalid")
33
33
  user.should_not be_valid
34
- errors_for(user, :email).should == ["is not a valid address"]
34
+ user.errors[:email].should == ["is not a valid address"]
35
35
  end
36
36
 
37
37
  it "should reject nil value" do
38
38
  user = User.new(:email => nil)
39
39
  user.should_not be_valid
40
- errors_for(user, :email).should_not be_empty
40
+ user.errors[:email].should_not be_empty
41
41
  end
42
42
 
43
43
  it "should reject empty value" do
44
44
  user = User.new(:email => "")
45
45
  user.should_not be_valid
46
- errors_for(user, :email).should_not be_empty
46
+ user.errors[:email].should_not be_empty
47
47
  end
48
48
 
49
49
  it "should validate multiple attributes" do
50
50
  user = User.new(:corporate_email => "invalid")
51
51
  user.should_not be_valid
52
- errors_for(user, :corporate_email).should == ["is not a valid address"]
52
+ user.errors[:corporate_email].should == ["is not a valid address"]
53
53
  end
54
54
 
55
55
  it "should use custom error message as :message options" do
56
56
  buyer = Buyer.new(:email => "invalid")
57
57
  buyer.should_not be_valid
58
- errors_for(buyer, :email).should == ["is not a valid e-mail"]
58
+ buyer.errors[:email].should == ["is not a valid e-mail"]
59
59
  end
60
60
 
61
61
  it "should use I18n string as error message [pt-BR]" do
62
62
  I18n.locale = :'pt-BR'
63
63
  user = User.new(:email => "invalid")
64
64
  user.should_not be_valid
65
- errors_for(user, :email).should == ["não parece ser um e-mail válido"]
65
+ user.errors[:email].should == ["não parece ser um e-mail válido"]
66
66
  end
67
67
 
68
- def errors_for(record, attr_name)
69
- record.errors[attr_name]
68
+ it "should have alias method" do
69
+ User.should respond_to(:validates_email)
70
70
  end
71
71
  end
@@ -0,0 +1,59 @@
1
+ require "spec_helper"
2
+
3
+ describe ".validates_ip_address" do
4
+ subject { User.new }
5
+
6
+ context "IPv4" do
7
+ it "should be valid" do
8
+ User.validates_ip_address :url, :only => :v4
9
+ subject.url = "192.168.1.2"
10
+ subject.should be_valid
11
+ end
12
+
13
+ it "should not be valid" do
14
+ User.validates_ip_address :url, :only => :v4
15
+ subject.url = "FE80:0000:0000:0000:0202:B3FF:FE1E:8329"
16
+ subject.should_not be_valid
17
+ subject.errors[:url].should == ["is not a valid IPv4 address"]
18
+ end
19
+ end
20
+
21
+ context "IPv6" do
22
+ it "should be valid" do
23
+ User.validates_ip_address :url, :only => :v6
24
+ subject.url = "FE80:0000:0000:0000:0202:B3FF:FE1E:8329"
25
+ subject.should be_valid
26
+ end
27
+
28
+ it "should not be valid" do
29
+ User.validates_ip_address :url, :only => :v6
30
+ subject.url = "192.168.1.2"
31
+ subject.should_not be_valid
32
+ subject.errors[:url].should == ["is not a valid IPv6 address"]
33
+ end
34
+ end
35
+
36
+ it "should be valid with IPv4" do
37
+ User.validates_ip_address :url
38
+ subject.url = "192.168.1.2"
39
+ subject.should be_valid
40
+ end
41
+
42
+ it "should be valid with IPv6" do
43
+ User.validates_ip_address :url
44
+ subject.url = "FE80:0000:0000:0000:0202:B3FF:FE1E:8329"
45
+ subject.should be_valid
46
+ end
47
+
48
+ it "should allow blank values" do
49
+ User.validates_ip_address :url, :allow_blank => true
50
+ subject.url = ""
51
+ subject.should be_valid
52
+ end
53
+
54
+ it "should allow nil values" do
55
+ User.validates_ip_address :url, :allow_nil => true
56
+ subject.url = nil
57
+ subject.should be_valid
58
+ end
59
+ end
@@ -0,0 +1,39 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+
4
+ describe ".validates_url_format_of" do
5
+ before do
6
+ User.validates_url_format_of :url, :allow_blank => false
7
+ end
8
+
9
+ VALID_URLS.each do |url|
10
+ it "should accept #{url.inspect} as a valid url" do
11
+ user = User.new(:url => url)
12
+ user.should be_valid
13
+ end
14
+ end
15
+
16
+ INVALID_URLS.each do |url|
17
+ it "should reject #{url.inspect} as a valid url" do
18
+ user = User.new(:url => url)
19
+ user.should_not be_valid
20
+ end
21
+ end
22
+
23
+ it "should have alias method" do
24
+ User.should respond_to(:validates_url)
25
+ end
26
+
27
+ it "should use default error message" do
28
+ user = User.new(:url => "invalid")
29
+ user.should_not be_valid
30
+ user.errors[:url].should == ["is not a valid address"]
31
+ end
32
+
33
+ it "should use I18n string as error message [pt-BR]" do
34
+ I18n.locale = :'pt-BR'
35
+ user = User.new(:url => "invalid")
36
+ user.should_not be_valid
37
+ user.errors[:url].should == ["não parece ser uma URL válida"]
38
+ end
39
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 0
9
- version: 0.1.0
8
+ - 1
9
+ version: 0.1.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - Nando Vieira
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-11-10 00:00:00 -02:00
17
+ date: 2010-11-11 00:00:00 -02:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -89,16 +89,25 @@ files:
89
89
  - README.rdoc
90
90
  - Rakefile
91
91
  - lib/validators.rb
92
+ - lib/validators/constants.rb
93
+ - lib/validators/ip.rb
92
94
  - lib/validators/validates_email_format_of.rb
95
+ - lib/validators/validates_ip_address.rb
93
96
  - lib/validators/validates_ownership_of.rb
97
+ - lib/validators/validates_url_format_of.rb
94
98
  - lib/validators/version.rb
95
99
  - spec/schema.rb
96
100
  - spec/spec_helper.rb
97
101
  - spec/support/emails.rb
102
+ - spec/support/ips.rb
98
103
  - spec/support/models.rb
99
104
  - spec/support/translations.yml
105
+ - spec/support/urls.rb
106
+ - spec/validators/ip_spec.rb
100
107
  - spec/validators/validates_email_format_of_spec.rb
108
+ - spec/validators/validates_ip_address_spec.rb
101
109
  - spec/validators/validates_ownership_of_spec.rb
110
+ - spec/validators/validates_url_format_of_spec.rb
102
111
  - validators.gemspec
103
112
  has_rdoc: true
104
113
  homepage: http://rubygems.org/gems/validators
@@ -136,7 +145,12 @@ test_files:
136
145
  - spec/schema.rb
137
146
  - spec/spec_helper.rb
138
147
  - spec/support/emails.rb
148
+ - spec/support/ips.rb
139
149
  - spec/support/models.rb
140
150
  - spec/support/translations.yml
151
+ - spec/support/urls.rb
152
+ - spec/validators/ip_spec.rb
141
153
  - spec/validators/validates_email_format_of_spec.rb
154
+ - spec/validators/validates_ip_address_spec.rb
142
155
  - spec/validators/validates_ownership_of_spec.rb
156
+ - spec/validators/validates_url_format_of_spec.rb