救援ActionClauseError

时间:2017-11-03 11:12:23

标签: elixir phoenix-framework

我正在实施API端点。在我的控制器操作中,我想使用防护来验证param类型,如下所示:

def get_object(conn, %{"objectId" => object_id}) when is_binary(object_id) do

当客户端使用" objectId"来调用此端点时不是二元的,或没有" objectId"完全,凤凰提出Phoenix.ActionClauseError。我想拯救此类异常,并返回自定义响应正文(例如{"message": "Invalid request body"})。我怎样才能做到这一点?我尝试使用Plug.ErrorHandler,但它正在重新引发错误(如文档中所述)。

编辑:我发现了类似的问题(https://github.com/phoenixframework/phoenix/issues/2386),但我不想为每个控制器操作创建def get_object(conn, _params), do: :params_mismatch,因为会有很多

1 个答案:

答案 0 :(得分:1)

您为每个操作实现默认子句所发现的是最好的方法,无论它是否存在于所有操作中 - 它是明确的,易于推理,并且正如您所指出的那样,每个动作基本上只有一行代码。

您可以使用宏来删除样板,它可能类似于:

defaction get_object(conn, %{"objectId" => object_id}) do
  ...
end

这样的宏的实现不是我推荐的,但是对于有趣和游戏,一个简单的实现可能是这样的:

defmacro defaction(signature, do: body) do
  {name, argc} =
    case signature do
      {:when, _, [{name, _, args} | _]} ->
        {name, length(args)}
      {name, _, args} ->
        {name, length(args)}
    end
  argv = Enum.map(1..argc, fn _ -> quote do _ end end)
  quote location: :keep do
    def unquote(signature) do
      unquote(body)
    end
    def unquote(name)(unquote_splicing(argv)) do
      :params_mismatch
    end
  end
end

然后您可以定义如下操作:

defaction get_object(conn, %{"objectId" => object_id}) do
  ...
end

或:

defaction get_object(conn, %{"objectId" => object_id}) when is_binary(object_id) do
  ...
end

我想提醒您不要使用这种方法,因为它会掩盖错误处理,这可以通过查看宏定义来看到,但也可以使代码的局部推理更加困难。