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
Page
s 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 Page
s for a User
first?