From 32620dfd5234be196e0abd4eaf7ecae51427e6a7 Mon Sep 17 00:00:00 2001 From: Zach Daniel Date: Sat, 7 Oct 2023 09:16:52 -0400 Subject: [PATCH] improvement: add `Ash.Sort.expr_sort`. In 3.0 sort should be a macro --- lib/ash/sort/sort.ex | 17 +++++++++++++++++ test/actions/read_test.exs | 9 +++++++++ 2 files changed, 26 insertions(+) diff --git a/lib/ash/sort/sort.ex b/lib/ash/sort/sort.ex index 3247714b..b7fd9e71 100644 --- a/lib/ash/sort/sort.ex +++ b/lib/ash/sort/sort.ex @@ -24,6 +24,23 @@ defmodule Ash.Sort do alias Ash.Error.Query.{InvalidSortOrder, NoSuchAttribute} + defmacro expr_sort(expression, type \\ nil) do + quote do + require Ash.Expr + type = unquote(type) + + case Ash.Query.Calculation.new( + :expr_sort, + Ash.Resource.Calculation.Expression, + [expr: Ash.Expr.expr(unquote(expression))], + type && Ash.Type.get_type(type) + ) do + {:ok, calc} -> calc + {:error, term} -> raise Ash.Error.to_ash_error(term) + end + end + end + @doc """ A utility for parsing sorts provided from external input. Only allows sorting on public attributes and aggregates. diff --git a/test/actions/read_test.exs b/test/actions/read_test.exs index 4a6771de..62d7d3e5 100644 --- a/test/actions/read_test.exs +++ b/test/actions/read_test.exs @@ -586,6 +586,15 @@ defmodule Ash.Test.Actions.ReadTest do |> Api.read() |> strip_metadata() end + + test "a sort can use an expression", %{post1: post1, post2: post2} do + require Ash.Sort + + Post + |> Ash.Query.sort([{Ash.Sort.expr_sort(title <> contents), :asc}]) + |> Api.read!() + |> IO.inspect() + end end describe "get_by with only a single field" do