defmodule Helper.Area do @moduledoc false defmacro __using__(_) do quote do import Helper.Area def regex, do: "" def area_name, do: "" def area_type, do: "" def area_abbreviation, do: "" defoverridable [regex: 0, area_name: 0, area_type: 0, area_abbreviation: 0] def builder(number) do [_ | country] = __MODULE__ |> Module.split |> Enum.reverse country = country |> Enum.reverse |> Module.concat [[_, code, area, number]] = Regex.scan(regex(), number) %{ country: country.country(), a2: country.a2(), a3: country.a3(), international_code: code, number: number, area_code: area, area_name: area_name(), area_type: area_type(), area_abbreviation: area_abbreviation() } end end end defp generate_codes(codes) do [quote do def codes, do: unquote(codes) end] end defp generate_errors do [quote do def build(_number), do: {:error, "Not a valid phone number."} def build!(_number), do: raise ArgumentError, message: "Not a valid phone number." def match?(_number), do: false end] end defp generate_matcher(code) do quote do def match?(unquote(code) <> _ = number) do Regex.match?(regex(), number) end def build(unquote(code) <> _ = number) do if match?(number) do {:ok, builder(number)} else {:error, "Not a valid phone number."} end end def build!(unquote(code) <> _ = number) do if match?(number) do builder(number) else raise ArgumentError, message: "Not a valid phone number." end end end end defmacro matcher(codes) do generate_codes(codes) ++ Enum.map(codes, fn code -> generate_matcher(code) end) ++ generate_errors() end end