---
url: /reference/concerns/phonable.md
---
# Trek::Phonable

Phone number validation, normalization and formatting, backed by [Phonelib](https://github.com/daddyz/phonelib).

## API

```ruby
class Organization < ApplicationRecord
  include Trek::Phonable
  phonable_attributes :phone, :fax
end
```

For each declared attribute:

* a validation (`phone: { possible: true, allow_blank: true }`, see [Strictness](#strictness))
* normalization to E.164 international format on save
* `formatted_{attr}` — national format (`"01 23 45 67 89"`)
* `{attr}_with_country_code` — E.164 (`"+33123456789"`)

## Strictness

`strictness:` picks how hard Phonelib looks at a number. It applies to every attribute of the call.

| value | what is accepted |
| --- | --- |
| `:possible` (default) | the digits **could** form a number for the country — right length and shape |
| `:valid` | the digits fall in a range the regulator has actually **assigned** |

```ruby
class Organization < ApplicationRecord
  include Trek::Phonable
  phonable_attributes :phone, strictness: :valid
end
```

The gap between the two is worth knowing before leaving the default in place. With
`Phonelib.default_country = "FR"`, `"0012345678"` is *possible*: under `:possible` it is accepted and
normalized to `"+12345678"` — the stray leading zero read as an international prefix, the number
silently rehomed to country code +1, and the original input gone, since normalization happens on
save. Under `:valid` the same input is rejected and the person is asked to correct it.

`:possible` is the right default for a number stored as a way to reach someone, where a false
rejection is worse than a number that never gets dialled. Choose `:valid` when the application
intends to actually call or text what it collects.

## Usage

```ruby
org = Organization.create(phone: "0123456789")
org.phone                   # => "+33123456789"
org.formatted_phone         # => "01 23 45 67 89"
org.phone_with_country_code # => "+33123456789"
```
