如何在Phoenix中创建两个表之间的简单关联并提交数据

问题描述 投票:0回答:1

我正在学习如何配置两个表之间的belong_to / has_many关系。我已完成配置,但我不知道调用它的语法。我想获取一个名为 Testbed 的预先存在的表,并将其分配给另一个名为 Group 的表。

  • 小组有_许多测试平台
  • 测试平台属于组。

这是我写的一个文档来记录这个过程,所以我完成了大部分步骤,直到我现在所在的位置。

在 Phoenix 中,我使用以下命令生成了两个表和相关的 UI 代码:

mix phx.gen.html Testbeds Testbed testbeds name:string

mix phx.gen.html Groups Group groups name:string

命令行提示我为它们添加资源/路由。我照它说的做了。

我跑了:

mix ecto.migrate

测试台迁移

对于测试床,我创建一个迁移文件并添加此字段:

:group_id, references(:groups)

defmodule App.Repo.Migrations.TestbedUpdate do
  use Ecto.Migration

  def change do
    alter table(:testbeds) do    
      add :group_id, references(:groups) # added
    end
  end
end

更改组架构我更新组架构。评论的变化

defmodule App.Groups.Group do
  use Ecto.Schema
  import Ecto.Changeset
  
  alias App.Testbeds.Testbed   # Alias!
  schema "groups" do
    field :name, :string
    has_many :testbeds, Testbed    # Has many
    timestamps()
  end

  @doc false
  def changeset(group, attrs) do
    group
    |> cast(attrs, [:name])
    |> validate_required([:name])
  end
end

更改测试台架构

defmodule App.Testbeds.Testbed do
  use Ecto.Schema
  import Ecto.Changeset
  alias App.Groups.Group      # Alias
  schema "testbeds" do
    field :name, :string
    belongs_to :group, Group    # Belongs to
    timestamps()
  end

  @doc false
  def changeset(testbed, attrs) do
    testbed
    |> cast(attrs, [:name])
    |> validate_required([:name])
  end
end

我读到我需要合并“预加载”以便我可以读取数据。所以我这样做了:

  def list_testbeds do
    Repo.all(Testbed)
    |> Repo.preload([:group])
  end

还有这个

  def list_groups do
    Repo.all(Group)
     |> Repo.preload([:testbeds])
  end

当我创建组和测试床并查询它们时,结果如下所示:

%App.Groups.Group{
    __meta__: #Ecto.Schema.Metadata<:loaded, "groups">,
    id: 3,
    name: "FUNK",
    testbeds: [],
    inserted_at: ~N[2023-09-27 18:13:15],
    updated_at: ~N[2023-09-27 18:13:15]
  }



%App.Testbeds.Testbed{
    __meta__: #Ecto.Schema.Metadata<:loaded, "testbeds">,
    id: 1,
    name: "Bloop",
    group_id: nil,
    group: nil,
    inserted_at: ~N[2023-09-27 14:04:15],
    updated_at: ~N[2023-09-27 18:22:23]
  }

我现在需要知道如何编写将测试床分配给组的代码。

创建群组

App.Groups.create_group(%{name: "OINK"})

提交测试平台并分配给团体协会

此代码将创建一个新的测试台并将其分配给 ID 为 1 的组。

group = App.Groups.get_group!(1)
thing = Ecto.build_assoc(group, :testbeds, name: "DUMB")
alias App.{Repo}
Repo.insert(thing)

当您查询该组时,您将看到一个字段名称为 testbeds 并分配有列表的组。该列表包含一个测试床结构。

现在我的问题是,如果我想采用预先创建的测试台并进行与之前的命令相同的关联,我该怎么办?我根本不知道语法,我尝试的所有方法都会导致错误。

我尝试创建一个测试台并手动为其分配一个group_id,如下所示:

App.Testbeds.update_testbed(my_testbed,%{group_id: 2,name: "some-name"}) 

它不会影响group_id并且它保持为零。

elixir phoenix-framework ecto
1个回答
0
投票

在预先存在的测试台和组之间手动创建关联的正确语法是

  1. 使用其 ID 检索要为其分配测试床的组:

    group = App.Groups.get_group!(1)

  2. 使用 ID 检索要分配给组的测试台:

    testbed = App.Testbeds.get_testbed!(1)

  3. 建立协会:

    thing = Ecto.build_assoc(testbed, :group, group)

  4. 使用 Repo.insert 将关联插入数据库:

    Repo.insert(thing)

这将创建测试床和组之间的关联,并且测试床中的 group_id 字段将使用组的 ID 进行更新。

© www.soinside.com 2019 - 2024. All rights reserved.