将已有模型的Ecto模型插入为关联
我有2个模型, entries
:
schema "entries" do
belongs_to :exception, Proj.Exception
field :application, :string
end
exceptions
:
schema "exceptions" do
field :name, :string
end
迁移脚本:
def change do
create table(:exceptions) do
add :name, :string, null: false
end
create table(:entries) do
add :exception_id, references(:exceptions), null: false
add :application, :string, null: false
end
end
我的目标是存储在另一个系统中发生的异常。 我希望项目能够将每个异常存储在第二个表exception
如果它们不在那里),然后将应用程序名称和异常ID存储在第一个表entries
。 entries
会有1000条记录,少数exceptions
。
假设entry_params
使用这种JSON格式:
{
exception: "NPE",
application: "SomeApp"
}
应该创建条目的方法:
def create(conn, %{"entry" => entry_params}) do
exception = Repo.get_by(Exception, name: entry_params["exception"]) ||
Repo.insert!(%Exception{name: entry_params["exception"]})
changeset =
Entry.changeset(%Entry{}, entry_params)
|> Ecto.Changeset.put_assoc(:exception, exception)
Repo.insert!(changeset)
end
这将打印出来:
** (ArgumentError) unknown assoc `exception` in `put_assoc`
如果我将entries
模型更改为使用has_one
而不是belongs_to
(我认为belongs_to在这里“感觉不好”,条目不属于异常,它只是有一个例外),它会抛出以下内容:
** (Postgrex.Error) ERROR (not_null_violation): null value in column "exception_id" violates not-null constraint
table: entries
column: exception_id
我基本上想要首先创建一个异常(如果它不存在),并创建一个新的系统错误条目并将以前生成的异常作为关联添加到条目中。
这里有什么问题?
belongs_to :exception, Proj.Exception
应该是belongs_to :exceptions, Proj.Exception
Ecto.Changeset.put_assoc(entries_changeset, :exception, exception)
应该是Ecto.Changeset.put_assoc(exception_changeset, :entries, entries)
尝试解决方案:
entries
模式:
schema "entries" do
field :application, :string
belongs_to :exceptions, Proj.Exception, on_replace: :nilify
end
exceptions
模式:
schema "exceptions" do
field :name, :string
has_many :entry, Proj.Entry, on_delete: :delete_all, on_replace: :delete
end
迁移脚本:
def change do
create table(:exceptions) do
add :name, :string, null: false
end
create table(:entries) do
add :application, :string, null: false
add :exception_id, references(:exceptions)
end
end
假设entry_params
使用这种JSON格式:
{
exception: "NPE",
application: "SomeApp"
}
创建或更新exceptions
和相关entries
:
def create(conn, %{"entry" => entry_params}) do
new_entry = Entry.changeset(%Entry{}, entry_params)
changeset =
case Repo.get_by(Exception, name: entry_params["exception"]) do
:nil ->
exception = %Exception{name: entry_params["exception"]} |> Repo.insert!
Ecto.Changeset.build_assoc(exception, :entries, [new_entry])
struct ->
changeset = Ecto.Changeset.change(struct)
data = Ecto.Changeset.preload(changeset, :entries) |> Map.get(:model) # Ecto 1.x
# data = Ecto.Changeset.preload(changeset, :entries) |> Map.get(:data) # Ecto 2.0.x
Ecto.Changeset.put_assoc(changeset, :entries, [new_entry | data.entries])
end
Repo.insert!(changeset)
end
链接地址: http://www.djcxy.com/p/90987.html
上一篇: Insert Ecto model with already existing model as an association