我會在模型的changeset
函數中通過「修復」params
來執行此操作,然後將其發送到cast
進行驗證。
範例模型與:count
整數字段:
def changeset(struct, params \\ %{}) do
struct
|> cast(fix_params(params), [:count])
|> validate_required([:count])
end
defp fix_params(%{count: "n/a"} = params), do: %{params | count: 0}
defp fix_params(params), do: params
演示:
iex(1)> Counter.changeset(%Counter{}, %{count: 123})
#Ecto.Changeset<action: nil, changes: %{count: 123}, errors: [],
data: #MyApp.Counter<>, valid?: true>
iex(2)> Counter.changeset(%Counter{}, %{count: "n/a"})
#Ecto.Changeset<action: nil, changes: %{count: 0}, errors: [],
data: #MyApp.Counter<>, valid?: true>
iex(3)> Counter.changeset(%Counter{}, %{count: "foo"})
#Ecto.Changeset<action: nil, changes: %{},
errors: [count: {"is invalid", [type: :integer]}], data: #MyApp.Counter<>,
valid?: false>
如果要任何非整數值轉換爲0時,可以這樣做:
defp fix_params(%{count: count} = params) when not is_integer(count), do: %{params | count: 0}
defp fix_params(params), do: params
演示:
iex(1)> Counter.changeset(%Counter{}, %{count: "foo"})
#Ecto.Changeset<action: nil, changes: %{count: 0}, errors: [],
data: #MyApp.Counter<>, valid?: true>
Thanks @Dogbert!我沒有看到很多使用自定義類型的好例子。這是最受歡迎的http://learningelixir.joekain.com/custom-types-in-ecto/。我猜想使用自定義類型與「更乾淨」功能的決定歸結爲你需要做的複雜性? – jacklin