這裏有一個簡單的方法。你可以自定義,支持更好的錯誤信息:
def validate_required_inclusion(changeset, fields) do
if Enum.any?(fields, &present?(changeset, &1)) do
changeset
else
# Add the error to the first field only since Ecto requires a field name for each error.
add_error(changeset, hd(fields), "One of these fields must be present: #{inspect fields}")
end
end
def present?(changeset, field) do
value = get_field(changeset, field)
value && value != ""
end
測試與Post模型和|> validate_required_inclusion([:title , :content])
:
iex(1)> Post.changeset(%Post{}, %{})
#Ecto.Changeset<action: nil, changes: %{},
errors: [title: {"One of these fields must be present: [:title, :content]",
[]}], data: #MyApp.Post<>, valid?: false>
iex(2)> Post.changeset(%Post{}, %{title: ""})
#Ecto.Changeset<action: nil, changes: %{},
errors: [title: {"One of these fields must be present: [:title, :content]",
[]}], data: #MyApp.Post<>, valid?: false>
iex(3)> Post.changeset(%Post{}, %{title: "foo"})
#Ecto.Changeset<action: nil, changes: %{title: "foo"}, errors: [],
data: #MyApp.Post<>, valid?: true>
iex(4)> Post.changeset(%Post{}, %{content: ""})
#Ecto.Changeset<action: nil, changes: %{},
errors: [title: {"One of these fields must be present: [:title, :content]",
[]}], data: #MyApp.Post<>, valid?: false>
iex(5)> Post.changeset(%Post{}, %{content: "foo"})
#Ecto.Changeset<action: nil, changes: %{content: "foo"}, errors: [],
data: #MyApp.Post<>, valid?: true>
我喜歡這個,因爲它比其他較短雖然它沒有在放棄它的工作...我將不得不玩它。謝謝! – DogEatDog
如果一個字段已經在模型中並且沒有發生變化,這將不起作用,例如'Post.changeset(%Post {content:「foo」},%{})'將會失敗,因爲儘管'content'存在,'changes'爲空。 – Dogbert
謝謝@Dogbert,很好。我已經更新了答案,儘管它仍然沒有像你的那樣檢查空字段。 – kmptkp