I want to execute a function defined in a module using Ecto.Schema
based on the main entity of a query. So I need to extract from a query its main schema. This is the solution I have so far (very simplified), I was wondering if there is a better way of doing so or if there are some cases I’m missing.
defmodule Foo do
def foo(query) do
case schema_module(query) do
schema -> apply(schema, :bar, [query])
nil -> query
end
end
defp schema_module(%Ecto.Query{from: %{source: {_, module}}}), do: schema_module(module)
defp schema_module(query) when is_atom(query) do
cond do
function_exported?(query, :__schema__, 1) -> query
true -> nil
end
end
end
It can be used like
User |> Foo.foo() |> Repo.all()
or
User |> Repo.preload(:posts) |> Foo.foo() |> Repo.all()
In both cases User.bar/1
is called with the query as argument.
My main concern is about the Ecto.Query.FromExpr
struct (the value of :from
key in Ecto.Query
struct). I think it is an ecto internal that can change without notification.