Ecto - 更新嵌套嵌入
Ecto - updating nested embed
我无法使用 ecto 更新嵌套设置,我得到 "no changes" 变更集或错误。迁移:
def change do
create table(:trees) do
...
add :settings, :map
设置如下:
defmodule Final.TreeSettings do
use Ecto.Schema
embedded_schema do
...
field :columns, :map
timestamps
end
end
注意嵌套的列映射。
我可以像这样轻松地插入新的树行:
changeset = Tree.changeset(%Tree{}, %{user_id: user_id, name: x})
|> Ecto.Changeset.put_embed(:settings, treeSettings)
但以同样的方式更新它不起作用:
get_tree = Repo.one! from p in Tree, where: p.name == ^tree["name"], where: p.user_id == ^user_id
settingss = get_tree.settings
settingss = Kernel.update_in(settingss.columns[tree["setting"]][tree["type"]], fn x -> "asdasd" end)
# IO.inspect(settingss) shows correct changes here.
changeset =
get_tree
|> Ecto.Changeset.change
|> Ecto.Changeset.put_embed(:settings, settingss)
IO.inspect changeset
给出:
#Ecto.Changeset<action: nil, changes: %{}, errors: [], data: #Final.Tree<>,
valid?: true>
我认为你可以在 Ecto.Changeset.change/2
中使用它之前将其包装到 Ecto.Changeset.html#put_embed/4
完整示例:
迁移:
defmodule Final.Repo.Migrations.CreateTree do
use Ecto.Migration
def change do
create table(:trees) do
add :settings, :map
end
end
end
模型树:
defmodule Final.Tree do
use Final.Web, :model
schema "trees" do
embeds_one :settings, Final.TreeSettings
end
def changeset(struct, params \ %{}) do
struct
|> cast(params, [])
|> cast_embed(:settings)
end
end
模型树设置:
defmodule Final.TreeSettings do
use Final.Web, :model
embedded_schema do
field :columns, :map
end
def changeset(struct, params \ %{}) do
struct
|> cast(params, [:columns])
end
end
测试:
defmodule Final.TreeTest do
use Final.ModelCase
alias Final.Tree
test "updating nested embed" do
Repo.insert! Tree.changeset(%Tree{}, %{settings: %{columns: %{"key" => "value", "key2" => "value2"}}})
tree = Repo.one(Tree)
settings_changeset = tree.settings
|> Ecto.Changeset.change(%{columns: %{tree.settings.columns | "key" => "new value"}})
changeset = tree
|> Ecto.Changeset.change
|> Ecto.Changeset.put_embed(:settings, settings_changeset)
Repo.update! changeset
assert Repo.one(Tree).settings.columns == %{"key" => "new value", "key2" => "value2"}
end
end
我无法使用 ecto 更新嵌套设置,我得到 "no changes" 变更集或错误。迁移:
def change do
create table(:trees) do
...
add :settings, :map
设置如下:
defmodule Final.TreeSettings do
use Ecto.Schema
embedded_schema do
...
field :columns, :map
timestamps
end
end
注意嵌套的列映射。
我可以像这样轻松地插入新的树行:
changeset = Tree.changeset(%Tree{}, %{user_id: user_id, name: x})
|> Ecto.Changeset.put_embed(:settings, treeSettings)
但以同样的方式更新它不起作用:
get_tree = Repo.one! from p in Tree, where: p.name == ^tree["name"], where: p.user_id == ^user_id
settingss = get_tree.settings
settingss = Kernel.update_in(settingss.columns[tree["setting"]][tree["type"]], fn x -> "asdasd" end)
# IO.inspect(settingss) shows correct changes here.
changeset =
get_tree
|> Ecto.Changeset.change
|> Ecto.Changeset.put_embed(:settings, settingss)
IO.inspect changeset
给出:
#Ecto.Changeset<action: nil, changes: %{}, errors: [], data: #Final.Tree<>,
valid?: true>
我认为你可以在 Ecto.Changeset.change/2
中使用它之前将其包装到 Ecto.Changeset.html#put_embed/4
完整示例:
迁移:
defmodule Final.Repo.Migrations.CreateTree do
use Ecto.Migration
def change do
create table(:trees) do
add :settings, :map
end
end
end
模型树:
defmodule Final.Tree do
use Final.Web, :model
schema "trees" do
embeds_one :settings, Final.TreeSettings
end
def changeset(struct, params \ %{}) do
struct
|> cast(params, [])
|> cast_embed(:settings)
end
end
模型树设置:
defmodule Final.TreeSettings do
use Final.Web, :model
embedded_schema do
field :columns, :map
end
def changeset(struct, params \ %{}) do
struct
|> cast(params, [:columns])
end
end
测试:
defmodule Final.TreeTest do
use Final.ModelCase
alias Final.Tree
test "updating nested embed" do
Repo.insert! Tree.changeset(%Tree{}, %{settings: %{columns: %{"key" => "value", "key2" => "value2"}}})
tree = Repo.one(Tree)
settings_changeset = tree.settings
|> Ecto.Changeset.change(%{columns: %{tree.settings.columns | "key" => "new value"}})
changeset = tree
|> Ecto.Changeset.change
|> Ecto.Changeset.put_embed(:settings, settings_changeset)
Repo.update! changeset
assert Repo.one(Tree).settings.columns == %{"key" => "new value", "key2" => "value2"}
end
end