Composable preloads in Ecto

So I’m back with more Ecto questions. :slight_smile:

I have a rather large query with many joins and preloads. I would like to split this up into smaller “query” functions I can reuse across multiple functions.

From the Ecto.Query docs describe how one can compose queries which join tables like so:

def load_joined_table(query) do
  query =  from rows in query,
      left_join: other_table in assoc(rows, :other_table)

  query
  |> join_nested_table
  |> join_other_nested_table
end

def join_nested_table(query) do
   from [rows, other_table] in query,
       left_join: nested_table in assoc(other_table, :nested_table)
end

def join_other_nested_table(query) do
   from [rows, other_table] in query,
       left_join: other_nested_table in assoc(other_table, :other_nested_table)
end

It does however not mention how to preload these nested associations.

How can one do that?

I’ve tried the following:

def load_joined_table(query) do
  query =  from rows in query,
      left_join: other_table in assoc(rows, :other_table),
      preload: [other_table: other_table]

  query
  |> join_nested_table
  |> join_other_nested_table
end

def join_nested_table(query) do
   from [rows, other_table] in query,
       left_join: nested_table in assoc(other_table, :nested_table),
      preload: [other_table: {other_table, nested_table: nested_table}]

end

def join_other_nested_table(query) do
   from [rows, other_table] in query,
       left_join: other_nested_table in assoc(other_table, :other_nested_table),
      preload: [other_table: {other_table, other_nested_table: other_nested_table}]
end

But this does not seem to work for me. So how does one split up preloads into separate composable functions? Am I missing something obvious (I often do :blush:)

I’ve been looking through the source code for Ecto.Query and Ecto.Query.Builder.Preload. It doesn’t seem possible. At least I don’t know how to solve it :slight_smile:

Did you ever figure out this problem? Just ran into the same issue, hunting through the docs and haven’t come across a solution yet…

No, I haven’t. But it seems Ecto 3 will support named joins (https://github.com/elixir-ecto/ecto/pull/2431), so I assume it will fix this as well.

Named Joins are such bliss, they will reduce SO much of my code when I finally migrate my big project. ^.^

1 Like