Skip to content

Instantly share code, notes, and snippets.

@thiamsantos
Created July 8, 2021 14:15
Show Gist options
  • Save thiamsantos/b39a5871b9dbf62f45d3950934549025 to your computer and use it in GitHub Desktop.
Save thiamsantos/b39a5871b9dbf62f45d3950934549025 to your computer and use it in GitHub Desktop.
defmodule App.PhoneNumber do
use Ecto.Type
defstruct country_code: nil,
national_number: nil,
extension: nil,
italian_leading_zero: nil,
number_of_leading_zeros: nil,
raw_input: nil,
country_code_source: nil,
preferred_domestic_carrier_code: nil
def parse(value) when is_binary(value) do
case ExPhoneNumber.parse(value, "") do
{:ok, phone_number} ->
fields = Map.from_struct(phone_number)
{:ok, struct!(__MODULE__, fields)}
_ ->
:error
end
end
def parse!(value) do
case parse(value) do
{:ok, phone_number} ->
phone_number
:error ->
raise ArgumentError,
"cannot parse #{inspect(value)} as phone number, reason: :invalid_format"
end
end
def to_e164(%__MODULE__{} = phone_number) do
fields = Map.from_struct(phone_number)
ExPhoneNumber.Model.PhoneNumber
|> struct!(fields)
|> ExPhoneNumber.format(:e164)
end
def to_national(%__MODULE__{} = phone_number) do
fields = Map.from_struct(phone_number)
ExPhoneNumber.Model.PhoneNumber
|> struct!(fields)
|> ExPhoneNumber.format(:national)
end
@impl true
def type, do: :string
@impl true
def cast("+" <> _phone = value) when is_binary(value) do
parse(value)
end
def cast(value) when is_binary(value) do
parse("+#{value}")
end
@impl true
def cast(%__MODULE__{} = phone_number), do: {:ok, phone_number}
@impl true
def cast(_), do: :error
@impl true
def load(value) when is_binary(value) do
parse(value)
end
@impl true
def dump(%__MODULE__{} = phone_number), do: {:ok, to_e164(phone_number)}
@impl true
def dump(_), do: :error
end
defimpl Inspect, for: App.PhoneNumber do
def inspect(phone_number, _opts) do
"#PhoneNumber<" <> App.PhoneNumber.to_e164(phone_number) <> ">"
end
end
defimpl Jason.Encoder, for: App.PhoneNumber do
def encode(phone_number, opts) do
Jason.Encode.string(App.PhoneNumber.to_e164(phone_number), opts)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment