我正在尝试在我正在处理的凤凰应用程序的架构中实现一些验证。我的架构有一个属性:详细信息,其中包含(除其他外)一个地图,其中包含有关问题和答案的数据(以及其他内容)。一个例子:
%{
question: "What's for dinner?",
options:[
%{option: "Chicken", selected: false},
%{option: "Fish", selected: true}
]
}
模式还有一个:type属性,用于描述:详细信息映射的内容。我已经编写了以下验证,以确保:详细信息映射包含以下类型的选项:类型为"对话"。
def validate_dialogue_options(changeset) do
validate_change(changeset, :details, fn :details, details ->
if(changeset.changes.type == "dialogue") do
cond do
Map.has_key?(details, :options) ->
[]
true ->
[details: "must include options for dialogue events"]
end
else
[]
end
end)
end
这样可行,但感觉非常麻烦。我对elixir很新,所以我确信有更简洁的方法来实现上述目标。任何人都可以推荐一种更简化的方式来实现上述目标吗?
谢谢!
奖励:我目前正在进行额外验证,以确保选择详细地图中至少有一个选项。现在我使用下面有效的方法,但我对更简洁的实现感兴趣!
Enum.member?(Enum.map(details.options, fn(x) -> x.selected end), true)
答案 0 :(得分:3)
第一部分可以使用模式匹配进行简化。我们对两个词changeset.changes.type
和details
感兴趣,因此我们匹配这些词的元组。
validate_change changeset, :details, fn :details, details ->
case {changeset.changes.type, details} do
{"dialogue", %{options: _}} -> []
{"dialogue", _} -> [details: "must include options for dialogue events"]
_ -> []
end
end
可以使用Enum.any?/2
Enum.any?(details.options, fn x -> x.selected end)
甚至
Enum.any?(details.options, & &1.selected)