0xAffe
0xAffe

Reputation: 1206

Preload all Relationships

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 ModelBs 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

Answers (3)

Nik
Nik

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

J_Tarasovic
J_Tarasovic

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

michalmuskala
michalmuskala

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

Related Questions