gpt4 book ai didi

Elixir ecto 2 创建 many_to_many 关联

转载 作者:行者123 更新时间:2023-12-03 23:29:31 24 4
gpt4 key购买 nike

如何与 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 Controller 中使用它。

最佳答案

您可以通过传递像“posts_categories”这样的字符串来连接表,或者通过像 MyApp.PostCategory 这样的模式来连接模式。我更喜欢通过模式加入,因为可以包含时间戳。假设您选择通过架构而不是表加入:

  • 您需要为要加入的 many_to_many 关系创建一个单独的表(例如:posts_categories)。

  • ``
    def change do
    create table(:posts_categories) do
    add :post_id, references(:posts)
    add :category_id, references(:categories)
    timestamps
    end
    end
  • 为您在步骤 1 中创建的表创建架构。在您的 web\models 文件夹中,创建一个文件 post_category.ex:

  • ``
    defmodule Ecto2.PostCategory do
    use Ecto2.Web, :model

    schema "posts_categories" do
    belongs_to :post, Ecto2.Post
    belongs_to :category, Ecto2.Category
    timestamps
    end

    def changeset(model, params \\ %{}) do
    model
    |> cast(params, [])
    end
    end

    Ecto beta 2 已将 :empty 更改为空 map 并将 cast\4 更改为 cast\3。检查更改日志。
  • 将此行添加到您的帖子架构中:

    many_to_many :categories, Ecto2.Category, join_through: Ecto2.PostCategory
  • 将此行添加到您的类别架构中:

  • many_to_many :posts, Ecto2.Post, join_through: Ecto2.PostCategory

    而已!现在你可以像这样更新
    ``
    post1 = Repo.get!(Post, 1)
    category1 = Repo.get!(Category, 1)

    post1
    |> Repo.preload(:categories)
    |> Post.changeset(%{})
    |> put_assoc(:categories, [category1])
    |> Repo.update!

    ``

    关于Elixir ecto 2 创建 many_to_many 关联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35529720/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com