2016-07-14 12 views
1

は、私は基本的にエントリのリストをラップ非常に単純なGenServerを実装していますエリクサーと機能入力の検証

エリキシル(が、ほとんどの関数型プログラミング)を学ぶためにしようとしています。各paramのエントリの最大数と最大サイズ(バイト単位)は、(設定ファイル)

defmodule List do 

    def init(_) do 
     {:ok, []} 
    end 

    def handle_call({:insert, param1, param2, param3}, from, list) do 

     import Application 

     param1_max_size = get_env(:app, ....) 
     param2_max_size = get_env(:app, ....) 
     param2_max_size = get_env(:app, ....) 

     max_items_count = get_env(:app, ....) 

     ## should be {:reply, {:error, :your_list_is_full}, list} if list is full 

     ## should be {:reply, {:error, {:check_this_args_please, wrong_params_list}, list} if any param is wrong. wrong_params_list contains the offending params 

     ## should be {:reply, {:ok}, [{param1, param2, param3} | list ]} otherwise 

    end 

end 

制限されている私はそれが簡単に思える知っているが、基本的に私はそれを行うには、エレガントな機能的な方法を見つけようとしています。私の頭は手続き的なもので、私はいつもCのように=演算子を使って "入れ子になったら他の地獄"になってしまいます。複数のパラメータを検証するため、私が知っている

THX

答えて

3

クリーンな方法は、そのchangesetsEctoです。あなたは非常に似たようなものを実装したいかもしれません。

  1. 値と検証エラー
  2. は、すべての検証機能は、最初の引数としてそのデータ構造を取る作成し、配管のためのそれを容易にするために、このデータ構造を返す保持しているデータ構造を作成します。私はchangesetと同じ方法でEctoと呼ぶつもりです。

    changeset = %{data: {param1, param2, param3}, errors: []} 
    
    def validate_param(changeset, number) do 
        max_size = get_env(:app, :"param#{number}" 
        if elem(changeset.data, number-1) < max_size do 
        changeset 
        else 
        errors = [{:"param#{number}", elem(changeset.data, number-1)} | changeset.errors 
        %{ changeset | errors: errors} 
        end 
    end 
    
    validated_changeset = 
        changeset 
        |> validate_param(1) 
        |> validate_param(2) 
        |> validate_param(3) 
    
    case validated_changeset.errors do 
        [] -> {:reply, :ok, [changeset.data | list]} 
        errors -> {:reply, errors, list} 
    end 
    

    エリクサーで特殊文字が含まれているために、引用符を使用して原子を定義することができます:

のコードは次のようなものである可能性があります。特別な文字が含まれていない場合には、引用符と同じです:

iex(1)> :"a b" 
:"a b" 
iex(10)> :"ab" 
:ab 

Insideは、あなたが原子:"param#{number}"を使用して、一般的なvalidate_paramを作成できるように、文字列の補間を使用することができます引用します。

elem関数はゼロインデックスされているので、numberelem(changeset.data, number-1)から1を引く必要があります。

エラーがなければ、変更を加えずにチェンジセットを返します。

エラーの構造は{field_name, field_value}です。 listをチェンジセットに追加し、リストの長さをチェックして正しいエラーを付加するもう1つの検証関数を作成するのは簡単です。

あなたはまたList.foldlを使用してvalidate_param 3回の呼び出しで重複を削除することができます。

List.foldl([1, 2, 3], changeset, fn(number, changeset) -> validate_number(changeset, number) end) 

かさえ短い:

List.foldl([1, 2, 3], changeset, &validate_number(&2, &1)) 

最も重要なことは、彼らと同じ型を返す関数のパターンであり、第一引数として取る。これにより、多くのネストされたifまたはcaseステートメントを避けることが容易になります。

+0

これは本当に良いです。 – justatester