I’m struggling with a pretty simple database action, and I’m pretty sure I’ve missed something obvious…
Let’s say I have the following schemas:
defmodule User
use Ecto.Schema
schema "users" do
field :username, :string
many_to_many :pages, Page, join_through: "users_pages"
timestamps()
end
end
defmodule Page
use Ecto.Schema
schema "pages" do
field :title, :string
many_to_many :users, User, join_through: "users_pages"
timestamps()
end
end
Pages are added after the User is created. So from what I’ve seen in the docs and in blog posts, I would create a changeset func that uses put_assoc like:
def changeset(%User{} = user, attrs) do
book
|> cast(attrs, [:username])
|> validate_required([:username])
|> put_assoc(:pages, attrs.pages)
end
Then I can go:
User.changeset(user, %{pages: [page]}) |> Repo.update()
All good. Now sometime later, a User adds another Page. From what I’ve read, to add this new Page to the User, I need to provide the entire new pages list as a changeset. Something like:
user = Repo.get(User, 1) |> Repo.preload(:pages)
User.changeset(user, %{pages: [new_page | user.pages]}) |> Repo.update()
But then, what about when a user already has thousands of pages. It doesn’t make sense to me to fetch all data for all of those pages simply to insert a new one.
Is there a simple way to insert a new Page for a User, utilizing the safety (validations etc) of a changeset, without fetching all Pages for a User first?






















