如何更新 Phoenix 中模型的关系?
How to update relation of a model in Phoenix?
当我尝试在我的 MyDb 应用程序中编辑 book
时,我收到以下错误消息:
you are attempting to change relation :people of MyDb.Book, but there is missing data.
以下是相关片段:
/web/models/book.ex
defmodule MyDb.Book do
use MyDb.Web, :model
schema "books" do
field :title, :string
field :note, :string
many_to_many :people, MyDb.Person, join_through: MyDb.BookPerson
timestamps()
end
@doc """
Builds a changeset based on the `struct` and `params`.
"""
def changeset(struct, params \ %{}) do
struct
|> cast(params, [:title, :note])
|> put_assoc(:people, parse_people_ids(params))
end
defp parse_people_ids(params) do
(params["people_ids"] || [])
|> Enum.map(&get_people/1)
end
defp get_people(id) do
MyDb.Repo.get_by(MyDb.Person, id: id)
end
end
我可以保存与此变更集的关系。
/web/controllers/book_controller.ex
def edit(conn, %{"id" => id}) do
book = Repo.get!(Book, id)|> Repo.preload(:people)
people = Repo.all(Person) |> Enum.map(&{&1.surname, &1.id})
changeset = Book.changeset(book)
render(conn, "edit.html", book: book, changeset: changeset, conn: conn, people: people)
end
def update(conn, %{"id" => id, "book" => book_params}) do
book = Repo.get!(Book, id)
changeset = Book.changeset(book, book_params)
case Repo.update(changeset) do
{:ok, book} ->
conn
|> put_flash(:info, "Book updated successfully.")
|> redirect(to: book_path(conn, :show, book))
{:error, changeset} ->
render(conn, "edit.html", book: book, changeset: changeset)
end
end
/web/templates/book/form.html.eex
<div class="form-group">
<%= label f, "Authors", class: "control-label" %>
<%= multiple_select f, :people_ids, @people, class: "form-control" %>
<%= error_tag f, :person_id %>
</div>
错误消息下的评论说如果我想更新现有条目但我不知道如何更新,我应该在数据旁边包括条目主键 (ID)。
需要在 books
架构中使用选项 on_replace: :delete
schema "books" do
field :title, :string
field :note, :string
many_to_many :people, MyDb.Person, join_through: MyDb.BookPerson, on_replace: :delete
timestamps()
end
当我尝试在我的 MyDb 应用程序中编辑 book
时,我收到以下错误消息:
you are attempting to change relation :people of MyDb.Book, but there is missing data.
以下是相关片段:
/web/models/book.ex
defmodule MyDb.Book do
use MyDb.Web, :model
schema "books" do
field :title, :string
field :note, :string
many_to_many :people, MyDb.Person, join_through: MyDb.BookPerson
timestamps()
end
@doc """
Builds a changeset based on the `struct` and `params`.
"""
def changeset(struct, params \ %{}) do
struct
|> cast(params, [:title, :note])
|> put_assoc(:people, parse_people_ids(params))
end
defp parse_people_ids(params) do
(params["people_ids"] || [])
|> Enum.map(&get_people/1)
end
defp get_people(id) do
MyDb.Repo.get_by(MyDb.Person, id: id)
end
end
我可以保存与此变更集的关系。
/web/controllers/book_controller.ex
def edit(conn, %{"id" => id}) do
book = Repo.get!(Book, id)|> Repo.preload(:people)
people = Repo.all(Person) |> Enum.map(&{&1.surname, &1.id})
changeset = Book.changeset(book)
render(conn, "edit.html", book: book, changeset: changeset, conn: conn, people: people)
end
def update(conn, %{"id" => id, "book" => book_params}) do
book = Repo.get!(Book, id)
changeset = Book.changeset(book, book_params)
case Repo.update(changeset) do
{:ok, book} ->
conn
|> put_flash(:info, "Book updated successfully.")
|> redirect(to: book_path(conn, :show, book))
{:error, changeset} ->
render(conn, "edit.html", book: book, changeset: changeset)
end
end
/web/templates/book/form.html.eex
<div class="form-group">
<%= label f, "Authors", class: "control-label" %>
<%= multiple_select f, :people_ids, @people, class: "form-control" %>
<%= error_tag f, :person_id %>
</div>
错误消息下的评论说如果我想更新现有条目但我不知道如何更新,我应该在数据旁边包括条目主键 (ID)。
需要在 books
架构中使用选项 on_replace: :delete
schema "books" do
field :title, :string
field :note, :string
many_to_many :people, MyDb.Person, join_through: MyDb.BookPerson, on_replace: :delete
timestamps()
end