使用具有 has_many 关系的结构播种数据库时找不到列

Column not found when seeding database with structs with has_many relationship

我首先尝试用一个简单的一层深度结构为我的数据库播种,效果很好。但是,当我添加一个路径映射以匹配我的顶级结构路径字段时,我得到了错误。

 ** (Postgrex.Error) ERROR 42703 (undefined_column): column "apis_id" of relation "paths" does not exist

我已经尝试删除 apis_id 但我相信我需要该字段来预加载我的 ApiController 中的 Path 结构。也许问题出在我的 has_many/belongs_to 语法上,尽管我相信我的语法是正确的,并且我已经尝试淹没其他 foreign_keys 和引用但没有运气。

我也可能只是遗漏了一些非常愚蠢的东西,需要一些新鲜的眼光,但我希望我对这段关系的理解可能是一团糟。

这是我的迁移:

_create_api.exs

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

  def change do
    create table(:apis) do
      add :basePath, :string
      add :definitions, :string
      add :paths, references(:paths)

      timestamps()
    end
  end
end

_create_paths.exs

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

  def change do
    create table(:paths) do
      add :apis_id, :string
      add :route, :string

      timestamps()
    end
  end
end

我的模特: api.ex

defmodule App.Api do
  use App.Web, :model

  schema "apis" do
    field :basePath, :string
    field :definitions, :string
    has_many :paths, App.Path, foreign_key: :apis_id

    timestamps()
  end
end

path.ex

defmodule App.Path do
  use App.Web, :model

  schema "paths" do
    belongs_to :apis, App.Api, references: :apis_id
    field :route, :string

    timestamps()
  end
end

这也是我的 ApiController api_controller.ex

defmodule App.ApiController do
  use App.Web, :controller

  alias App.Api

  def index(conn, _params) do
    apis = Repo.all(Api) |> Repo.preload([:paths])
    render conn, "index.json", apis: apis
  end
end

最后是我的 seeds.ex

alias App.Repo
alias App.Path
alias App.Api

api = %Api{
  basePath: "v1",
  definitions: "none",
  paths: [
    %Path{
      apis_id: 1,
      route: "/account"
    }
  ]
}

Repo.insert! api

如果我删除 %Path 映射并将其设为空字符串,这将起作用。

如能提供正确方向的帮助,我们将不胜感激!

提前致谢。

您不应该将对 paths 的引用放入数据库中。一对多的关系只是单方面的——你只需要在 Path 模式中使用 api_id,反之则不需要。

但是 Ecto 能够将 Paths 映射到 Api 结构中的字段。您不需要的是 _create_api 迁移中的 paths 字段。

所以我认为正确的文件内容应该是:

_create_api.exs

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

  def change do
    create table(:apis) do
      add :basePath, :string
      add :definitions, :string

      timestamps()
    end
  end
end

_create_paths.exs

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

  def change do
    create table(:paths) do
      add :api_id, references(:apis)
      add :route, :string

      timestamps()
    end
  end
end

api.ex

defmodule App.Api do
  use App.Web, :model

  schema "apis" do
    field :basePath, :string
    field :definitions, :string
    has_many :paths, App.Path

    timestamps()
  end
end

path.ex

defmodule App.Path do
  use App.Web, :model

  schema "paths" do
    belongs_to :api, App.Api
    field :route, :string

    timestamps()
  end
end

请注意,我从模型中删除了 referencesforeign_key。此外,我将字段名称 apis_id 更改为 api_id 以匹配标准命名。

编辑: 添加了 seeds.exs

alias App.Repo
alias App.Path
alias App.Api

api = Repo.insert! %Api{
      basePath: "v1",
      definitions: "none"
    }

path = Repo.insert! %Path{
      api_id: api.id,
      route: "/account"
    }

但我建议你使用变更集。