# subdomain_validator.rb (place in your lib/ or extra/ load path)
class SubdomainValidator < ActiveModel::EachValidator
def validate_each(object, attribute, value)
return unless value.present?
reserved_names = %w(www ftp mail pop smtp admin ssl sftp)
reserved_names = options[:reserved] if options[:reserved]
if reserved_names.include?(value)
object.errors[attribute] << 'cannot be a reserved name'
end
object.errors[attribute] << 'must have between 3 and 63 letters' unless (3..63) === value.length
object.errors[attribute] << 'cannot start or end with a hyphen' unless value =~ /^[^-].*[^-]$/i
object.errors[attribute] << 'must be alphanumeric; A-Z, 0-9 or hyphen' unless value =~ /^[a-z0-9\-]*$/i
end
end
# And in your model
validates :subdomain, :presence => true,
:uniqueness => true,
:subdomain => true
# Or with your own reserved names
validates :subdomain, :presence => true,
:uniqueness => true,
:subdomain => { :reserved => %w(foo bar) }
For more on creating custom Rails 3 validators, check our Ryan Bates’s screencast on the topic.
4 comments so far
Rodrigo Dellacqua Oct 28, 2010
Validators is a nice way to reuse validation code, but your code is wrong. There’s no options hash and there’s a typo in the error message for reserved words.
Rodrigo Dellacqua Oct 28, 2010
Alright, my bad, options hash is just being used, its from another object.
Matt Oct 30, 2010
Typo fixed, thanks for the heads up. Yep the options hash originates from the hash passed in the model validates call.
Palash Apr 15, 2012
I want my website subdomain valid.