My association are:
defmodule Mp.Schema.User do
use Ecto.Schema
import Ecto.Changeset
schema "users" do
# ...
has_many :user_gyms, UserGym, on_replace: :delete
has_many :gyms, through: [:user_gyms, :gyms]
end
end
defmodule Mp.Schema.UserGym do
use Ecto.Schema
import Ecto.Changeset
schema "user_gyms" do
# ...
belongs_to(:user, User)
belongs_to(:gym, Gym)
end
end
defmodule Mp.Schema.Gym do
use Ecto.Schema
import Ecto.Changeset
schema "gyms" do
# ...
has_many :user_gyms, UserGym, on_replace: :delete
has_many :users, through: [:user_gyms, :users]
end
end
I am trying to preload gyms:
query = from U in Mp.Schema.User, preload: :gyms
Mp.Repo.all(query)
But i am getting this error:
schema Mp.Schema.UserGym does not have association or embed :gyms
There seems to have issue on association but I think I have fulfilled all requirements. any suggestion?
The reason this is failing for you is that you're using :gyms
and :users
in the :through
lists. Those keys should refer to the associations on UserGym
, which are :user
and :gym
, so, your code should look like:
defmodule Mp.Schema.User do
use Ecto.Schema
import Ecto.Changeset
schema "users" do
# ...
has_many :user_gyms, UserGym, on_replace: :delete
has_many :gyms, through: [:user_gyms, :gym]
end
end
...
defmodule Mp.Schema.Gym do
use Ecto.Schema
import Ecto.Changeset
schema "gyms" do
# ...
has_many :user_gyms, UserGym, on_replace: :delete
has_many :users, through: [:user_gyms, :user]
end
end
So, for instance :gyms
is created as an association through the existing :user_gyms
of the current schema and :gym
on that schema.
If you look at the documentation for has_many/3
, you'll see there's an example using through
and it has a comment that says:
# In the has_many :through example below, the `:comments`
# in the list [:comments, :author] refers to the
# `has_many :comments` in the Post own schema and the
# `:author` refers to the `belongs_to :author` of the
# Comment's schema (the module below).