2017-02-02 104 views
0

我正在努力想出一個乾淨的方式來在Elixir中進行輸入驗證。Elixir中的輸入驗證

在面向對象的語言,我會做這樣的事情:

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

盡我所能想出的藥劑是這樣的:

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中有這樣做的首選模式嗎?

+0

你的代碼對我來說看起來很好。而不是':否則 - >'對於最後一種情況,我已經看到大多數人使用'true - >'。 – Dogbert

+0

我也見過。我個人更喜歡用':else'或':otherwise'來提高可讀性。 –

回答

3

一切都取決於什麼來驗證和什麼驗證你想要的。

例如:如果您只是驗證是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時非常方便。

+0

你能舉一個例子說明如何將我的'cond'塊分解成不同的函數嗎? –

+0

在這種情況下:只需將其重命名爲「驗證」並在'my_func'中,我會在頂部調用驗證。 – PatNowak

0

根據驗證的複雜程度和數據的外觀,即使您不打算存儲數據,也可以選擇使用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密鑰。