Often in my contexts (Phoenix) I have some kind of list selection where I want to allow the caller of the function to specify the preloads and the select fields. The preloads are easy, as these can just be passed to Repo.preload/2
, but I’m kind of struggling with the select.
def get_company_addresses_by_uuid(uuids, opts) when is_list(uuids) do
preload = Keyword.get(opts, :preload, [])
fields = Keyword.get(opts, :fields, nil)
query =
CompanyAddress
|> ProjectName.Query.dynamic_select(fields)
|> where([ca], ca.uuid in ^uuids)
query
|> Repo.all()
|> Repo.preload(preload)
end
And dynamic_select
:
def dynamic_select(query, nil), do: query |> select([q], q)
def dynamic_select(query, []), do: query |> select([q], q)
def dynamic_select(query, fields) when is_list(fields), do: query |> select([q], ^fields)
def dynamic_select(query, _), do: query
This feels like something Ecto should already be able to do, but I just haven’t found the right way. I’ve tried:
from(ca in CompanyAddress, where: ca.uuid in ^uuids, select: map(ca, fields)
Fails when fields is nil
, []
, or just generally an unexpected value.
Is there a better way of doing this?