diff --git a/.rspec b/.rspec index 62c58f0..8c18f1a 100644 --- a/.rspec +++ b/.rspec @@ -1 +1,2 @@ --cfs +--format documentation +--color diff --git a/.ruby-gemset b/.ruby-gemset new file mode 100644 index 0000000..f26935d --- /dev/null +++ b/.ruby-gemset @@ -0,0 +1 @@ +url_validation diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000..8e8299d --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +2.4.2 diff --git a/Gemfile b/Gemfile index b6a9705..dbf5df6 100644 --- a/Gemfile +++ b/Gemfile @@ -1,13 +1,18 @@ -source :rubygems +source 'https://rubygems.org' -gem 'addressable', :require => 'addressable/uri' # for unicode URIs +gem 'addressable', require: 'addressable/uri' # for unicode URIs gem 'activesupport' gem 'activerecord' gem 'httpi' group :development do - gem 'jeweler' - gem 'yard' - gem 'RedCloth', require: 'redcloth' + # PUBLISHING + gem 'juwelier' + + # DOCS + gem 'yard', require: nil + gem 'redcarpet', require: nil + + # SPECS gem 'rspec' end diff --git a/Gemfile.lock b/Gemfile.lock index bbf69f5..5809ee1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,53 +1,107 @@ GEM - remote: http://rubygems.org/ + remote: https://rubygems.org/ specs: - RedCloth (4.2.7) - activemodel (3.0.7) - activesupport (= 3.0.7) - builder (~> 2.1.2) - i18n (~> 0.5.0) - activerecord (3.0.7) - activemodel (= 3.0.7) - activesupport (= 3.0.7) - arel (~> 2.0.2) - tzinfo (~> 0.3.23) - activesupport (3.0.7) - addressable (2.2.6) - arel (2.0.10) - builder (2.1.2) - diff-lcs (1.1.2) - git (1.2.5) - httpi (0.9.4) - pyu-ntlm-http (>= 0.1.3.1) + activemodel (5.1.5) + activesupport (= 5.1.5) + activerecord (5.1.5) + activemodel (= 5.1.5) + activesupport (= 5.1.5) + arel (~> 8.0) + activesupport (5.1.5) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (~> 0.7) + minitest (~> 5.1) + tzinfo (~> 1.1) + addressable (2.5.2) + public_suffix (>= 2.0.2, < 4.0) + arel (8.0.0) + builder (3.2.3) + concurrent-ruby (1.0.5) + descendants_tracker (0.0.4) + thread_safe (~> 0.3, >= 0.3.1) + diff-lcs (1.3) + faraday (0.12.2) + multipart-post (>= 1.2, < 3) + git (1.3.0) + github_api (0.18.2) + addressable (~> 2.4) + descendants_tracker (~> 0.0.4) + faraday (~> 0.8) + hashie (~> 3.5, >= 3.5.2) + oauth2 (~> 1.0) + hashie (3.5.7) + highline (1.7.10) + httpi (2.4.3) rack - i18n (0.5.0) - jeweler (1.6.0) - bundler (~> 1.0.0) - git (>= 1.2.5) + socksify + i18n (0.9.5) + concurrent-ruby (~> 1.0) + juwelier (2.4.9) + builder + bundler + git + github_api + highline + kamelcase (~> 0) + nokogiri + psych rake - pyu-ntlm-http (0.1.3.1) - rack (1.3.0) - rake (0.9.0) - rspec (2.6.0) - rspec-core (~> 2.6.0) - rspec-expectations (~> 2.6.0) - rspec-mocks (~> 2.6.0) - rspec-core (2.6.3) - rspec-expectations (2.6.0) - diff-lcs (~> 1.1.2) - rspec-mocks (2.6.0) - tzinfo (0.3.27) - yard (0.7.1) + rdoc + semver2 + jwt (1.5.6) + kamelcase (0.0.2) + semver2 (~> 3) + mini_portile2 (2.3.0) + minitest (5.11.3) + multi_json (1.13.1) + multi_xml (0.6.0) + multipart-post (2.0.0) + nokogiri (1.8.2) + mini_portile2 (~> 2.3.0) + oauth2 (1.4.0) + faraday (>= 0.8, < 0.13) + jwt (~> 1.0) + multi_json (~> 1.3) + multi_xml (~> 0.5) + rack (>= 1.2, < 3) + psych (3.0.2) + public_suffix (3.0.2) + rack (2.0.4) + rake (12.3.1) + rdoc (6.0.2) + redcarpet (3.4.0) + rspec (3.7.0) + rspec-core (~> 3.7.0) + rspec-expectations (~> 3.7.0) + rspec-mocks (~> 3.7.0) + rspec-core (3.7.1) + rspec-support (~> 3.7.0) + rspec-expectations (3.7.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.7.0) + rspec-mocks (3.7.0) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.7.0) + rspec-support (3.7.1) + semver2 (3.4.2) + socksify (1.7.1) + thread_safe (0.3.6) + tzinfo (1.2.5) + thread_safe (~> 0.1) + yard (0.9.12) PLATFORMS ruby DEPENDENCIES - RedCloth activerecord activesupport addressable httpi - jeweler + juwelier + redcarpet rspec yard + +BUNDLED WITH + 1.16.1 diff --git a/README.md b/README.md new file mode 100644 index 0000000..5896c84 --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +# url_validation + +Simple URL validator for Rails 3. + +| | | +|:------------|:--------------------------------| +| **Author** | Tim Morgan | +| **Version** | 1.0 (May 9, 2011) | +| **License** | Released under the MIT license. | + +## About + +This gem adds a very simple URL format validator to be used with Active Record +models in Rails 3.0. It supports localized error messages. It can validate many +different kinds of URLs, including HTTP and HTTPS. It supports advanced +validation features like sending `HEAD` requests to URLS to verify that they are +valid endpoints. + +## Installation + +Add the gem to your project's Gemfile: + +``` ruby +gem 'url_validation' +``` + +## Usage + +This gem is an `EachValidator`, and thus is used with the `validates` method: + +``` ruby +class User < ActiveRecord::Base + validates :terms_of_service_link, + presence: true, + url: true +end +``` + +There are other options to fine-tune your validation; see the {UrlValidator} +class for more, and for a list of error message localization keys. diff --git a/README.textile b/README.textile deleted file mode 100644 index 713ebcb..0000000 --- a/README.textile +++ /dev/null @@ -1,36 +0,0 @@ -h1. url_validation -- Simple URL validator for Rails 3 - -| *Author* | Tim Morgan | -| *Version* | 1.0 (May 9, 2011) | -| *License* | Released under the MIT license. | - -h2. About - -This gem adds a very simple URL format validator to be used with ActiveRecord -models in Rails 3.0. It supports localized error messages. It can validate many -different kinds of URLs, including HTTP and HTTPS. It supports advanced -validation features like sending @HEAD@ requests to URLS to verify that they are -valid endpoints. - -h2. Installation - -Add the gem to your project's @Gemfile@: - -
-gem 'url_validation'
-
-
-h2. Usage
-
-This gem is an @EachValidator@, and thus is used with the @validates@ method:
-
-
-class User < ActiveRecord::Base
- validates :terms_of_service_link,
- :presence => true,
- :url => true
-end
-
-
-There are other options to fine-tune your validation; see the {UrlValidator}
-class for more, and for a list of error message localization keys.
diff --git a/Rakefile b/Rakefile
index 61308f6..7902e2a 100644
--- a/Rakefile
+++ b/Rakefile
@@ -9,30 +9,30 @@ rescue Bundler::BundlerError => e
end
require 'rake'
-require 'jeweler'
-Jeweler::Tasks.new do |gem|
- gem.name = "url_validation"
- gem.summary = %Q{Simple URL validation in Rails 3}
+require 'juwelier'
+Juwelier::Tasks.new do |gem|
+ gem.name = 'url_validation'
+ gem.summary = %Q{Simple URL validation in Rails 3+}
gem.description = %Q{A simple, localizable EachValidator for URL fields in ActiveRecord 3.0.}
- gem.email = "git@timothymorgan.info"
- gem.homepage = "http://github.com/riscfuture/url_validation"
- gem.authors = [ "Tim Morgan" ]
- gem.required_ruby_version = '>= 1.8.7'
+ gem.email = 'git@timothymorgan.info'
+ gem.homepage = 'http://github.com/riscfuture/url_validation'
+ gem.authors = ['Tim Morgan']
+ gem.required_ruby_version = '>= 2.0.0'
end
-Jeweler::RubygemsDotOrgTasks.new
+Juwelier::RubygemsDotOrgTasks.new
require 'yard'
YARD::Rake::YardocTask.new('doc') do |doc|
- doc.options << "-m" << "textile"
- doc.options << "--protected" << "--no-private"
- doc.options << "-r" << "README.textile"
- doc.options << "-o" << "doc"
- doc.options << "--title" << "url_validation Documentation".inspect
-
- doc.files = [ 'lib/*_validator.rb', 'README.textile' ]
+ doc.options << '-m' << 'markdown' << '-M' << 'redcarpet'
+ doc.options << '--protected' << '--no-private'
+ doc.options << '-r' << 'README.md'
+ doc.options << '-o' << 'doc'
+ doc.options << '--title' << 'url_validation Documentation'.inspect
+
+ doc.files = %w(lib/**/*.rb README.md)
end
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new
-task :default => :spec
+task default: :spec
diff --git a/VERSION b/VERSION
index afaf360..867e524 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.0.0
\ No newline at end of file
+1.2.0
\ No newline at end of file
diff --git a/lib/url_validation.rb b/lib/url_validation.rb
index 0313568..2f97a88 100644
--- a/lib/url_validation.rb
+++ b/lib/url_validation.rb
@@ -2,163 +2,183 @@
require 'httpi'
require 'active_support/core_ext/hash/except'
require 'active_model/validator'
+require 'active_support/core_ext/array/wrap'
# Validates URLs. Uses the following I18n error message keys:
#
-# | @invalid_url@ | URL is improperly formatted. |
-# | @url_not_accessible@ | Couldn't connect to the URL. |
-# | @url_invalid_response@ | Got a bad HTTP response (not of an acceptable type, e.g., 2xx). |
+# | | |
+# |:-----------------------|:----------------------------------------------------------------|
+# | `invalid_url` | URL is improperly formatted. |
+# | `url_not_accessible` | Couldn't connect to the URL. |
+# | `url_invalid_response` | Got a bad HTTP response (not of an acceptable type, e.g., 2xx). |
#
# @example Checks the syntax only
-# validates :link, :url => true
+# validates :link, url: true
#
# @example Ensures the host is available but does not check the path
-# validates :link, :url => { :check_host => true }
+# validates :link, url: {check_host: true}
#
# @example Ensures that the host is available and that a request for the path does not return a 4xx or 5xx response
-# validates :link, :url => { :check_path => true }
+# validates :link, url: {check_path: true}
#
# @example Ensures that the host is available and that a request for the path does not return a 3xx, 4xx, or 5xx response
-# validates :link, :url => { :check_path => [ 300..399, 400..499, 500..599 ] }
+# validates :link, url: {check_path: [300..399, 400..499, 500..599]}
#
# @example Checks for host accessibility with a custom timeout
-# validates :link, :url => {
-# :check_host => true,
-# :request_callback => lambda { |request| request.timeout = 30 }
+# validates :link, url: {
+# check_host: true,
+# request_callback: ->(request) { request.timeout = 30 }
# }
#
-# h2. Options
+# ## Options
#
-# h3. Basic options
+# ### Basic options
#
-# | @:allow_nil@ | If @true@, @nil@ values are allowed. |
-# | @:allow_blank@ | If @true@, @nil@ or empty values are allowed. |
+# | | |
+# |:------------------|:------------------------------------------------------------|
+# | `:allow_nil` | If `true`, `nil` values are allowed. |
+# | `:allow_blank` | If `true`, `nil` or empty values are allowed. |
+# | `:require_domain` | If `true`, A domain must be present to be considered valid. |
#
-# h3. Error messages
+# ### Error messages
#
-# | @:invalid_url_message@ | A custom message to use in place of @:invalid_url@. |
-# | @:incorrect_url_type_message@ | A custom message to use in place of @:incorrect_url_type@. |
-# | @:url_not_accessible_message@ | A custom message to use in place of @:url_not_accessible@. |
-# | @:url_invalid_response_message@ | A custom message to use in place of @:url_invalid_response@. |
+# | | |
+# |:--------------------------------|:-------------------------------------------------------------|
+# | `:invalid_url_message` | A custom message to use in place of `:invalid_url`. |
+# | `:incorrect_url_type_message` | A custom message to use in place of `:incorrect_url_type`. |
+# | `:url_not_accessible_message` | A custom message to use in place of `:url_not_accessible`. |
+# | `:url_invalid_response_message` | A custom message to use in place of `:url_invalid_response`. |
#
-# h3. Networkless URL validation
+# ### Networkless URL validation
#
-# | @:scheme@ | A string or array of strings, such as "http" or "ftp", indicating which URL schemes are valid. By default only ==HTTP(S)== URLs are accepted. |
-# | @:default_scheme@ | A default URL scheme to try for improper URLs. If this is set to, e.g., "http", then when a URL like "whoops.com" is given (which would otherwise fail due to an improper format), "http://whoops.com" will be tried instead. |
+# | | |
+# |:------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+# | `:scheme` | A string or array of strings, such as "http" or "ftp", indicating which URL schemes are valid. By default only HTTP(S) URLs are accepted. |
+# | `:default_scheme` | A default URL scheme to try for improper URLs. If this is set to, e.g., "http", then when a URL like "whoops.com" is given (which would otherwise fail due to an improper format), "http://whoops.com" will be tried instead. |
#
-# h3. Over-the-network URL validation
+# ### Over-the-network URL validation
#
# The HTTPI gem is used to provide a generic interface to whatever HTTP client
# you wish to use. This allows you to drop in, e.g., a Curl client if you want.
-# You can set the HTTPI adapter with the @:httpi_adapter@ option.
+# You can set the HTTPI adapter with the `:httpi_adapter` option.
#
-# | @:check_host@ | If @true@, the validator will perform a network test to verify that it can connect to the server and access the host (at the "/" path). This check will only be performed for ==HTTP(S)== URLs. |
-# | @:check_path@ | An integer or symbol (or array of integers or symbols), such as 301 or @:moved_permanently@, indicating what response codes are unacceptable. You can also use ranges, and include them in an array, such as @[ :moved_permanently, 400..404, 500..599 ]@. By default, this is @nil@, and therefore only host accessibility is checked. If @true@ is given, uses a default set of invalid error codes (4xx and 5xx). Implies @:check_host@ is also true. |
-# | @:httpi_adapter@ | The HTTPI adapter to use for checking HTTP and HTTPS URLs (default set by the HTTPI gem). |
+# | | |
+# |:-----------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+# | `:check_host` | If `true`, the validator will perform a network test to verify that it can connect to the server and access the host (at the "/" path). This check will only be performed for HTTP(S) URLs. |
+# | `:check_path` | An integer or symbol (or array of integers or symbols), such as 301 or `:moved_permanently`, indicating what response codes are unacceptable. You can also use ranges, and include them in an array, such as `[:moved_permanently, 400..404, 500..599]`. By default, this is `nil`, and therefore only host accessibility is checked. If `true` is given, uses a default set of invalid error codes (4xx and 5xx). Implies `:check_host` is also true. |
+# | `:httpi_adapter` | The HTTPI adapter to use for checking HTTP and HTTPS URLs (default set by the HTTPI gem). |
#
-# h3. Other options
+# ### Other options
#
-# | @:request_callback@ | A proc that receives the request object (for ==HTTP(S)== requests, the @HTTPI::Request@ object) before it is executed. You can use this proc to set, e.g., custom headers or timeouts on the request. |
-# | @:response_callback@ | A proc that receives the response object after it is executed by @:check_path@, when it is enabled. This is useful for checking redirect URL's, etc. |
+# | | |
+# |:--------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+# | `:request_callback` | A proc that receives the request object (for HTTP(S) requests, the `HTTPI::Request` object) before it is executed. You can use this proc to set, e.g., custom headers or timeouts on the request. |
class UrlValidator < ActiveModel::EachValidator
# @private
CODES = {
- :continue => 100,
- :switching_protocols => 101,
- :processing => 102,
- :ok => 200,
- :created => 201,
- :accepted => 202,
- :non_authoritative_information => 203,
- :no_content => 204,
- :reset_content => 205,
- :partial_content => 206,
- :multi_status => 207,
- :im_used => 226,
- :multiple_choices => 300,
- :moved_permanently => 301,
- :found => 302,
- :see_other => 303,
- :not_modified => 304,
- :use_proxy => 305,
- :reserved => 306,
- :temporary_redirect => 307,
- :bad_request => 400,
- :unauthorized => 401,
- :payment_required => 402,
- :forbidden => 403,
- :not_found => 404,
- :method_not_allowed => 405,
- :not_acceptable => 406,
- :proxy_authentication_required => 407,
- :request_timeout => 408,
- :conflict => 409,
- :gone => 410,
- :length_required => 411,
- :precondition_failed => 412,
- :request_entity_too_large => 413,
- :request_uri_too_long => 414,
- :unsupported_media_type => 415,
- :requested_range_not_satisfiable => 416,
- :expectation_failed => 417,
- :unprocessable_entity => 422,
- :locked => 423,
- :failed_dependency => 424,
- :upgrade_required => 426,
- :internal_server_error => 500,
- :not_implemented => 501,
- :bad_gateway => 502,
- :service_unavailable => 503,
- :gateway_timeout => 504,
- :http_version_not_supported => 505,
- :variant_also_negotiates => 506,
- :insufficient_storage => 507,
- :not_extended => 510
+ continue: 100,
+ switching_protocols: 101,
+ processing: 102,
+ ok: 200,
+ created: 201,
+ accepted: 202,
+ non_authoritative_information: 203,
+ no_content: 204,
+ reset_content: 205,
+ partial_content: 206,
+ multi_status: 207,
+ im_used: 226,
+ multiple_choices: 300,
+ moved_permanently: 301,
+ found: 302,
+ see_other: 303,
+ not_modified: 304,
+ use_proxy: 305,
+ reserved: 306,
+ temporary_redirect: 307,
+ bad_request: 400,
+ unauthorized: 401,
+ payment_required: 402,
+ forbidden: 403,
+ not_found: 404,
+ method_not_allowed: 405,
+ not_acceptable: 406,
+ proxy_authentication_required: 407,
+ request_timeout: 408,
+ conflict: 409,
+ gone: 410,
+ length_required: 411,
+ precondition_failed: 412,
+ request_entity_too_large: 413,
+ request_uri_too_long: 414,
+ unsupported_media_type: 415,
+ requested_range_not_satisfiable: 416,
+ expectation_failed: 417,
+ unprocessable_entity: 422,
+ locked: 423,
+ failed_dependency: 424,
+ upgrade_required: 426,
+ internal_server_error: 500,
+ not_implemented: 501,
+ bad_gateway: 502,
+ service_unavailable: 503,
+ gateway_timeout: 504,
+ http_version_not_supported: 505,
+ variant_also_negotiates: 506,
+ insufficient_storage: 507,
+ not_extended: 510
}
-
-
+
# @private
def validate_each(record, attribute, value)
- return if options[:allow_nil] and value.nil?
- return if options[:allow_blank] and value.blank?
-
- uri = Addressable::URI.parse(value)
- if uri.scheme.nil? and options[:default_scheme] then
- uri = Addressable::URI.parse("#{options[:default_scheme]}://#{value}")
+ return if value.blank?
+
+ begin
+ uri = Addressable::URI.parse(value)
+
+ if uri.scheme.nil? and options[:default_scheme]
+ uri = Addressable::URI.parse("#{options[:default_scheme]}://#{value}")
+ end
+ rescue Addressable::URI::InvalidURIError
+ record.errors.add(attribute, options[:invalid_url_message] || :invalid_url) if uri.nil? || !url_format_valid?(uri, options)
+ return
end
-
- record.errors.add(attribute, options[:invalid_url_message] || :invalid_url) unless url_format_valid?(uri, options)
- record.errors.add(attribute, options[:url_not_accessible_message] || :url_not_accessible) unless response = url_accessible?(uri, options)
- record.errors.add(attribute, options[:url_invalid_response_message] || :url_invalid_response) unless url_response_valid?(response, record, attribute, value, options)
+
+ record.errors.add(attribute, options[:invalid_url_message] || :invalid_url) unless url_format_valid?(uri, options)
+ record.errors.add(attribute, options[:url_not_accessible_message] || :url_not_accessible) unless response = url_accessible?(uri, options)
+ record.errors.add(attribute, options[:url_invalid_response_message] || :url_invalid_response) unless url_response_valid?(response, options)
end
-
+
private
-
+
def url_format_valid?(uri, options)
- return false unless Array.wrap(options[:scheme] || %w( http https )).include?(uri.scheme)
-
+ return false unless Array.wrap(options[:scheme] || %w(http https)).include?(uri.scheme)
+
case uri.scheme
when 'http', 'https'
- return http_url_format_valid?(uri)
+ return http_url_format_valid?(uri, options)
else
return true
end
end
-
- def http_url_format_valid?(uri)
- uri.host.present? and not uri.path.nil?
+
+ def http_url_format_valid?(uri, options)
+ valid_format = uri.host.present? and not uri.path.nil?
+ return valid_format unless options[:require_domain]
+
+ valid_format and uri.domain.present?
end
-
+
def url_accessible?(uri, options)
return true unless options[:check_host] or options[:check_path]
-
+
check_host = options[:check_host]
- check_host ||= %w( http https ) if options[:check_path]
- if (schemes = Array.wrap(check_host)) and schemes.all? { |scheme| scheme.kind_of?(String) } then
+ check_host ||= %w(http https) if options[:check_path]
+ if (schemes = Array.wrap(check_host)) and schemes.all? { |scheme| scheme.kind_of?(String) }
return true unless schemes.include?(uri.scheme)
end
-
+
case uri.scheme
when 'http', 'https'
return http_url_accessible?(uri, options)
@@ -174,16 +194,15 @@ def http_url_accessible?(uri, options)
rescue
return false
end
-
- def url_response_valid?(response, record, attribute, value, options)
+
+ def url_response_valid?(response, options)
return true unless response.kind_of?(HTTPI::Response) and options[:check_path]
- options[:response_callback].call(response, record, attribute, value) if options[:response_callback].respond_to?(:call)
response_codes = options[:check_path] == true ? [400..499, 500..599] : Array.wrap(options[:check_path]).flatten
return response_codes.none? do |code| # it's good if it's not a bad response
case code # and it's a bad response if...
when Range
code.include? response.code
- when Fixnum
+ when Integer
code == response.code
when Symbol
CODES.include?(code) && CODES[code] == response.code
diff --git a/spec/url_validator_spec.rb b/spec/url_validator_spec.rb
index 5e6a365..6676443 100644
--- a/spec/url_validator_spec.rb
+++ b/spec/url_validator_spec.rb
@@ -11,229 +11,233 @@ class Record
@record = Record.new
end
- context "[basic]" do
+ context '[basic]' do
it "should allow nil if :allow_nil is set" do
- @validator = UrlValidator.new(:attributes => [ :field ], :allow_nil => true)
+ @validator = UrlValidator.new(attributes: %i(field), allow_nil: true)
@validator.validate_each(@record, :field, nil)
- @record.errors.should be_empty
+ expect(@record.errors).to be_empty
end
it "should allow \"\" if :allow_blank is set" do
- @validator = UrlValidator.new(:attributes => [ :field ], :allow_blank => true)
+ @validator = UrlValidator.new(attributes: %i(field), allow_blank: true)
@validator.validate_each(@record, :field, "")
- @record.errors.should be_empty
+ expect(@record.errors).to be_empty
end
end
-
- context "[format]" do
+
+ context '[format]' do
it "should only allow HTTP URLs if :scheme is set to 'http'" do
- @validator = UrlValidator.new(:attributes => [ :field ], :scheme => 'http')
- @validator.validate_each(@record, :field, "http://www.apple.com")
- @record.errors.should be_empty
+ @validator = UrlValidator.new(attributes: %i(field), scheme: 'http')
+ @validator.validate_each(@record, :field, 'http://www.apple.com')
+ expect(@record.errors).to be_empty
- @validator.validate_each(@record, :field, "https://www.apple.com")
- @record.errors[:field].first.should include('invalid_url')
+ @validator.validate_each(@record, :field, 'https://www.apple.com')
+ expect(@record.errors[:field].first).to include('invalid_url')
end
- it "should only allow HTTP and HTTPS URLs if :scheme is set to %w( http https )" do
- @validator = UrlValidator.new(:attributes => [ :field ], :scheme => %w( http https ))
- @validator.validate_each(@record, :field, "http://www.apple.com")
- @record.errors.should be_empty
- @validator.validate_each(@record, :field, "https://www.apple.com")
- @record.errors.should be_empty
+ it "should only allow HTTP and HTTPS URLs if :scheme is set to %w(http https)" do
+ @validator = UrlValidator.new(attributes: %i(field), scheme: %w(http https))
+ @validator.validate_each(@record, :field, 'http://www.apple.com')
+ expect(@record.errors).to be_empty
+ @validator.validate_each(@record, :field, 'https://www.apple.com')
+ expect(@record.errors).to be_empty
- @validator.validate_each(@record, :field, "ftp://www.apple.com")
- @record.errors[:field].first.should include('invalid_url')
+ @validator.validate_each(@record, :field, 'ftp://www.apple.com')
+ expect(@record.errors[:field].first).to include('invalid_url')
end
it "should try a default scheme if :default_scheme is set" do
- @validator = UrlValidator.new(:attributes => [ :field ], :scheme => 'http', :default_scheme => 'http')
- @validator.validate_each(@record, :field, "www.apple.com")
- @record.errors.should be_empty
+ @validator = UrlValidator.new(attributes: %i(field), scheme: 'http', default_scheme: 'http')
+ @validator.validate_each(@record, :field, 'www.apple.com')
+ expect(@record.errors).to be_empty
end
-
- context "[HTTP(S)]" do
+
+ it "should only allow URLs with a domain if :require_domain is set" do
+ @validator = UrlValidator.new(attributes: %i(field), require_domain: true)
+ @validator.validate_each(@record, :field, 'http://apple.com')
+ expect(@record.errors).to be_empty
+
+ @validator.validate_each(@record, :field, 'http://apple')
+ expect(@record.errors[:field].first).to include('invalid_url')
+ end
+
+ context '[HTTP(S)]' do
it "should not allow garbage URLs that still somehow pass the ridiculously open-ended RFC" do
- @validator = UrlValidator.new(:attributes => [ :field ])
-
- [
- 'http:sdg.sdfg/',
- 'http/sdg.d',
- 'http:://dsfg.dsfg/',
- 'http//sdg..g',
- 'http://://sdfg.f',
- 'http://dsaf.com://sdg.com'
- ].each do |uri|
+ @validator = UrlValidator.new(attributes: %i(field))
+
+ %w(
+ http:sdg.sdfg/
+ http/sdg.d
+ http:://dsfg.dsfg/
+ http//sdg..g
+ http://://sdfg.f).each do |uri|
@record.errors.clear
- @validator.validate_each(@record, :field, "www.apple.com")
- @record.errors[:field].first.should include('invalid_url')
+ @validator.validate_each(@record, :field, uri)
+ expect(@record.errors[:field].first).to include('invalid_url')
end
end
+
+ it "should not allow invalid scheme formats" do
+ @validator = UrlValidator.new(attributes: %i(field))
+ @validator.validate_each(@record, :field, ' https://www.apple.com')
+ expect(@record.errors[:field].first).to include('invalid_url')
+ end
end
end
-
- context "[accessibility]" do
- context "[:check_host]" do
+
+ context '[accessibility]' do
+ context '[:check_host]' do
it "should only validate if the host is accessible when :check_host is set" do
- @validator = UrlValidator.new(:attributes => [ :field ])
- @validator.validate_each(@record, :field, "http://www.invalid.tld")
- @record.errors.should be_empty
+ @validator = UrlValidator.new(attributes: %i(field))
+ @validator.validate_each(@record, :field, 'http://www.invalid.tld')
+ expect(@record.errors).to be_empty
- @validator = UrlValidator.new(:attributes => [ :field ], :check_host => true)
- @validator.validate_each(@record, :field, "http://www.invalid.tld")
- @record.errors[:field].first.should include('url_not_accessible')
+ @validator = UrlValidator.new(attributes: %i(field), check_host: true)
+ @validator.validate_each(@record, :field, 'http://www.invalid.tld')
+ expect(@record.errors[:field].first).to include('url_not_accessible')
end
it "should not perform the accessibility check if :check_host is set to 'http' and the URL scheme is not HTTP" do
- @validator = UrlValidator.new(:attributes => [ :field ], :check_host => 'http')
- @validator.validate_each(@record, :field, "https://www.invalid.tld")
- @record.errors.should be_empty
+ @validator = UrlValidator.new(attributes: %i(field), check_host: 'http')
+ @validator.validate_each(@record, :field, 'https://www.invalid.tld')
+ expect(@record.errors).to be_empty
end
it "should only validate if the host is accessible when :check_host is set to 'http' and the URL scheme is HTTP" do
- @validator = UrlValidator.new(:attributes => [ :field ], :check_host => 'http')
- @validator.validate_each(@record, :field, "http://www.invalid.tld")
- @record.errors[:field].first.should include('url_not_accessible')
+ @validator = UrlValidator.new(attributes: %i(field), check_host: 'http')
+ @validator.validate_each(@record, :field, 'http://www.invalid.tld')
+ expect(@record.errors[:field].first).to include('url_not_accessible')
end
- it "should not perform the accessibility check if :check_host is set to %w( http https ) and the URL scheme is not HTTP(S)" do
- @validator = UrlValidator.new(:attributes => [ :field ], :check_host => %w( http https ), :scheme => %w( ftp http https ))
- @validator.validate_each(@record, :field, "ftp://www.invalid.tld")
- @record.errors.should be_empty
+ it "should not perform the accessibility check if :check_host is set to %w(http https) and the URL scheme is not HTTP(S)" do
+ @validator = UrlValidator.new(attributes: %i(field), check_host: %w(http https), scheme: %w(ftp http https))
+ @validator.validate_each(@record, :field, 'ftp://www.invalid.tld')
+ expect(@record.errors).to be_empty
end
-
- it "should only validate if the host is accessible when :check_host is set to %w( http https ) and the URL scheme is HTTP(S)" do
- @validator = UrlValidator.new(:attributes => [ :field ], :check_host => %w( http https ))
- @validator.validate_each(@record, :field, "http://www.invalid.tld")
- @record.errors[:field].first.should include('url_not_accessible')
- @validator = UrlValidator.new(:attributes => [ :field ], :check_host => %w( http https ))
- @validator.validate_each(@record, :field, "https://www.invalid.tld")
- @record.errors[:field].first.should include('url_not_accessible')
+ it "should only validate if the host is accessible when :check_host is set to %w(http https) and the URL scheme is HTTP(S)" do
+ @validator = UrlValidator.new(attributes: %i(field), check_host: %w(http https))
+ @validator.validate_each(@record, :field, 'http://www.invalid.tld')
+ expect(@record.errors[:field].first).to include('url_not_accessible')
+
+ @validator = UrlValidator.new(attributes: %i(field), check_host: %w(http https))
+ @validator.validate_each(@record, :field, 'https://www.invalid.tld')
+ expect(@record.errors[:field].first).to include('url_not_accessible')
end
it "should only validate the host" do
- @validator = UrlValidator.new(:attributes => [ :field ], :check_host => true)
- @validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
- @record.errors.should be_empty
+ @validator = UrlValidator.new(attributes: %i(field), check_host: true)
+ @validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
+ expect(@record.errors).to be_empty
end
end
-
- context "[:check_path]" do
- it "should not validate if the response code is equal to the Fixnum value of this option" do
- @validator = UrlValidator.new(:attributes => [ :field ], :check_path => 404)
- @validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
- @record.errors[:field].first.should include('url_invalid_response')
-
+
+ context '[:check_path]' do
+ it "should not validate if the response code is equal to the Integer value of this option" do
+ @validator = UrlValidator.new(attributes: %i(field), check_path: 404)
+ @validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
+ expect(@record.errors[:field].first).to include('url_invalid_response')
+
@record.errors.clear
-
- @validator = UrlValidator.new(:attributes => [ :field ], :check_path => 405)
- @validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
- @record.errors[:field].should be_empty
+
+ @validator = UrlValidator.new(attributes: %i(field), check_path: 405)
+ @validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
+ expect(@record.errors[:field]).to be_empty
end
-
+
it "should not validate if the response code is equal to the Symbol value of this option" do
- @validator = UrlValidator.new(:attributes => [ :field ], :check_path => :not_found)
- @validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
- @record.errors[:field].first.should include('url_invalid_response')
-
+ @validator = UrlValidator.new(attributes: %i(field), check_path: :not_found)
+ @validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
+ expect(@record.errors[:field].first).to include('url_invalid_response')
+
@record.errors.clear
-
- @validator = UrlValidator.new(:attributes => [ :field ], :check_path => :unauthorized)
- @validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
- @record.errors[:field].should be_empty
+
+ @validator = UrlValidator.new(attributes: %i(field), check_path: :unauthorized)
+ @validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
+ expect(@record.errors[:field]).to be_empty
end
-
+
it "should not validate if the response code is within the Range value of this option" do
- @validator = UrlValidator.new(:attributes => [ :field ], :check_path => 400..499)
- @validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
- @record.errors[:field].first.should include('url_invalid_response')
-
+ @validator = UrlValidator.new(attributes: %i(field), check_path: 400..499)
+ @validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
+ expect(@record.errors[:field].first).to include('url_invalid_response')
+
@record.errors.clear
-
- @validator = UrlValidator.new(:attributes => [ :field ], :check_path => 500..599)
- @validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
- @record.errors[:field].should be_empty
- end
-
- it "should not validate if the response code is equal to the Fixnum value contained in the Array value of this option" do
- @validator = UrlValidator.new(:attributes => [ :field ], :check_path => [ 404, 405 ])
- @validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
- @record.errors[:field].first.should include('url_invalid_response')
-
+
+ @validator = UrlValidator.new(attributes: %i(field), check_path: 500..599)
+ @validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
+ expect(@record.errors[:field]).to be_empty
+ end
+
+ it "should not validate if the response code is equal to the Integer value contained in the Array value of this option" do
+ @validator = UrlValidator.new(attributes: %i(field), check_path: [404, 405])
+ @validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
+ expect(@record.errors[:field].first).to include('url_invalid_response')
+
@record.errors.clear
-
- @validator = UrlValidator.new(:attributes => [ :field ], :check_path => [ 405, 406 ])
- @validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
- @record.errors[:field].should be_empty
+
+ @validator = UrlValidator.new(attributes: %i(field), check_path: [405, 406])
+ @validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
+ expect(@record.errors[:field]).to be_empty
end
-
+
it "should not validate if the response code is equal to the Symbol value contained in the Array value of this option" do
- @validator = UrlValidator.new(:attributes => [ :field ], :check_path => [ :not_found, :unauthorized ])
- @validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
- @record.errors[:field].first.should include('url_invalid_response')
-
+ @validator = UrlValidator.new(attributes: %i(field), check_path: %i(not_found unauthorized))
+ @validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
+ expect(@record.errors[:field].first).to include('url_invalid_response')
+
@record.errors.clear
-
- @validator = UrlValidator.new(:attributes => [ :field ], :check_path => [ :unauthorized, :moved_permanently ])
- @validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
- @record.errors[:field].should be_empty
+
+ @validator = UrlValidator.new(attributes: %i(field), check_path: %i(unauthorized moved_permanently))
+ @validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
+ expect(@record.errors[:field]).to be_empty
end
-
+
it "should not validate if the response code is equal to the Range value contained in the Array value of this option" do
- @validator = UrlValidator.new(:attributes => [ :field ], :check_path => [ 400..499, 500..599 ])
- @validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
- @record.errors[:field].first.should include('url_invalid_response')
-
+ @validator = UrlValidator.new(attributes: %i(field), check_path: [400..499, 500..599])
+ @validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
+ expect(@record.errors[:field].first).to include('url_invalid_response')
+
@record.errors.clear
-
- @validator = UrlValidator.new(:attributes => [ :field ], :check_path => [ 500..599, 300..399 ])
- @validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
- @record.errors[:field].should be_empty
+
+ @validator = UrlValidator.new(attributes: %i(field), check_path: [500..599, 300..399])
+ @validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
+ expect(@record.errors[:field]).to be_empty
end
-
+
it "should skip validation by default" do
- @validator = UrlValidator.new(:attributes => [ :field ], :check_path => nil)
- @validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
- @record.errors[:field].should be_empty
+ @validator = UrlValidator.new(attributes: %i(field), check_path: nil)
+ @validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
+ expect(@record.errors[:field]).to be_empty
end
-
+
it "should not validate 4xx and 5xx response codes if the value is true" do
- @validator = UrlValidator.new(:attributes => [ :field ], :check_path => true)
- @validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
- @record.errors[:field].first.should include('url_invalid_response')
+ @validator = UrlValidator.new(attributes: %i(field), check_path: true)
+ @validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
+ expect(@record.errors[:field].first).to include('url_invalid_response')
end
-
+
it "should skip validation for non-HTTP URLs" do
- @validator = UrlValidator.new(:attributes => [ :field ], :check_path => true, :scheme => %w( ftp http https ))
- @validator.validate_each(@record, :field, "ftp://ftp.sdgasdgohaodgh.com/sdgjsdg")
- @record.errors[:field].should be_empty
+ @validator = UrlValidator.new(attributes: %i(field), check_path: true, scheme: %w(ftp http https))
+ @validator.validate_each(@record, :field, 'ftp://ftp.sdgasdgohaodgh.com/sdgjsdg')
+ expect(@record.errors[:field]).to be_empty
end
end
-
- context "[:httpi_adapter]" do
+
+ context '[:httpi_adapter]' do
it "should use the specified HTTPI adapter" do
- @validator = UrlValidator.new(:attributes => [ :field ], :httpi_adapter => :curl, :check_host => true)
- HTTPI.should_receive(:get).once.with(an_instance_of(HTTPI::Request), :curl).and_return(false)
- @validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
- end
- end
-
- context "[:request_callback]" do
- it "should be yielded the HTTPI request" do
- called = false
- @validator = UrlValidator.new(:attributes => [ :field ], :check_host => true, :request_callback => lambda { |request| called = true; request.should be_kind_of(HTTPI::Request) })
- @validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
- called.should be_true
+ @validator = UrlValidator.new(attributes: %i(field), httpi_adapter: :curl, check_host: true)
+ expect(HTTPI).to receive(:get).once.with(an_instance_of(HTTPI::Request), :curl).and_return(false)
+ @validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
end
end
- context "[:response_callback]" do
- it "should be yielded the HTTPI response" do
- called = false
- @validator = UrlValidator.new(:attributes => [ :field ], :check_path => true, :response_callback => lambda { |response, record, attribute, value| called = true; response.should be_kind_of(HTTPI::Response) })
- @validator.validate_each(@record, :field, "http://www.google.com/sdgsdgf")
- called.should be_true
+ context '[:request_callback]' do
+ it "should be yielded the HTTPI request" do
+ called = false
+ @validator = UrlValidator.new(attributes: %i(field), check_host: true, request_callback: ->(request) { called = true; expect(request).to be_kind_of(HTTPI::Request) })
+ @validator.validate_each(@record, :field, 'http://www.google.com/sdgsdgf')
+ expect(called).to eql(true)
end
end
end
diff --git a/url_validation.gemspec b/url_validation.gemspec
index 3ad181b..af643e0 100644
--- a/url_validation.gemspec
+++ b/url_validation.gemspec
@@ -1,28 +1,32 @@
-# Generated by jeweler
+# Generated by juwelier
# DO NOT EDIT THIS FILE DIRECTLY
-# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
+# Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
# -*- encoding: utf-8 -*-
+# stub: url_validation 1.2.0 ruby lib
Gem::Specification.new do |s|
- s.name = %q{url_validation}
- s.version = "1.0.0"
+ s.name = "url_validation".freeze
+ s.version = "1.2.0"
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
- s.authors = [%q{Tim Morgan}]
- s.date = %q{2011-05-27}
- s.description = %q{A simple, localizable EachValidator for URL fields in ActiveRecord 3.0.}
- s.email = %q{git@timothymorgan.info}
+ s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
+ s.require_paths = ["lib".freeze]
+ s.authors = ["Tim Morgan".freeze]
+ s.date = "2017-05-31"
+ s.description = "A simple, localizable EachValidator for URL fields in ActiveRecord 3.0.".freeze
+ s.email = "git@timothymorgan.info".freeze
s.extra_rdoc_files = [
"LICENSE",
- "README.textile"
+ "README.md"
]
s.files = [
".document",
".rspec",
+ ".ruby-gemset",
+ ".ruby-version",
"Gemfile",
"Gemfile.lock",
"LICENSE",
- "README.textile",
+ "README.md",
"Rakefile",
"VERSION",
"lib/url_validation.rb",
@@ -30,43 +34,42 @@ Gem::Specification.new do |s|
"spec/url_validator_spec.rb",
"url_validation.gemspec"
]
- s.homepage = %q{http://github.com/riscfuture/url_validation}
- s.require_paths = [%q{lib}]
- s.required_ruby_version = Gem::Requirement.new(">= 1.8.7")
- s.rubygems_version = %q{1.8.3}
- s.summary = %q{Simple URL validation in Rails 3}
+ s.homepage = "http://github.com/riscfuture/url_validation".freeze
+ s.required_ruby_version = Gem::Requirement.new(">= 2.0.0".freeze)
+ s.rubygems_version = "2.6.12".freeze
+ s.summary = "Simple URL validation in Rails 3+".freeze
if s.respond_to? :specification_version then
- s.specification_version = 3
+ s.specification_version = 4
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
- s.add_runtime_dependency(%q