missing_validators 0.5.2 → 0.6.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 CHANGED
@@ -73,6 +73,8 @@ You can specify domains to which the URL domain should belong in one of the folo
73
73
  validates :url, url: { domains: :com }
74
74
  validates :url, url: { domains: [:com, 'edu'] }
75
75
  validates :url, url: { root: true }
76
+ validates :url, url: { scheme: :http }
77
+ validates :url, url: { scheme: [:http, 'https'] }
76
78
 
77
79
  RSpec matcher is also available for your convenience:
78
80
 
@@ -14,18 +14,32 @@ class UrlValidator < ActiveModel::EachValidator
14
14
  # @param [Object] value attribute value
15
15
  def validate_each(record, attribute, value)
16
16
  uri = URI.parse(value)
17
- raise URI::InvalidURIError unless uri.kind_of?(URI::HTTP)
18
17
 
19
- domains = Array.wrap(options[:domain])
20
- host = uri.host.downcase
21
- in_valid_domain = domains.empty? || domains.any? { |domain| host.end_with?(".#{domain.downcase}") }
22
- raise URI::InvalidURIError unless in_valid_domain
18
+ unless uri.kind_of?(URI::HTTP) \
19
+ && in_valid_top_level_domains?(uri, Array.wrap(options[:domain])) \
20
+ && with_valid_scheme?(uri, Array.wrap(options[:scheme])) \
21
+ && (!!!options[:root] || is_root?(uri))
23
22
 
24
- must_be_domain_root = options[:root] || false
25
- if must_be_domain_root && (!['/', ''].include?(uri.path) || uri.query.present? || uri.fragment.present?)
26
23
  raise URI::InvalidURIError
27
24
  end
25
+
28
26
  rescue URI::InvalidURIError
29
27
  record.errors[attribute] << (options[:message] || I18n.t('errors.messages.url'))
30
28
  end
29
+
30
+ private
31
+
32
+ def in_valid_top_level_domains?(uri, tlds)
33
+ host_downcased = uri.host.downcase
34
+ tlds.empty? || tlds.map(&:downcase).any? { |domain| host_downcased.end_with?(".#{domain}") }
35
+ end
36
+
37
+ def with_valid_scheme?(uri, schemes)
38
+ scheme_downcased = uri.scheme.downcase
39
+ schemes.empty? || schemes.map(&:to_s).map(&:downcase).any? { |scheme| scheme_downcased == scheme }
40
+ end
41
+
42
+ def is_root?(uri)
43
+ ['/', ''].include?(uri.path) && uri.query.blank? && uri.fragment.blank?
44
+ end
31
45
  end
@@ -1,5 +1,5 @@
1
1
  # Provides a collection of custom validators that are often required in Rails applications.
2
2
  module MissingValidators
3
3
  # Gem version.
4
- VERSION = "0.5.2"
4
+ VERSION = "0.6.0"
5
5
  end
@@ -35,62 +35,69 @@ describe UrlValidator do
35
35
  it { should_not allow_value("http://user_example.a").for(:url) }
36
36
  end
37
37
 
38
- context "url is in the specific domain" do
39
- context "url specified as symbol" do
40
- let(:klass) do
41
- Class.new do
42
- include ActiveModel::Validations
43
- attr_accessor :url, :name
44
- validates :url, url: { domain: :org }
45
- end
38
+ describe "url must be in a specific domain" do
39
+ let(:klass) do
40
+ Class.new do
41
+ include ActiveModel::Validations
42
+ attr_accessor :url1, :url2
43
+ validates :url1, url: { domain: :org }
44
+ validates :url2, url: { domain: [:org, 'edu', 'Com.Au'] }
46
45
  end
46
+ end
47
47
 
48
- subject { klass.new }
48
+ subject { klass.new }
49
49
 
50
- it { should ensure_valid_url_format_of(:url) }
51
- it { should_not ensure_valid_url_format_of(:name) }
50
+ it { should allow_value("http://example.org").for(:url1) }
51
+ it { should_not allow_value("http://example.com").for(:url1) }
52
52
 
53
- it { should allow_value("http://example.org").for(:url) }
54
- it { should_not allow_value("http://example.com").for(:url) }
55
- end
53
+ it { should allow_value("http://example.org").for(:url2) }
54
+ it { should allow_value("http://example.edu").for(:url2) }
55
+ it { should allow_value("http://example.com.au").for(:url2) }
56
+ it { should allow_value("http://example.Com.Au").for(:url2) }
57
+ it { should_not allow_value("http://example.com").for(:url2) }
58
+ end
56
59
 
