url_validator 0.0.2
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/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.markdown +0 -0
- data/Rakefile +14 -0
- data/init.rb +2 -0
- data/lib/url_validator.rb +60 -0
- data/lib/url_validator/version.rb +4 -0
- data/spec/models/user_spec.rb +240 -0
- data/spec/resources/user.rb +8 -0
- data/spec/resources/user_with_ar.rb +6 -0
- data/spec/resources/user_with_blank.rb +8 -0
- data/spec/resources/user_with_custom_scheme.rb +8 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +25 -0
- data/url_validator.gemspec +28 -0
- metadata +153 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.markdown
ADDED
File without changes
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rake'
|
5
|
+
require 'spec/rake/spectask'
|
6
|
+
|
7
|
+
Bundler::GemHelper.install_tasks
|
8
|
+
|
9
|
+
|
10
|
+
Spec::Rake::SpecTask.new('spec') do |t|
|
11
|
+
t.spec_opts = ['--options', "spec/spec.opts"]
|
12
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
13
|
+
end
|
14
|
+
|
data/init.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'active_model'
|
3
|
+
require 'addressable/uri'
|
4
|
+
|
5
|
+
module ActiveModel
|
6
|
+
module Validations
|
7
|
+
class UrlValidator < ActiveModel::Validator
|
8
|
+
|
9
|
+
def validate(record)
|
10
|
+
schemes = options[:schemes] || %w(http https).join('|')
|
11
|
+
message = options[:message] || "is not a valid URL"
|
12
|
+
url_regexp = /^((#{schemes}):\/\/){0,1}[a-z0-9]+([a-z0-9\-\.]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/ix
|
13
|
+
|
14
|
+
options[:attributes].each do |attribute|
|
15
|
+
value = record.send(attribute).to_s
|
16
|
+
next if value.blank? && (options[:allow_blank] || options[:allow_nil])
|
17
|
+
normalized_value = record.send(attribute.to_s + '_normalized')
|
18
|
+
begin
|
19
|
+
uri = Addressable::URI.parse(value)
|
20
|
+
unless url_regexp =~ normalized_value
|
21
|
+
record.errors.add(attribute, message, :value => uri.to_s)
|
22
|
+
end
|
23
|
+
rescue Addressable::URI::InvalidURIError
|
24
|
+
record.errors.add(attribute, message, :value => uri.to_s)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
module ClassMethods
|
33
|
+
# Validates whether the value of the specified attribute is valid url.
|
34
|
+
#
|
35
|
+
# class User
|
36
|
+
# include ActiveModel::Validations
|
37
|
+
# attr_accessor :website, :ftpsite
|
38
|
+
# validates_url :website, :allow_blank => true
|
39
|
+
# validates_url :ftpsite, :schemes => ['ftp']
|
40
|
+
# end
|
41
|
+
# Configuration options:
|
42
|
+
# * <tt>:message</tt> - A custom error message (default is: "is not a valid URL").
|
43
|
+
# * <tt>:allow_nil</tt> - If set to true, skips this validation if the attribute is +nil+ (default is +false+).
|
44
|
+
# * <tt>:allow_blank</tt> - If set to true, skips this validation if the attribute is blank (default is +false+).
|
45
|
+
# * <tt>:schemes</tt> - Array of URI schemes to validate against. (default is +['http', 'https']+)
|
46
|
+
def validates_url(*attr_names)
|
47
|
+
attrs = attr_names.take_while{|a| !a.instance_of?(Hash)}
|
48
|
+
attrs.each do |a_name|
|
49
|
+
class_eval <<-EOF
|
50
|
+
def #{a_name}_normalized
|
51
|
+
Addressable::IDNA.to_ascii(#{a_name}.to_s)
|
52
|
+
end
|
53
|
+
EOF
|
54
|
+
end
|
55
|
+
validates_with UrlValidator, _merge_attributes(attr_names)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
@@ -0,0 +1,240 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "User" do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
ActiveRecord::Schema.define(:version => 1) do
|
7
|
+
|
8
|
+
create_table :users, :force => true do |t|
|
9
|
+
t.column :website, :string
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
after(:all) do
|
15
|
+
ActiveRecord::Base.connection.drop_table(:users)
|
16
|
+
end
|
17
|
+
|
18
|
+
context "with regular validator" do
|
19
|
+
before do
|
20
|
+
@user = User.new
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should not allow nil as url" do
|
24
|
+
@user.website = nil
|
25
|
+
@user.should_not be_valid
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should not allow blank as url" do
|
29
|
+
@user.website = ''
|
30
|
+
@user.should_not be_valid
|
31
|
+
end
|
32
|
+
|
33
|
+
it "www.website.c should not be valid" do
|
34
|
+
@user.website = 'www.website.c'
|
35
|
+
@user.should_not be_valid
|
36
|
+
end
|
37
|
+
|
38
|
+
it "www.web site.com should not be valid" do
|
39
|
+
@user.website = 'www.web site.com'
|
40
|
+
@user.should_not be_valid
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should not accept invalid URLs" do
|
44
|
+
["htt://www.website.com", "htttp://www.website.com",
|
45
|
+
"http:/www.website.com", "http://website"].each do |url|
|
46
|
+
@user.website = url
|
47
|
+
@user.should_not be_valid
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should accept different kind of valid URLs" do
|
52
|
+
["http://www.website.com", "https://www.website.com/",
|
53
|
+
"www.website.com", "website.com"].each do |url|
|
54
|
+
@user.website = url
|
55
|
+
@user.should be_valid
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it "website.com should be valid" do
|
60
|
+
@user.website = 'website.com'
|
61
|
+
@user.should be_valid
|
62
|
+
@user.errors[:website].should be_empty
|
63
|
+
end
|
64
|
+
|
65
|
+
it "wEbsIte.coM should be valid" do
|
66
|
+
@user.website = 'wEbsIte.coM'
|
67
|
+
@user.should be_valid
|
68
|
+
@user.errors[:website].should be_empty
|
69
|
+
end
|
70
|
+
|
71
|
+
it "http://12pointdesign.com/advice/dashes_vs_underscores.asp should be valid" do
|
72
|
+
@user.website = 'http://12pointdesign.com/advice/dashes_vs_underscores.asp'
|
73
|
+
@user.should be_valid
|
74
|
+
@user.errors[:website].should be_empty
|
75
|
+
end
|
76
|
+
|
77
|
+
it "stage.website.com/m/65/John_Oconer should be valid" do
|
78
|
+
@user.website = 'stage.website.com/m/65/John_Oconer'
|
79
|
+
@user.should be_valid
|
80
|
+
@user.errors[:website].should be_empty
|
81
|
+
end
|
82
|
+
|
83
|
+
it "http://website.com/~smith//// should be valid" do
|
84
|
+
@user.website = 'http://website.com/~smith////'
|
85
|
+
@user.should be_valid
|
86
|
+
@user.errors[:website].should be_empty
|
87
|
+
end
|
88
|
+
|
89
|
+
it "www.website.com/~smith//// should be valid" do
|
90
|
+
@user.website = 'www.website.com/~smith////'
|
91
|
+
@user.should be_valid
|
92
|
+
@user.errors[:website].should be_empty
|
93
|
+
end
|
94
|
+
|
95
|
+
it "website.com/~smith//a// should be valid" do
|
96
|
+
@user.website = 'website.com/~smith//a//'
|
97
|
+
@user.should be_valid
|
98
|
+
@user.errors[:website].should be_empty
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
context "with allow blank" do
|
105
|
+
before do
|
106
|
+
@user = UserWithBlank.new
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should allow nil as url" do
|
110
|
+
@user.website = nil
|
111
|
+
@user.should be_valid
|
112
|
+
@user.errors[:website].should be_empty
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should allow blank as url" do
|
116
|
+
@user.website = ""
|
117
|
+
@user.should be_valid
|
118
|
+
@user.errors[:website].should be_empty
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should allow a valid url" do
|
122
|
+
@user.website = "http://www.website.com"
|
123
|
+
@user.should be_valid
|
124
|
+
@user.errors[:website].should be_empty
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
context "with ActiveRecord" do
|
129
|
+
before do
|
130
|
+
@user = UserWithAr.new
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should not allow invalid url: website" do
|
134
|
+
@user.website = "website"
|
135
|
+
@user.should_not be_valid
|
136
|
+
@user.errors[:website].should_not be_empty
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should not allow invalid url: website.c" do
|
140
|
+
@user.website = "website.c"
|
141
|
+
@user.should_not be_valid
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context "with regular validator and custom scheme ftp://" do
|
146
|
+
before do
|
147
|
+
@user = UserWithCustomScheme.new
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should allow alternative URI schemes" do
|
151
|
+
@user.website = "ftp://ftp.website.com"
|
152
|
+
@user.should be_valid
|
153
|
+
end
|
154
|
+
|
155
|
+
it "website.com should not be valid - scheme is ftp" do
|
156
|
+
@user.website = 'http://website.com'
|
157
|
+
@user.should_not be_valid
|
158
|
+
end
|
159
|
+
|
160
|
+
end
|
161
|
+
|
162
|
+
context "check validate with different charset" do
|
163
|
+
before do
|
164
|
+
@user = UserWithAr.new
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should be valid http://www.中国政府.政务.cn" do
|
168
|
+
@user.website = "http://www.中国政府.政务.cn"
|
169
|
+
@user.should be_valid
|
170
|
+
@user.errors[:website].should be_empty
|
171
|
+
end
|
172
|
+
|
173
|
+
it "should be valid www.詹姆斯.com" do
|
174
|
+
@user.website = "www.詹姆斯.com"
|
175
|
+
@user.should be_valid
|
176
|
+
@user.errors[:website].should be_empty
|
177
|
+
end
|
178
|
+
|
179
|
+
it "should not be valid http://www.詹姆斯.c" do
|
180
|
+
@user.website = "www.詹姆斯.c"
|
181
|
+
@user.should_not be_valid
|
182
|
+
@user.errors[:website].should_not be_empty
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
|
187
|
+
context "check normalizing" do
|
188
|
+
before do
|
189
|
+
@user = User.new
|
190
|
+
end
|
191
|
+
|
192
|
+
it "should convert correctly http://website.com/~smith/" do
|
193
|
+
@user.website = "http://website.com/~smith/"
|
194
|
+
@user.website_normalized.should == "http://website.com/~smith/"
|
195
|
+
end
|
196
|
+
|
197
|
+
it "should convert correctly website.com" do
|
198
|
+
@user.website = "website.com"
|
199
|
+
@user.website_normalized.should == "website.com"
|
200
|
+
end
|
201
|
+
|
202
|
+
it "should be equivalent to リ宠퐱卄.com" do
|
203
|
+
@user.website = "リ宠퐱卄.com"
|
204
|
+
@user.website_normalized.should == "xn--eek174hoxfpr4k.com"
|
205
|
+
end
|
206
|
+
|
207
|
+
it "should be equivalent to www.詹姆斯.com" do
|
208
|
+
@user.website = "www.詹姆斯.com"
|
209
|
+
@user.website_normalized.should == "www.xn--8ws00zhy3a.com"
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should convert 'www.Iñtërnâtiônàlizætiøn.com' correctly" do
|
213
|
+
@user.website = "www.Iñtërnâtiônàlizætiøn.com"
|
214
|
+
@user.website_normalized.should == "www.xn--itrntinliztin-vdb0a5exd8ewcye.com"
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
context "when custom message is set" do
|
219
|
+
before do
|
220
|
+
@user = User.new
|
221
|
+
end
|
222
|
+
|
223
|
+
it "should show correct message" do
|
224
|
+
@user.valid?
|
225
|
+
@user.errors[:website].to_s.should == 'bad bad URL'
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
context "when custom message is not set" do
|
230
|
+
before do
|
231
|
+
@user = UserWithAr.new
|
232
|
+
end
|
233
|
+
|
234
|
+
it "should show correct message" do
|
235
|
+
@user.valid?
|
236
|
+
@user.errors[:website].to_s.should == 'is not a valid URL'
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/resources')
|
3
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
4
|
+
|
5
|
+
require 'rubygems'
|
6
|
+
require 'spec'
|
7
|
+
require 'sqlite3'
|
8
|
+
require 'active_record'
|
9
|
+
require 'active_record/base'
|
10
|
+
require 'active_record/migration'
|
11
|
+
require 'ruby-debug'
|
12
|
+
|
13
|
+
ActiveRecord::Migration.verbose = false
|
14
|
+
ActiveRecord::Base.establish_connection(
|
15
|
+
"adapter" => "sqlite3",
|
16
|
+
"database" => ":memory:"
|
17
|
+
)
|
18
|
+
|
19
|
+
require File.join(File.dirname(__FILE__), '..', 'init')
|
20
|
+
|
21
|
+
autoload :User ,'resources/user'
|
22
|
+
autoload :UserWithBlank ,'resources/user_with_blank'
|
23
|
+
autoload :UserWithAr ,'resources/user_with_ar'
|
24
|
+
autoload :UserWithCustomScheme ,'resources/user_with_custom_scheme'
|
25
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "url_validator/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "url_validator"
|
7
|
+
s.version = UrlValidator::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Zdenko Nevrala"]
|
10
|
+
s.email = ["nevralaz@gmail.com"]
|
11
|
+
s.homepage = "http://github.com/zdenal/url_validator"
|
12
|
+
s.summary = %q{URL validator}
|
13
|
+
s.description = %q{URL validator with normalize URL from different charset}
|
14
|
+
|
15
|
+
s.rubyforge_project = "url_validator"
|
16
|
+
|
17
|
+
s.add_development_dependency "rspec"
|
18
|
+
s.add_development_dependency "ruby-debug"
|
19
|
+
s.add_development_dependency "sqlite3"
|
20
|
+
s.add_dependency "rails", "3.0.1"
|
21
|
+
s.add_dependency "addressable"
|
22
|
+
|
23
|
+
s.files = `git ls-files`.split("\n")
|
24
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
25
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
26
|
+
s.require_paths = ["lib"]
|
27
|
+
end
|
28
|
+
|
metadata
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: url_validator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Zdenko Nevrala
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-04-03 00:00:00 +02:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: rspec
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: ruby-debug
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
47
|
+
type: :development
|
48
|
+
version_requirements: *id002
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: sqlite3
|
51
|
+
prerelease: false
|
52
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
type: :development
|
62
|
+
version_requirements: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: rails
|
65
|
+
prerelease: false
|
66
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
68
|
+
requirements:
|
69
|
+
- - "="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
hash: 5
|
72
|
+
segments:
|
73
|
+
- 3
|
74
|
+
- 0
|
75
|
+
- 1
|
76
|
+
version: 3.0.1
|
77
|
+
type: :runtime
|
78
|
+
version_requirements: *id004
|
79
|
+
- !ruby/object:Gem::Dependency
|
80
|
+
name: addressable
|
81
|
+
prerelease: false
|
82
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
hash: 3
|
88
|
+
segments:
|
89
|
+
- 0
|
90
|
+
version: "0"
|
91
|
+
type: :runtime
|
92
|
+
version_requirements: *id005
|
93
|
+
description: URL validator with normalize URL from different charset
|
94
|
+
email:
|
95
|
+
- nevralaz@gmail.com
|
96
|
+
executables: []
|
97
|
+
|
98
|
+
extensions: []
|
99
|
+
|
100
|
+
extra_rdoc_files: []
|
101
|
+
|
102
|
+
files:
|
103
|
+
- .gitignore
|
104
|
+
- Gemfile
|
105
|
+
- README.markdown
|
106
|
+
- Rakefile
|
107
|
+
- init.rb
|
108
|
+
- lib/url_validator.rb
|
109
|
+
- lib/url_validator/version.rb
|
110
|
+
- spec/models/user_spec.rb
|
111
|
+
- spec/resources/user.rb
|
112
|
+
- spec/resources/user_with_ar.rb
|
113
|
+
- spec/resources/user_with_blank.rb
|
114
|
+
- spec/resources/user_with_custom_scheme.rb
|
115
|
+
- spec/spec.opts
|
116
|
+
- spec/spec_helper.rb
|
117
|
+
- url_validator.gemspec
|
118
|
+
has_rdoc: true
|
119
|
+
homepage: http://github.com/zdenal/url_validator
|
120
|
+
licenses: []
|
121
|
+
|
122
|
+
post_install_message:
|
123
|
+
rdoc_options: []
|
124
|
+
|
125
|
+
require_paths:
|
126
|
+
- lib
|
127
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
128
|
+
none: false
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
hash: 3
|
133
|
+
segments:
|
134
|
+
- 0
|
135
|
+
version: "0"
|
136
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ">="
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
hash: 3
|
142
|
+
segments:
|
143
|
+
- 0
|
144
|
+
version: "0"
|
145
|
+
requirements: []
|
146
|
+
|
147
|
+
rubyforge_project: url_validator
|
148
|
+
rubygems_version: 1.3.7
|
149
|
+
signing_key:
|
150
|
+
specification_version: 3
|
151
|
+
summary: URL validator
|
152
|
+
test_files: []
|
153
|
+
|