自动更新父记录 updated_at 字段(Elixir-Ecto)
Automatic update of parent record updated_at field (Elixir-Ecto)
假设我有两个模型:父模型和子模型。
如果更新了子记录,是否可以选择自动更新关联的父记录时间戳?
有几种方法可以做到这一点。其中之一需要 Ecto master(即将成为 Ecto v2.0)并且只需直接更新父级即可:
# Assuming a child_changeset with the parent loaded
child_changset = Ecto.Changeset.put_assoc(child_changeset, :parent, %{updated_at: Ecto.DateTime.utc})
现在,当持久化子项时,它会自动将更改传播到父项。
或者,您可以将 Ecto v1.1 与 prepare_changes 和 update_all 一起使用来传播更改:
# Assuming a child_changeset
Ecto.Changeset.prepare_changes child_changeset, fn changeset ->
query = Ecto.assoc(changeset.model, :parent)
changeset.repo.update_all query, set: [updated_at: ^Ecto.DateTime.utc]
changeset
end
在此示例中,我们使用在事务中与子更改一起执行的 prepare_changes 来构建表示父模型的查询并发出 update_all 更新所有 updated_at 与查询匹配的模块的列。
您可以向变更集添加一个函数来检查变更以及它们是否有效(如果您正在通过父变更集更新关联)。
def touch_parent(%{changes: changes, valid: true}=changeset) when map_size(changes) > 0 do
updated_at = DateTime.utc_now() |> DateTime.to_naive()
cast(changeset, %{updated_at: updated_at}, [:updated_at])
end
def touch_parent(changeset), do: changeset
您可以将其放在模型的 update_changeset
函数的末尾。
def update_changeset(%Model{}=model, attrs) do
model
# casting
|> touch_parent()
end
如果您只想进行特定的关联,您可以这样做:
def touch_parent(%{changes: changes, valid: true) when map_size(changes) > 0 do
updated_at = DateTime.utc_now() |> DateTime.to_naive()
changed_fields = Map.keys(changes)
cond do
:association in changed_fields ->
cast(changeset, %{updated_at: updated_at}, [:updated_at])
true -> changeset
end
end
:)
假设我有两个模型:父模型和子模型。 如果更新了子记录,是否可以选择自动更新关联的父记录时间戳?
有几种方法可以做到这一点。其中之一需要 Ecto master(即将成为 Ecto v2.0)并且只需直接更新父级即可:
# Assuming a child_changeset with the parent loaded
child_changset = Ecto.Changeset.put_assoc(child_changeset, :parent, %{updated_at: Ecto.DateTime.utc})
现在,当持久化子项时,它会自动将更改传播到父项。
或者,您可以将 Ecto v1.1 与 prepare_changes 和 update_all 一起使用来传播更改:
# Assuming a child_changeset
Ecto.Changeset.prepare_changes child_changeset, fn changeset ->
query = Ecto.assoc(changeset.model, :parent)
changeset.repo.update_all query, set: [updated_at: ^Ecto.DateTime.utc]
changeset
end
在此示例中,我们使用在事务中与子更改一起执行的 prepare_changes 来构建表示父模型的查询并发出 update_all 更新所有 updated_at 与查询匹配的模块的列。
您可以向变更集添加一个函数来检查变更以及它们是否有效(如果您正在通过父变更集更新关联)。
def touch_parent(%{changes: changes, valid: true}=changeset) when map_size(changes) > 0 do
updated_at = DateTime.utc_now() |> DateTime.to_naive()
cast(changeset, %{updated_at: updated_at}, [:updated_at])
end
def touch_parent(changeset), do: changeset
您可以将其放在模型的 update_changeset
函数的末尾。
def update_changeset(%Model{}=model, attrs) do
model
# casting
|> touch_parent()
end
如果您只想进行特定的关联,您可以这样做:
def touch_parent(%{changes: changes, valid: true) when map_size(changes) > 0 do
updated_at = DateTime.utc_now() |> DateTime.to_naive()
changed_fields = Map.keys(changes)
cond do
:association in changed_fields ->
cast(changeset, %{updated_at: updated_at}, [:updated_at])
true -> changeset
end
end
:)