Extension to ActiveModel for validating hostnames and domain names.
- Ruby >= 3.0.0
- Active Model >= 6.0
- Adds validation for hostnames to ActiveModel
- Supports I18n for the error messages
As a gem:
# in Gemfile
gem 'validates_hostname', '~> 2.0'
# Run bundler
bundle installThe following validations are performed on the hostname:
- The maximum length of the hostname is 255 characters.
- The maximum length of each hostname label is 63 characters.
- The allowed characters in hostname labels are
a-z,A-Z,0-9and hyphen (-). - Labels do not begin or end with a hyphen.
- Labels do not consist of numeric values only.
The validator can be configured with the following options:
allow_underscore: Allows for underscores in hostname labels.require_valid_tld: Requires that the last label is a valid TLD.valid_tlds: A list of valid TLDs. This option requiresrequire_valid_tldto betrue.allow_numeric_hostname: Allows numeric values in the first label of the hostname.allow_wildcard_hostname: Allows for a wildcard hostname in the first label.allow_root_label: Allows for a trailing dot (root label) in the hostname.
See also http://www.zytrax.com/books/dns/apa/names.html
Simple usage:
class Record
include ActiveModel::Validations
attr_accessor :name
def self.model_name
ActiveModel::Name.new(self, nil, "Record")
end
validates :name, hostname: true
endWith options:
class Record
include ActiveModel::Validations
attr_accessor :name
def self.model_name
ActiveModel::Name.new(self, nil, "Record")
end
validates :name, hostname: { allow_underscore: true }
endallow_underscore: Permits underscore characters (_) in hostname labels. (default:false)require_valid_tld: Ensures that the hostname's last label is a recognized Top-Level Domain (TLD). (default:false)valid_tlds: An array of specific Top-Level Domains (TLDs) that are considered valid. This option requiresrequire_valid_tldto betrueto take effect. (default: List fromdata/tlds.txt)allow_numeric_hostname: Allows hostname labels to consist solely of numeric digits (e.g.,123.example.com). Note: A hostname cannot consist of a single numeric label (e.g.,123is always invalid). (default:false)allow_wildcard_hostname: Permits a wildcard character (*) as the first label of the hostname (e.g.,*.example.com). (default:false)allow_root_label: Permits a trailing dot (root label) in the hostname (e.g.,example.com.). (default:false)
Without options:
class Record
include ActiveModel::Validations
attr_accessor :name
def self.model_name
ActiveModel::Name.new(self, nil, "Record")
end
validates :name, hostname: true
end
>> @record = Record.new(name: "horse")
>> @record.save
=> true
>> @record2 = Record.new(name: "_horse")
>> @record2.save
=> falseWith :allow_underscore:
class Record
include ActiveModel::Validations
attr_accessor :name
def self.model_name
ActiveModel::Name.new(self, nil, "Record")
end
validates :name, hostname: { allow_underscore: true }
end
>> @record3 = Record.new(name: "_horse")
>> @record3.save
=> trueWith :require_valid_tld:
class Record
include ActiveModel::Validations
attr_accessor :name
def self.model_name
ActiveModel::Name.new(self, nil, "Record")
end
validates :name, hostname: { require_valid_tld: true }
end
>> @record4 = Record.new(name: "horse")
>> @record4.save
=> false
>> @record5 = Record.new(name: "horse.com")
>> @record5.save
=> trueWith :valid_tlds:
class Record
include ActiveModel::Validations
attr_accessor :name
def self.model_name
ActiveModel::Name.new(self, nil, "Record")
end
validates :name, hostname: { require_valid_tld: true, valid_tlds: %w(com org net) }
end
>> @record6 = Record.new(name: "horse.info")
>> @record6.save
=> falseWith :allow_numeric_hostname:
class Record
include ActiveModel::Validations
attr_accessor :name
def self.model_name
ActiveModel::Name.new(self, nil, "Record")
end
validates :name, hostname: { allow_numeric_hostname: false }
end
>> @record7 = Record.new(name: "123.info")
>> @record7.save
=> falseWith :allow_wildcard_hostname:
class Record
include ActiveModel::Validations
attr_accessor :name
def self.model_name
ActiveModel::Name.new(self, nil, "Record")
end
validates :name, hostname: { allow_wildcard_hostname: true }
end
>> @record8 = Record.new(name: "*.123.info")
>> @record8.save
=> trueWith :allow_root_label:
class Record
include ActiveModel::Validations
attr_accessor :name
def self.model_name
ActiveModel::Name.new(self, nil, "Record")
end
validates :name, hostname: { allow_root_label: true }
end
>> @record9 = Record.new(name: "example.com.")
>> @record9.save
=> trueA few extra validators are included.
Sets require_valid_tld to true.
Sets allow_numeric_hostname to true. This option cannot be changed by the user.
Returns error if there is only one label and this label is numeric.
class Record
include ActiveModel::Validations
attr_accessor :name
def self.model_name
ActiveModel::Name.new(self, nil, "Record")
end
validates :name, domainname: true
end
>> @record = Record.new(name: "123.com")
>> @record.save
=> true
>> @record2 = Record.new(name: "123")
>> @record2.save
=> falseSets require_valid_tld to true.
class Record
include ActiveModel::Validations
attr_accessor :name
def self.model_name
ActiveModel::Name.new(self, nil, "Record")
end
validates :name, fqdn: true
end
>> @record = Record.new(name: "example.com")
>> @record.save
=> true
>> @record2 = Record.new(name: "example")
>> @record2.save
=> falseSets allow_wildcard_hostname to true.
class Record
include ActiveModel::Validations
attr_accessor :name
def self.model_name
ActiveModel::Name.new(self, nil, "Record")
end
validates :name, wildcard: true
end
>> @record = Record.new(name: "*.example.com")
>> @record.save
=> trueThe gem uses the I18n system for error messages. You can provide your own
translations in your application's locale files (e.g., config/locales/en.yml).
Example of a custom error message in config/locales/en.yml:
en:
errors:
messages:
invalid_hostname_length: "is not a valid hostname length"The gem comes with the following built-in translations:
- English (en)
- Spanish (es)
- German (de)
- French (fr)
- Simplified Chinese (zh)
The %{valid_chars} interpolator is available for the
label_contains_invalid_characters message.
Copyright (c) 2009-2025 Kim Nørgaard, released under the MIT license.