Skip to content

Instantly share code, notes, and snippets.

@Dowwie
Created February 8, 2023 13:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Dowwie/d69de06af2e9f8799287d8b4236e7ed7 to your computer and use it in GitHub Desktop.
Save Dowwie/d69de06af2e9f8799287d8b4236e7ed7 to your computer and use it in GitHub Desktop.
Elixir Ecto tsrange type
defmodule My.Postgres.TsRange do
@moduledoc """
Wraps a `Postgrex.Range` and casts to a PostgreSQL `tsrange` type.
Works w/ecto 3.8.0, postgrex 0.16
"""
use Ecto.Type
alias Postgrex.Range
defstruct lower: nil,
lower_inclusive: true,
upper: nil,
upper_inclusive: false
@type t :: %__MODULE__{
lower: NaiveDateTime.t() | :unbound,
lower_inclusive: boolean(),
upper: NaiveDateTime.t() | :unbound,
upper_inclusive: boolean()
}
@spec new(any, any) :: __MODULE__.t()
def new(lower, upper) do
struct!(__MODULE__, lower: lower, upper: upper)
end
@spec type :: :tsrange
@doc false
def type, do: :tsrange
@spec from_postgrex(Range.t()) :: __MODULE__.t()
def from_postgrex(%Range{} = range),
do: struct!(__MODULE__, Map.from_struct(range))
@doc false
@spec to_postgrex(__MODULE__.t()) :: Range.t()
def to_postgrex(%__MODULE__{} = range),
do: struct!(Range, Map.from_struct(range))
@spec cast(any) :: :error | {:ok, nil | Dispatch.Postgres.TsRange.t()}
@doc false
def cast(nil), do: {:ok, nil}
def cast(%Range{} = range), do: {:ok, from_postgrex(range)}
def cast(%__MODULE__{} = range), do: {:ok, range}
def cast(_), do: :error
@spec load(any) :: :error | {:ok, nil | Dispatch.Postgres.TsRange.t()}
@doc false
def load(nil), do: {:ok, nil}
def load(%Range{} = range), do: {:ok, from_postgrex(range)}
def load(_), do: :error
@spec dump(any) :: :error | {:ok, nil | Postgrex.Range.t()}
@doc false
def dump(nil), do: {:ok, nil}
def dump(%__MODULE__{} = range), do: {:ok, to_postgrex(range)}
def dump(_), do: :error
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment