【发布时间】:2016-06-02 11:13:00
【问题描述】:
如何与 ecto 2 建立多对多关系?作为一个示例应用程序,我想 创建一个可以属于多个类别的帖子。类别已经存在。例如:
[%Category{id: "1", name: "elixir"}, %Category{id: "2", name: "erlang"}]
我正在使用 Ecto 2 beta 0。示例项目名为 Ecto2。
我定义了两个模型:
defmodule Ecto2.Post do
use Ecto2.Web, :model
use Ecto.Schema
schema "posts" do
field :title, :string
many_to_many :categories, Ecto2.Category, join_through: "posts_categories", on_replace: :delete
timestamps
end
@required_fields ~w(title)
@optional_fields ~w()
def changeset(model, params \\ :empty) do
model
|> cast(params, @required_fields, @optional_fields)
|> cast_assoc(:categories) # not suitable?
end
end
defmodule Ecto2.Category do
use Ecto2.Web, :model
schema "categories" do
field :name, :string
timestamps
end
@required_fields ~w(name)
@optional_fields ~w()
def changeset(model, params \\ :empty) do
model
|> cast(params, @required_fields, @optional_fields)
end
end
我试过这样做:
post = Repo.get!(Post, 1) |> Repo.preload(:categories)
changeset = Post.changeset(post, %{"title"=> "bla", "categories"=> [%{id: "1"}]})
Repo.update!(changeset)
但是 Post.changeset 中的 cast_assoc 不适合这个任务,它想创建一个全新的 Category 而不是关联一个。 我应该改用什么?建立关联?但是 build_assoc 文档没有提到它对 many_to_many 很有用。我该如何使用它?我应该将 build_assoc 放在 Post.changeset 中,还是应该在 phoenix 控制器中使用它。
【问题讨论】:
-
我可以看到下面的答案显示了一种通过使用 put_assoc(:categories, [category1]) (可能在控制器等中)在 Post 变更集之外解决此问题的方法。在 Post 变更集中解决它?就像你提到的, cast_assoc 创建新模型,它不与现有模型关联。
标签: elixir phoenix-framework ecto