Select merge with joins and count

From what I can tell:

  • Key interpolation (key set at run time) works as long as the key is a string. Even query expressions work to some extent (e.g. (a.id + 4) doesn’t make much sense but it works).
  • atoms seem to only work as keys at compile time
defmodule Playground do
  import Ecto.Query
  alias MusicDB.Repo
  alias MusicDB.Album

  @keys [:run_time_key]
  @keys_list Keyword.new(@keys, &{&1, Atom.to_string(&1)})

  defp swap_key({to_key, from_key}, map) do
    case Map.pop(map, from_key) do
      {value, rest} ->
        Map.put(rest, to_key, value)

      _ ->
        map
    end
  end

  defp keys_swap(map),
    do: List.foldl(@keys_list, map, &swap_key/2)

  def play do
    album_id = 4

    query =
      from(a in Album,
        where: a.id == ^album_id,
        select: %{}
      )

    key = "run_time_key"
    fields = [:title]

    query =
      from(a in query,
        select_merge: %{^key => map(a, ^fields)}
      )

    query
    |> Repo.all()
    # [%{"run_time_key" => %{title: "Portrait In Jazz"}}]
    |> IO.inspect()
    |> Enum.map(&keys_swap/1)
    # [%{run_time_key: %{title: "Portrait In Jazz"}}]
    |> IO.inspect()

    :ok
  end
end