2016-04-26 73 views
0

我在我的应用程序中使用库,它定期返回{:ok, value}{:error, error}的元组。在我们假设可能有错误(例如用户输入)的情况下,我们正在明确处理这些情况。对于所有其他情况,我宁愿假设他们将得到妥善处理,如果没有,则通过重定向处理失败案例。我如何处理凤凰城的全球自定义错误?

我开始尝试用一个函数来解决这个问题:

def show(conn, %{"id" => id}) do 
    user = client.user_show(conn.assigns.endpoint, id) |> get_value(conn) 
    # rest of method omitted 
end 

def get_value({:ok, value}, _conn), do: value 

def get_value({:error, value}, conn) do 
    conn 
    |> put_flash(:error, "Client error") 
    |> redirect(to: "/") 
    |> halt 
end 

这似乎是个好主意,但不幸的是,在美国康涅狄格州仍在继续,尽管停止。这是有道理的,因为代码路径没有分割。

所以看来更好的解决方案是实现此功能来引发特定的错误,然后尝试全局解决它。

不幸的是,我找不到一种方法来处理菲尼克斯在全球范围内的错误。我看到的唯一可能的选择是使用ErrorView,但我不想只显示错误,我想根据错误进行适当的重定向。

我错过了什么,或者目前在凤凰城这是不可能的吗?

回答

0

halt函数实际上并不提供任何分支逻辑。它只将conn的私人字段halted设置为true。这可以确保其他插件不会进一步处理它,但其余操作将处理它并覆盖halted字段。

解决方案是将此功能移至插头。

def client_error_plug(conn) do 
    user = client.user_show(conn.assigns.endpoint, id) |> get_value(conn) 
    case user do 
    {:ok, user} -> 
     assign(conn, :current_user, user) 
    {:error, reason} -> 
     conn 
     |> put_flash(:error, "Client error") 
     |> redirect(to: "/") 
     |> halt 
    end 
end 

,并在控制器只是把”

plug :client_error_plug when action in [:show, ...] 

这可能是有道理给这个插件更有意义的名称,但是它依赖于应用程序的逻辑:)现在你可以确信你有用户在分配,因为如果它不在那里,重定向将踢入。