问题描述
按照 José Valim 本人的指示,我有一个带有嵌入式结构的 Elixir 结构:
http://blog.plataformatec.com.br/2015/08/working-with-ecto-associations-and-embeds/
defmodule MyApp.Post do
use Ecto.Schema
schema "posts" do
field :title
field :body
embeds_many :comments,MyApp.Comment
timestamps
end
end
defmodule MyApp.Comment do
use Ecto.Schema
embedded_schema "comments" do
field :body
belongs_to :post,MyApp.Post
timestamps
end
end
除了嵌入评论的 updated_at 时间戳之外,几乎所有东西都能完美运行,它在更新后似乎保留了其原始值。
我的意思是,如果我更改列表中的评论之一并在帖子上更新它并像这样保存:
my_post
|> change()
|> put_embed(:comments,comments)
|> Repo.update()
对值的更新按预期进行,除了 Comment 的 updated_at 时间戳没有改变。
我可以手动设置:
|> Map.put(:updated_at,DateTime.to_iso8601(DateTime.utc_Now))
这行得通,但试图弄清楚为什么它没有被 Ecto 自动设置。使用 Ecto 3.5.3。任何帮助将不胜感激!
迁移:
defmodule MyApp.Repo.Migrations.CreatePosts do
use Ecto.Migration
def change do
create table(:posts) do
add :title,:string
add :body,:string
add :comments,:map
timestamps()
end
end
end
解决方法
put_embed/4
的行为基于 put_assoc/4
的行为,它指出:
可以给出映射或关键字列表来更新关联数据,只要它们具有匹配的主键即可。例如,put_assoc(changeset,:comments,[%{id: 1,title: "changed"}])
将定位 :id
为 1 的评论并更新其标题。如果不存在具有此类 id 的评论,则会即时创建一个。
根据您评论的行为,我怀疑您没有在评论中提供 :id
字段。这意味着现有评论将被删除并插入提供的评论。要验证此假设,请检查 inserted_at
或 id
字段是否随每次执行而更改。