【发布时间】:2016-08-16 01:04:12
【问题描述】:
我有一个从 Repo 获取的模型并预加载了一些关联。我在 GenServer 中维护这个大型结构,但对它进行持久更改。我怎样才能坚持这些变化?例如:
query = from e in Empire,
where: e.user_id == ^user.id,
preload: [:board, {:board, [{:tiles, [:system]}]}]
empire = Repo.one(query)
#=> %Empire{
id: 1,
currency: 1000,
board: %Board{
empire_id: 1,
tiles: [
%Tile{
id: 1,
system: %System{
id: 1,
tile_id: 1,
ore: 10
}
},
%Tile{
id: 2,
system: nil
}
]
}
}
changed_empire = Empire.move_system(empire)
#=> %Empire{
id: 1,
currency: 500, #changed
board: %Board{
empire_id: 1,
tiles: [
%Tile{
id: 1,
system: nil #changed
}
},
%Tile{
id: 2,
system: %System{
id: 1,
tile_id: 2, #changed
ore: 5 #changed
}
]
}
}
请注意,系统已从一个 Tile 移动到另一个 Tile,并且 Empires 货币发生了变化。更改可以包括添加或删除关联。所有这些都是在没有来自客户端的任何数据的情况下完成的,因此无需担心添加错误数据,因为服务器是如何操作模型的唯一权威。
我不能依赖正常
changeset(model, params \\ %{}) do
model
|> cast(params, [])
end
因为 params 将是结构体。我可以尝试使用建议的更改
update_change(struct) do
struct
|> change()
|> validate()
end
但现在我遇到了需要手动将关联结构发送到它们自己的 update_change 函数的问题。
有没有更好的方法来完成这个而不增加我似乎遇到的所有额外复杂性?
【问题讨论】:
-
你可以试试
Ecto.Changeset.change/2hexdocs.pm/ecto/Ecto.Changeset.html#change/2 -
我仍然想进行验证。 change/2 似乎跳过了它们。
-
第二个参数不能是struct,而是params的map。如果你有一个结构并且想要转换它, Map.from_struct 应该可以解决问题。
-
@ChristianDiLorenzo 我正在考虑这个。唯一的问题是我需要通过 Map.from_struct 遍历每个关联。但到目前为止,这似乎是最简单的方法。
-
别担心,它没有副作用。 :-)
标签: elixir phoenix-framework ecto