Ecto 是否有内置方法可以在将其插入数据库之前调用
Ecto.Changeset
时删除 changeset/2
中字段的尾随和前导空格?
目前,我正在向架构中添加两个自定义函数以进行数据过滤,以提高数据完整性:
defp trim_fields(changeset, fields) do
Enum.reduce(fields, changeset, &trim(&2, &1))
end
defp trim(changeset, field) do
if get_change(changeset, field) do
update_change(changeset, field, &String.trim/1)
else
changeset
end
end
然后可以将函数通过管道传输到
changeset/2
函数中,例如
def changeset(%Customer{} = customer, attrs) do
|> cast(attrs, [:first_name, :last_name])
|> validate_required([:first_name], [:last_name])
|> trim_fields([:first_name, :last_name])
end
因为我认为这是一个常见的用例,所以我想知道是否没有一个函数已经提供了此功能?
如果 Ecto 中尚未提供此功能,那么从 Ectos API 的角度来看,添加此类功能并将其命名为
filter_trim
和 filter_...
我猜会很方便?
我认为最好在运行验证之前修剪输入。此外,
update_change
仅当给定键发生更改时才会执行更改。
这会导致代码稍微简化:
changeset
|> cast(attrs, [:first_name, :last_name])
|> update_change(:first_name, &String.trim/1)
|> update_change(:last_name, &String.trim/1)
|> validate_required([:first_name, :last_name])
为什么不简单地使用
:trim
?
changeset
|> cast(attrs, [:first_name, :last_name])
|> validate_required([:first_name, :last_name], [trim: true])
我想扩展 zwippie 的精彩答案。
正如文档指出的,如果该字段被清除,该值可能是
nil
。因此,我会使用这样的东西:
def changeset(%Customer{} = customer, attrs) do
customer
|> cast(attrs, [:first_name, :last_name])
|> update_change(:first_name, &trim/1)
|> update_change(:last_name, &trim/1)
|> validate_required([:first_name, :last_name])
end
defp trim(binary) when is_binary(binary), do: String.trim(binary)
defp trim(nil), do: nil
如果你有很多字段想要进行修剪,我会考虑定义一个辅助函数
update_changes/3
(类似于你的trim_fields/2
):
def changeset(%Customer{} = customer, attrs) do
customer
|> cast(attrs, [:first_name, :last_name])
|> update_changes([:first_name, :last_name], &trim/1)
|> validate_required([:first_name, :last_name])
end
defp update_changes(changeset, keys, function) do
Enum.reduce(keys, changeset, fn key, set -> update_change(set, key, function) end)
end