2016-05-27 12 views
2

エリクサーでこれをリファクタリングして読みやすくする方法はありますか?エリクサーのネストされたif文を避けるには?

def validate(params) do 
    Repo.start_link 

    if validate_oauth_params(params) === true do 
     oauth_client = Repo.get_by(OauthClient, random_id: params["client_id"], secret: params["secret"]) 

     if oauth_client != nil do 
     allowed_grant_types = Poison.Parser.parse!(oauth_client.allowed_grant_types) 
     if Map.has_key?(allowed_grant_types, params["grant_type"]) do 
      case params["grant_type"] do 
      "password" -> 
       process_password_grant(params, oauth_client) 
      "refresh_token" -> 
       process_refresh_token_grant(params["refresh_token"], oauth_client) 
      "client_credentials" -> 
       process_client_credentials_grant(oauth_client) 
      nil -> 
       %{message: "Invalid oauth credentials", code: 400} 
      end 
     end 
     else 
     %{message: "Invalid oauth credentials", code: 400} 
     end 
    else 
     %{message: "Invalid oauth credentials", code: 400} 
    end 
    end 

このコードはPHPのように見えるので、それを行うためのエリクサーの方法は何ですか。私はそれを書いていない。

+1

コードをサブファンクションに分解します。私は今すぐコードを書き直す時間がありませんが、最も内側の 'if'を別の関数に抽象化し、他の' if'の場合と同様にしてください。 –

+1

開発者はこの素晴らしいスタートガイドを読んで理解する必要があります少なくとも重要なポイント:http://elixir-lang.org/getting-started/introduction.html – webdeb

+1

この問題は、Code Review Exchangeで自宅にいるようです。 –

答えて

4

あなたは正しく、PHPのようです。パターンマッチングのようなエリキシルの利点は使用されません。

これをリファクタリングするのは難しいです。他の方法もリファクタリングして、よりきれいにする必要があるようです。あなたはそれに対してパターンマッチするように、例えばvalidate_oauth_params機能は、代わりにブール値のタプルを返す「でした」、とあなたは同じように行うことになります。このような

def validate(params) do 
    case validate_oauth_params(params) do 
    {:ok, params} -> choose_oauth_method params 
    {:error} -> handle_error "Invalid params" 
    end 
end 

defp choose_oauth_method(%{"grant_type" => "password"} = params) do 
    process_password_grant(params) 
end 
defp choose_oauth_method(%{"grant_type" => nil}) do 
    handle_error "Method undefined" 
end 

defp handle_error(msg), do: %{message: msg, code: 400} 
defp handle_error(msg, code), do: %{message: msg, code: code} 
defp handle_error(), do: %{message: "Default error massage", code: 400} 

何かを、これは、すべてのコードを動作しません、ただのアイデア、どのようにパターンマッチング作品とその利点を得ることが

あなたはしかし、そのようなrefactiongは、他のタラでさらに変更が必要な場合があります

def validate(params) do 
    with 
    {:ok, p} <- validate_oauth_params(params), 
    {:ok, client} = get_client_for_params(p), 
    {:ok, allowed_grant_types} <- Poison.Parser.parse(oauth_client.allowed_grant_types) 
    do 
    case params["grant_type"] do 
     "password" -> 
     process_password_grant(params, oauth_client) 
     "refresh_token" -> 
     process_refresh_token_grant(params["refresh_token"], oauth_client) 
     "client_credentials" -> 
     process_client_credentials_grant(oauth_client) 
     nil -> :error 
    end 
    end |> case do 
    {:ok, something} -> something 
    _ -> %{message: "Invalid oauth credentials", code: 400} 
    end 
end 

のようなものにwith式を使用してこのコードを書き換えることを試みることができ

+1

あなたの最後の 'handle_error'節は決して一致しません。これは最初のものと同等ですが、パラメータを無視するだけです。単純に 'handle_error()'にしようとしましたか?パラメータはありませんか? – CoderDennis

+0

ありがとう、その更新;) – webdeb

2

eまたは認識可能な値とエラーを返すためのヘルパー関数の導入withは現在パターンのガードをサポートしていませんが、1.3のガードをサポートします。

+0

もっと整理されたが、まだ混乱IMHOに見えます。 – kgpdeveloper

0

ここでは、ロジックが本当に複雑になり、with/doステートメントでは不十分な場合に使用する方法が少し異なります。

def validate(params) do 
    try do 
     if !validate_oauth_params(params), do: 
      throw({:error, %{message: "Invalid oauth credentials", code: 400}}) 

     if !oauth_client, do: 
      throw({:error, %{message: "Invalid oauth credentials", code: 400}}) 

     allowed_grant_types = Poison.Parser.parse!(oauth_client.allowed_grant_types) 
     if !Map.has_key?(allowed_grant_types, params["grant_type"]), do: 
      throw({:error, %{message: "No grant type", code: 400}}) 

     case params["grant_type"] do 
      "password" -> 
       process_password_grant(params, oauth_client) 
      "refresh_token" -> 
       process_refresh_token_grant(params["refresh_token"], oauth_client) 
      "client_credentials" -> 
       process_client_credentials_grant(oauth_client) 
      nil -> 
       throw({:error, %{message: "Invalid oauth credentials", code: 400}}) 
     end 
    catch 
     {:error, map} -> {:error, map} 
    else 
     result -> {:ok, result} 
    end 
end