我正在为我们的系统构建一个管理工具应用程序。我想记录每个用户的每一个动作
我是这么做的
defmodule AdminToolWeb.UserController do
use AdminToolWeb, :controller
...
def delete(conn, %{"id" => id}) do
current_user = Guardian.Plug.current_resource(conn)
with %User{} <- user = Accounts.get_user(id) do
Accounts.delete_user(user)
conn
|> put_flash(:info, "#{user.id} deleted.")
|> Activities.log(current_user)
|> redirect(to: Routes.user_path(conn, :index))
end
end
...
end
问题是我必须在我的应用程序中的每个控制器的每个动作中管道|> Activity.log(current_user)
。
有办法实现这样的东西吗?Controller -> (ActivityLogPlugOfSorts) -> View
用一个定制插头,然后这样叫它?
defmodule AdminToolWeb.UserController do
use AdminToolWeb, :controller
import AdminToolWeb.Plugs.Activities
plug :log
...
但是它应该在控制器和视图之间调用
或者我应该把一个函数内的视图模块代替?
我希望有更好的方法。
你在这里寻找的是控制器插头,它确实可以直接插入控制器级别。它们将在之前运行控制器动作,因此当插头运行时,您将没有机会知道尝试的动作是否成功。然而,你可以使用控制器插头来设置一个回调,它将在之后运行。控制器动作(但在发送响应之前)。例如:
defmodule HelloWeb.Plugs.ActionLogger do
import Plug.Conn
require Logger
def init(default), do: default
def call(conn, _default) do
register_before_send(conn, fn conn ->
if (response_code_2xx?(conn) do
Logger.info("action taken: #{extract_action(conn)}")
end
conn
end)
end
end
其中response_code_2xx?/1
和extract_action/1
留作习题,供读者参考。