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

时间:2017-08-15 02:53:05

标签: postgresql elixir phoenix-framework ecto

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

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

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

我也可能只是缺少一些非常愚蠢的东西,需要一些新鲜的眼睛,但我希望我对这种关系的理解可能搞砸了。

以下是我的迁移:

_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

最后我的种子.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映射并将其设为空字符串,则此方法有效。

非常感谢任何以正确方向转向的帮助!

提前谢谢。

1 个答案:

答案 0 :(得分:0)

您不应该将paths引用到数据库中。一对多的关系只是单方面的 - 你只需要api_id架构中的Path,你不需要反过来。

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

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

_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"
    }

但我建议你使用变更集。