Reputation: 1206
I have an ERM similar to this one:
-------- -------- --------
|ModelA|-----|ModelB|-----|ModelC|
-------- -------- --------
I get ModelA and its ModelBs with the following:
modela = Repo.get(ModelA,1)
modela = preload(modela, :modelb)
Now I can access ModelB
s with modela.modelb
. But how can I preload ModelC
aswell? When I print my modelA, it says, that modelc is not loaded.
Upvotes: 4
Views: 4489
Reputation: 1363
You can preload both Model B and it's Model C associations using one piped Repo query, without having to include an association between Model A and Model C in Model A's model definition:
modela = Repo.get(ModelA, 1)
|> Repo.preload(:modelb)
|> Repo.preload(modelb: :modelc)
Upvotes: 2
Reputation: 114
Can't comment yet but you have to define the nested relationship in ModelA. See Ecto.Schema
has_one :model_c, through: [:model_b, :model_c]
Upvotes: 3
Reputation: 11278
You can pass a list to Repo.preload
to load multiple associations. You can even pass a keyword list to preload nested associations.
I also find it useful to load everything that I need in the query itself (those two options below are equivalent):
query = from m in ModelA, preload: [modelb: :modelc]
Repo.get(query, 1)
Repo.get(ModelA, 1) |> Repo.preload(modelb: :modelc)
You can also pass tuples with {association_name, query}
for advanced preloding - especially useful in many associations to specify ordering.
You can read more of the documentation on preloads in the Ecto.Query.preload/3
docs
Upvotes: 10