凤凰模式

时间:2017-11-07 19:25:02

标签: elixir phoenix-framework

我正在尝试在我正在处理的凤凰应用程序的架构中实现一些验证。我的架构有一个属性:详细信息,其中包含(除其他外)一个地图,其中包含有关问题和答案的数据(以及其他内容)。一个例子:

%{
  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)

1 个答案:

答案 0 :(得分:3)

第一部分可以使用模式匹配进行简化。我们对两个词changeset.changes.typedetails感兴趣,因此我们匹配这些词的元组。

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)