57
- context "url specified as array of strings and symbols" do
58
- let(:klass) do
59
- Class.new do
60
- include ActiveModel::Validations
61
- attr_accessor :url, :name
62
- validates :url, url: { domain: [:org, 'edu', 'Com.Au'] }
63
- end
60
+ describe "url must be domain root" do
61
+ let(:klass) do
62
+ Class.new do
63
+ include ActiveModel::Validations
64
+ attr_accessor :url1, :url2
65
+ validates :url1, url: { root: true }
66
+ validates :url2, url: { root: false }
64
67
  end
68
+ end
65
69
 
66
- subject { klass.new }
70
+ subject { klass.new }
67
71
 
68
- it { should ensure_valid_url_format_of(:url) }
69
- it { should_not ensure_valid_url_format_of(:name) }
72
+ it { should allow_value("http://example.org").for(:url1) }
73
+ it { should allow_value("http://example.org/").for(:url1) }
74
+ it { should_not allow_value("http://example.com/test").for(:url1) }
75
+ it { should_not allow_value("http://example.com/#fragment").for(:url1) }
76
+ it { should_not allow_value("http://example.com/?key=value").for(:url1) }
70
77
 
71
- it { should allow_value("http://example.org").for(:url) }
72
- it { should allow_value("http://example.edu").for(:url) }
73
- it { should allow_value("http://example.com.au").for(:url) }
74
- it { should allow_value("http://example.Com.Au").for(:url) }
75
- it { should_not allow_value("http://example.com").for(:url) }
76
- end
78
+
79
+ it { should allow_value("http://example.org").for(:url2) }
80
+ it { should allow_value("http://example.org/lorem").for(:url2) }
77
81
  end
78
82
 
79
- context "url must be domain root" do
83
+ describe "url must have a specific scheme" do
80
84
  let(:klass) do
81
85
  Class.new do
82
86
  include ActiveModel::Validations
83
- attr_accessor :url, :name
84
- validates :url, url: { root: true }
87
+ attr_accessor :url1, :url2
88
+ validates :url1, url: { scheme: 'http' }
89
+ validates :url2, url: { scheme: ['HTTP', :https] }
85
90
  end
86
91
  end
87
92
 
88
93
  subject { klass.new }
89
94
 
90
- it { should allow_value("http://example.org").for(:url) }
91
- it { should allow_value("http://example.org/").for(:url) }
92
- it { should_not allow_value("http://example.com/test").for(:url) }
93
- it { should_not allow_value("http://example.com/#fragment").for(:url) }
94
- it { should_not allow_value("http://example.com/?key=value").for(:url) }
95
+ it { should allow_value("http://example.org").for(:url1) }
96
+ it { should_not allow_value("https://example.org").for(:url1) }
97
+
98
+ it { should allow_value("http://example.org").for(:url2) }
99
+ it { should allow_value("https://example.org").for(:url2) }
100
+ it { should allow_value("HTTPS://example.org").for(:url2) }
101
+ it { should_not allow_value("ftp://example.org").for(:url2) }
95
102
  end
96
103
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: missing_validators
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.2
4
+ version: 0.6.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-10-11 00:00:00.000000000 Z
12
+ date: 2013-10-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70277040464020 !ruby/object:Gem::Requirement
16
+ requirement: &70348494356240 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70277040464020
24
+ version_requirements: *70348494356240
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: shoulda-matchers
27
- requirement: &70277040463440 !ruby/object:Gem::Requirement
27
+ requirement: &70348494355460 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70277040463440
35
+ version_requirements: *70348494355460
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: activemodel
38
- requirement: &70277040462560 !ruby/object:Gem::Requirement
38
+ requirement: &70348494354760 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 3.0.0
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70277040462560
46
+ version_requirements: *70348494354760
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: activesupport
49
- requirement: &70277040461820 !ruby/object:Gem::Requirement
49
+ requirement: &70348494353960 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,7 +54,7 @@ dependencies:
54
54
  version: 3.0.0
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70277040461820
57
+ version_requirements: *70348494353960
58
58
  description: Validates email addresses, URLs, and inequality of attributes.
59
59
  email:
60
60
  - andrew.gridnev@gmail.com