if Code.ensure_loaded?(Ecto) do defmodule MobileNumberFormat.SegmentedMobileNumber do use Ecto.Schema import Ecto.Changeset @primary_key false embedded_schema do field :iso_country_code, :string field :country_calling_code, :string field :national_number, :string field :trimmed_national_number_input, :string field :international_number, :string end @fields ~w(iso_country_code country_calling_code national_number international_number)a def changeset(mobile, attrs) do mobile |> cast(attrs, @fields) |> validate_and_clean_mobile() end defp validate_and_clean_mobile(%Ecto.Changeset{changes: %{iso_country_code: _}} = changeset), do: do_validate_and_clean_mobile(changeset) defp validate_and_clean_mobile(%Ecto.Changeset{changes: %{country_calling_code: _}} = changeset), do: do_validate_and_clean_mobile(changeset) defp validate_and_clean_mobile(%Ecto.Changeset{changes: %{national_number_user_input: _}} = changeset), do: do_validate_and_clean_mobile(changeset) defp validate_and_clean_mobile(changeset), do: changeset defp do_validate_and_clean_mobile(changeset) do parsed_data = MobileNumberFormat.parse(%{ iso_country_code: fetch_field!(changeset, :iso_country_code), country_calling_code: fetch_field!(changeset, :country_calling_code), national_number: fetch_field!(changeset, :national_number_user_input) }) case parsed_data do :invalid_iso_country_code -> add_error(changeset, :invalid_iso_country_code, "country is not valid") :invalid_country_calling_code -> add_error(changeset, :invalid_country_calling_code, "country calling code is not valid") :invalid_number -> add_error(changeset, :invalid_number, "mobile number is not valid") :insufficient_data -> raise "unexpected error" parsed_data -> {:ok, %{ iso_country_code: iso_country_code, country_calling_code: country_calling_code, national_number: national_number, trimmed_national_number_input: trimmed_national_number_input }} = parsed_data change(changeset, %{ iso_country_code: iso_country_code, country_calling_code: country_calling_code, national_number: national_number, national_number_user_input: trimmed_national_number_input }) end end end end