Привет, я новичок в Elixir и моделях/БД/API в целом, и я немного не понимаю, как добиться следующего:
Я хочу создать событие, когда я выполняю POST в своем API для /v1/events
отправки как tag_id
, так и gate_id
, но я не знаю, как это обработать в моем контроллере.
Я сделал это с более простыми моделями, где они просто belong_to
один родитель, и я просто передаю build_assoc
в changeset
, однако я не понимаю, как это сделать с несколькими родителями. Я даже попробовал схематичное решение, чтобы вручную создать набор изменений, вручную установив gate_id
и tag_id
, как это Event.changeset(%Event{"gate_id" => gate_id, "tag_id" => tag_id}, event_params)
, однако он выдал ошибку, сказав, что gate_id
и tag_id
не являются частью модели.
Итак, два вопроса: как правильно поступить в этой ситуации? Я даже близко или мои модели неверны?
Также хорошо ли звучит POST для /v1/events
, передавая оба идентификатора, или я тоже потерялся в этом?
Модели для справки
Тег модели:
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
%Event{"gate_id" => gate_id, "tag_id" => tag_id}
на%Event{gate_id: gate_id, tag_id: tag_id}
, чтобы исправить последнюю ошибку. - person Dogbert   schedule 21.04.2016