Validators
Validators available to any Active Record or Active Model class of the app (User, a sign-up, a contact or newsletter form…): Trek's own, and those of the gems Trek depends on, which it loads.
| Validator | Key | From |
|---|---|---|
| Disposable email addresses | not_disposable | Trek |
| Email format | email | email_validator |
| Email checks | "valid_email_2/email" | valid_email2 |
| Phone numbers | phone | Phonelib |
| Uniqueness of a translated attribute | uniqueness | Mobility |
Disposable email addresses
NotDisposableValidator refuses an email address from a throwaway email provider (mailinator.com, yopmail.com…), or a subdomain of one, whatever its case:
class Contact < ApplicationRecord
validates :email, presence: true, email: { mode: :strict }, not_disposable: true
endIt is opt-in: Trek doesn't add it to User, whose accounts admins create. A blank address is left to the presence validation.
The error is :disposable, « is a disposable email address, use a permanent one » (« est une adresse e-mail jetable, utilisez-en une permanente »). Change it in the app's locales (errors.messages.disposable), or per model:
validates :email, not_disposable: { message: "must be your work address" }The domains come from the valid_email2 gem, whose maintainers keep the list up to date: updating the gem updates the list, with no data to refresh in the app. Only the list is checked, without looking up the domain's mail servers. To let a domain through, list it in config/allow_listed_email_domains.yml:
- legit-provider.exampleThe list (about 180,000 domains) is loaded on the first check, as a single string of 2.6 MB searched by bisection, rather than valid_email2's own Set of about 35 MB: about 5 µs per address.
Email format
EmailValidator checks an address's shape, without any network lookup:
validates :email, email: { mode: :strict }| Option | Default | |
|---|---|---|
mode | :loose | :loose only asks for something on each side of an @; :strict refuses consecutive or leading/trailing dots and asks for a domain with a TLD; :rfc follows RFC 5322 |
require_fqdn | — (true in :strict mode) | a domain with a TLD |
domain | — | only this domain, e.g. domain: "example.com" |
allow_nil | false |
User uses :strict mode.
Email checks
valid_email2's validator checks an address's shape too, and optionally more: its domain's mail servers (mx: true, strict_mx: true), a deny list (deny_list: true, from config/deny_listed_email_domains.yml), or refusing +tag addresses (disallow_subaddressing: true). See its options.
validates :email, "valid_email_2/email": { mx: true }mxandstrict_mxlook the domain up in the DNS on every validation, which can take up todns_timeout(5 seconds) and fails offline, in specs too.- For disposable addresses, use
not_disposablerather than itsdisposableoptions: they load its Set of 180,000 domains, which grows each process by about 35 MB.
Phone numbers
PhoneValidator checks a phone number with Phonelib, against Phonelib.default_country when the number has no country code:
validates :phone, phone: { possible: true, allow_blank: true }| Option | |
|---|---|
possible | true to only ask whether the digits could form a number for the country; otherwise they must fall in a range actually assigned (see Strictness) |
types | e.g. :mobile, [:mobile, :fixed] |
countries | e.g. [:fr, :be] |
allow_blank | a blank value fails otherwise |
Trek::Phonable adds it for you, with the number's normalization and formatting.
Uniqueness of a translated attribute
On a model with translated attributes, Mobility replaces uniqueness, so it works on them too, in the current locale: a title taken in English is still free in French.
class Fragment < ApplicationRecord
include Trek::Translatable
translate_attributes :title, :content
validates :title, uniqueness: true
end