Preloading deeply nested associations in Ecto
Asked Answered
P

1

8

It's clear how to preload associations in Ecto 1-2 levels deep, such as post and comments to it.

I have an Address, and Address belongs_to a Street, and Street belongs_to a City, and City belongs_to Region, and Region belong_to a Country

Given Address:

addr = Repo.get(Address, 123)
|> Repo.preload(street: ?????)

how do I preload it all the way to Country:

IO.puts("the name of country: #{addr.street.city.region.country.name}")

?

Proust answered 20/2, 2019 at 22:32 Comment(0)
I
18

According to the docs Repo.preload/3 is similar to Ecto.Query.preload/3 and you can pass a nested list of preloads to both of them.

Examples:

Using Repo.preload/3:

addr = 
  Address
  |> Repo.get(123)
  |> Repo.preload(street: [city: [region: :country]])

IO.inspect(addr.street.city.region.country)

Using Ecto.Query.preload/3:

addr = 
  Address
  |> Ecto.Query.where(id: 123)
  |> Ecto.Query.preload(street: [city: [region: :country]])
  |> Repo.one()

IO.inspect(addr.street.city.region.country)
Inerrable answered 21/2, 2019 at 0:41 Comment(2)
What about preloads on the same level as street? or city? Like preload(street: [city: [], base: [] ], boulevard: [])Kermie
Yes, this should work. Also, if you don't have any sub-dependencies of city and base, you can simply write preload(street: [:city, :base], boulevard: []).Inerrable

© 2022 - 2024 — McMap. All rights reserved.