belong_to 多个 parents

belong_to multiple parents

嗨,我是 Elixir 的新手,一般来说 models/DB/APIs,我对如何实现以下目标有点迷茫:

我想创建一个事件,当我在 API 中执行 POST 到 /v1/events 同时发送 tag_idgate_id 但我没有我不知道如何在我的控制器中处理这个问题。

我用更简单的模型做到了这一点,它们只有 belong_to 一个 parent 而我只是将 build_assoc 输送到 changeset,但是,我迷失了如何使用多个 parent 来做到这一点。我什至尝试了一个粗略的解决方案来手动创建一个变更集,手动设置 gate_idtag_id 像这样 Event.changeset(%Event{"gate_id" => gate_id, "tag_id" => tag_id}, event_params) 但是它错误地说 gate_idtag_id 不是模型的一部分。

所以两个问题: 处理这种情况的正确方法是什么?我什至很接近还是我的模型有误?

POST 到 /v1/events 同时传递两个 ID 听起来不错,还是我也迷失在其中?

型号供参考

标签模型:

defmodule Tracker.Tag do
  use Tracker.Web, :model

  schema "tags" do
    field :epc, :string
    field :name, :string
    field :is_active, :boolean, default: false
    field :is_inside, :boolean, default: false

    has_many :events, Tracker.Event

    timestamps
  end

 @required_fields ~w(epc name is_active is_inside)
  @optional_fields ~w()

  def changeset(model, params \ :empty) do
    model
    |> cast(params, @required_fields, @optional_fields)
    |> cast_assoc(:events, required: false)
  end
end

门型号:

defmodule Tracker.Gate do
  use Tracker.Web, :model

  schema "gates" do
    field :name, :string
    field :direction_in, :boolean, default: false
    field :antenna, :integer
    belongs_to :reader, Tracker.Reader

    has_many :events, Tracker.Event

    timestamps
  end

  @required_fields ~w(name direction_in antenna)
  @optional_fields ~w()

  def changeset(model, params \ :empty) do
    model
    |> cast(params, @required_fields, @optional_fields)
    |> cast_assoc(:events, required: false)
  end
end

更新:更多信息

事件模型:

defmodule Tracker.Event do
  use Tracker.Web, :model

  schema "events" do
    belongs_to :tag, Tracker.Tag
    belongs_to :gate, Tracker.Gate

    timestamps
  end

  @required_fields ~w()
  @optional_fields ~w()

  def changeset(model, params \ :empty) do
    model
    |> cast(params, @required_fields, @optional_fields)
  end
end

事件迁移:

defmodule Tracker.Repo.Migrations.CreateV1.Event do
  use Ecto.Migration

  def change do
    create table(:events) do
      add :tag_id, references(:tags, on_delete: :nothing)
      add :gate_id, references(:gates, on_delete: :nothing)

      timestamps
    end
    create index(:events, [:tag_id])
    create index(:events, [:gate_id])

  end
end

事件控制器创建函数(有点迷失在这个函数上)

  def create(conn, %{"event" => event_params}) do
    gate_id = conn.assigns.gate_id
    tag_id = conn.assigns.tag_id

    changeset = Event.changeset(%Event{"gate_id" => gate_id, "tag_id" => tag_id}, event_params)

    case Repo.insert(changeset) do
      {:ok, event} ->
        conn
        |> put_status(:created)
        |> put_resp_header("location", v1_event_path(conn, :show, event))
        |> render("show.json", event: event)
      {:error, changeset} ->
        conn
        |> put_status(:unprocessable_entity)
        |> render(Tracker.ChangesetView, "error.json", changeset: changeset)
    end
  end

我得到的最新错误是

== Compilation error on file web/controllers/v1/event_controller.ex ==
** (CompileError) web/controllers/v1/event_controller.ex:22: unknown key "gate_id" for struct Tracker.Event

您能否 post 您的错误以及 Event 的迁移?我相信您需要将 tag_idgate_id 添加到模型中的必填字段:

defmodule Tracker.Event do
  use Tracker.Web, :model

  schema "events" do
    belongs_to :tag, Tracker.Tag
    belongs_to :gate, Tracker.Gate

    timestamps
  end

  @required_fields ~w(tag_id gate_id)
  @optional_fields ~w()

  def changeset(model, params \ :empty) do
    model
    |> cast(params, @required_fields, @optional_fields)
  end
end