@Alekseis 答案的问题在于语法:
%{changeset | uuid: String.pad_leading(uuid, 8, "0")}
首先,更改将存在于changeset.changes,例如changeset.changes.uuid。但它们仅在此属性实际发生更改时才存在。所以写
%{changeset.changes | uuid: String.pad_leading(uuid, 8, "0")}
对我们没有帮助,因为这种语法只有在键已经存在于地图中时才有效。我们可以这样做:
Map.put(changeset, :uuid, String.pad_leading(uuid, 8, "0")
但我建议使用来自Ecto.Changeset 的适当函数,因为变更集可能只是一个结构,但围绕它有相当多的逻辑。我们的朋友是:https://hexdocs.pm/ecto/Ecto.Changeset.html#put_change/3
所以让我们重写解决方案:
@spec prepend_zeroes_to_uuid(Ecto.Changeset.t()) :: Ecto.Changeset.t()
# There are changes on uuid but it already is 8 characters long
def prepend_zeroes_to_uuid(%{changes: %{uuid: uuid}} = changeset)
when is_binary(uuid) and byte_size(uuid) >= 8, do: changeset
# There are changes on uuid and it needs padding
def prepend_zeroes_to_uuid(%{changes: %{uuid: uuid}} = changeset) when is_binary(uuid) do
put_change(changeset, :uuid, String.pad_leading(uuid, 8, "0"))
end
# There are no changes on uuid
def prepend_zeroes_to_uuid(changeset), do: changeset
# Now in your pipeline:
user
|> User.changeset(%{uuid: new_uuid})
|> prepend_zeroes_to_uuid()
|> Repo.update()