[extra-01] add custom date range graphql type
This type allow graphql to work natively with postgres date range and reduce the amount of work to convert between representations.
This commit is contained in:
parent
1597d34a2d
commit
24a2c516c5
46
lib/wabanex_web/schema/types/custom/date_range.ex
Normal file
46
lib/wabanex_web/schema/types/custom/date_range.ex
Normal file
@ -0,0 +1,46 @@
|
||||
defmodule WabanexWeb.Schema.Types.Custom.DateRange do
|
||||
use Absinthe.Schema.Notation
|
||||
|
||||
alias Absinthe.Blueprint.Input
|
||||
|
||||
scalar :date_range, name: "DateRange" do
|
||||
description("""
|
||||
The `DateRange` scalar represents a range/period of date. The `DateRange`
|
||||
appears as a string of two ISO8601 formatted dates separated by comma.
|
||||
""")
|
||||
|
||||
serialize &serialize_range/1
|
||||
parse &parse_range/1
|
||||
end
|
||||
|
||||
@spec serialize_range(PgRanges.DateRange.t()) :: String.t()
|
||||
@spec serialize_range(list(String.t())) :: String.t()
|
||||
defp serialize_range(%PgRanges.DateRange{lower: start_range, upper: end_range}),
|
||||
do: serialize_range([start_range, end_range])
|
||||
|
||||
defp serialize_range([start_range, nil]), do: "#{Date.to_iso8601(start_range)},"
|
||||
|
||||
defp serialize_range([start_range, end_range]),
|
||||
do: "#{Date.to_iso8601(start_range)},#{Date.to_iso8601(end_range)}"
|
||||
|
||||
@spec parse_range(Input.String.t()) :: {:ok, PgRanges.DateRange.t()} | :error
|
||||
@spec parse_range(Input.Null.t()) :: {:ok, nil}
|
||||
defp parse_range(%Input.String{value: value}) do
|
||||
value
|
||||
|> String.split(",")
|
||||
|> Enum.map(&Date.from_iso8601/1)
|
||||
|> case do
|
||||
[{:error, _}] -> :error
|
||||
[{:error, _}, _] -> :error
|
||||
[_, {:error, _}] -> :error
|
||||
result -> {:ok, result |> Enum.map(fn {:ok, value} -> value end) |> new()}
|
||||
end
|
||||
end
|
||||
|
||||
defp parse_range(%Input.Null{}), do: {:ok, nil}
|
||||
defp parse_range(_), do: :error
|
||||
|
||||
defp new([start_date]), do: new([start_date, nil])
|
||||
defp new([start_date, end_date]), do: PgRanges.DateRange.new(start_date, end_date)
|
||||
defp new([]), do: new([nil, nil])
|
||||
end
|
48
test/wabanex_web/schema/types/custom/date_range_test.exs
Normal file
48
test/wabanex_web/schema/types/custom/date_range_test.exs
Normal file
@ -0,0 +1,48 @@
|
||||
defmodule WabanexWeb.Schema.Types.Custom.DateRangeTest do
|
||||
use ExUnit.Case, async: true
|
||||
|
||||
alias Absinthe.{Blueprint.Input, Type}
|
||||
alias PgRanges.DateRange
|
||||
alias WabanexWeb.Schema.Types
|
||||
|
||||
defmodule TestSchema do
|
||||
use Absinthe.Schema
|
||||
|
||||
import_types Types.Custom.DateRange
|
||||
|
||||
query do
|
||||
end
|
||||
end
|
||||
|
||||
defp serialize(type, value) do
|
||||
TestSchema.__absinthe_type__(type)
|
||||
|> Type.Scalar.serialize(value)
|
||||
end
|
||||
|
||||
defp parse(type, value) do
|
||||
TestSchema.__absinthe_type__(type)
|
||||
|> Type.Scalar.parse(value)
|
||||
end
|
||||
|
||||
describe ":date_range" do
|
||||
test "serialize a list of dates as a list of ISO8601 date strings" do
|
||||
assert "1978-12-15,1980-02-13" == serialize(:date_range, [~D[1978-12-15], ~D[1980-02-13]])
|
||||
assert "1978-12-15," == serialize(:date_range, [~D[1978-12-15], nil])
|
||||
end
|
||||
|
||||
test "serialize a postgres range as a list of ISO8601 date strings" do
|
||||
assert "1978-12-15,1980-02-13" ==
|
||||
serialize(:date_range, DateRange.new(~D[1978-12-15], ~D[1980-02-13]))
|
||||
|
||||
assert "1978-12-15," == serialize(:date_range, DateRange.new(~D[1978-12-15], nil))
|
||||
end
|
||||
|
||||
test "can be parsed from a string of ISO8601" do
|
||||
assert {:ok, DateRange.new(~D[1978-12-15], ~D[1980-02-13])} ==
|
||||
parse(:date_range, %Input.String{value: "1978-12-15,1980-02-13"})
|
||||
|
||||
assert {:ok, DateRange.new(~D[1978-12-15], nil)} ==
|
||||
parse(:date_range, %Input.String{value: "1978-12-15"})
|
||||
end
|
||||
end
|
||||
end
|
Loading…
x
Reference in New Issue
Block a user