I’m trying to add associations. The simplified example has users and categories, with an n-to-n relationship between them. I’m trying to add an existing category to a user in the map_user_categories function. But the result is always a Ecto.Association.NotLoaded error.
iex(37)> UserCategory.map_user_categories(u, c)
** (ArgumentError) schema M2mTest.Accounts.User does not have association or embed :user_categories
(elixir 1.17.3) lib/enum.ex:2531: Enum."-reduce/3-lists^foldl/2-0-"/3
(m2m_test 0.1.0) lib/m2m_test/accounts/user_category.ex:34: M2mTest.Accounts.UserCategory.map_user_categories/2
iex:37: (file)
#user.ex
defmodule M2mTest.Accounts.User do
use Ecto.Schema
import Ecto.Changeset
alias M2mTest.Accounts.Category
alias M2mTest.Accounts.UserCategory
schema "users" do
field :name, :string
field :email, :string
many_to_many :categories, Category,
join_through: UserCategory,
join_keys: [user_id: :id, category_id: :id]
timestamps(type: :utc_datetime)
end
@doc false
def changeset(user, attrs) do
user
|> cast(attrs, [:name, :email])
|> validate_required([:name, :email])
|> unique_constraint(:email)
end
end
#category.ex
defmodule M2mTest.Accounts.Category do
use Ecto.Schema
import Ecto.Changeset
alias M2mTest.Accounts.User
alias M2mTest.Accounts.UserCategory
schema "categories" do
field :name, :string
many_to_many :users, User,
join_through: UserCategory,
join_keys: [category_id: :id, user_id: :id]
timestamps(type: :utc_datetime)
end
@doc false
def changeset(category, attrs) do
category
|> cast(attrs, [:name])
|> validate_required([:name])
end
end
#user_category.ex
defmodule M2mTest.Accounts.UserCategory do
use Ecto.Schema
import Ecto.Changeset
alias M2mTest.Accounts.User
alias M2mTest.Accounts.Category
@primary_key false
schema "user_categories" do
belongs_to :user, User, primary_key: true
belongs_to :category, Category, primary_key: true
timestamps(type: :utc_datetime)
end
@doc false
def changeset(user_category, attrs) do
user_category
|> cast(attrs, [:user_id, :category_id])
|> validate_required([])
end
def create_user_category(user_id, category_id) do
%__MODULE__{}
|> changeset(%{user_id: user_id, category_id: category_id})
|> M2mTest.Repo.insert()
end
def map_user_categories(user, categories) when is_list(categories) do
user_categories_existing = user.categories || []
user
|> M2mTest.Repo.preload(:categories)
|> Ecto.Changeset.change()
|> Ecto.Changeset.put_assoc(:categories, user_categories_existing ++ categories)
|> M2mTest.Repo.update()
end
def map_user_categories(user, category) do
map_user_categories(user, [category])
end
end




















