Elixir中的输入验证

时间:2017-02-02 20:57:47

标签: elixir

我正在努力想出一个在Elixir中进行输入验证的简洁方法。

在OOP语言中我会做这样的事情:

def my_func(a, b):
  if !validate_a(a):
    raise ArgumentError
  if !validate_b(b):
    raise ArgumentError
  return "something"

Elixir中我能想到的最好的是:

def my_func(a, b) do
  cond do
    not valid_a?(a) -> {:error, "a is invalid"}
    not valid_b?(b) -> {:error, "b is invalid"}
    :otherwise      -> {:ok, "something"}
  end
end

我知道我也可以在Elxir中引发一个异常,但我更喜欢对返回类型进行模式匹配,因为我的代码并没有被try / rescue块搞得一团糟。

在Elixir中是否有首选模式?

2 个答案:

答案 0 :(得分:4)

一切都取决于验证后 以及您希望验证的种类

例如:如果您只是验证ab是整数,则可以在函数定义中使用guard子句。

def my_func(a, b) when is_integer(a) and is_integer(b) do
  # your code - validation passed
end

def my_func(_, _) do
  # validation failed
end

在自定义验证方面,最好有单独的功能,您可以在“主”功能中使用它 - 您的代码更清晰,更容易测试,因为它更好地隔离。在您的情况下 - 具有验证的cond可能具有不同的功能。

在处理Phoenix控制器中的验证时,您显然可以创建自己的Plugs,当您在Ruby on Rails控制器中使用类似before时,这非常方便。

答案 1 :(得分:1)

根据验证的复杂程度和数据的外观,即使您不打算存储数据,也可以选择使用Ecto.Changeset

非常简单,如下所示

defmodule Foo do
  use Ecto.Schema
  import Ecto.Changeset

  schema "my_schema" do
    field :name, :string
    field :age, :integer
  end

  def changeset(struct, params) do
    struct
    |> cast(params, [:name, :age])
    |> validate_required([:name, :age])
    |> validate_number(:age, greater_than: 18)
  end
end

运行changeset/2功能后,系统会为您Ecto.Changeset提供一个valid?字段。如果是这样,它会通过所有验证。如果它是错误的,它还会从变更集的:errors键中告诉您原因。