Phoenix - 控制器和视图之间的回调动作

Phoenix - Callback action between controller and view

我正在为我们的系统构建一个管理工具应用程序。 我想记录每个用户的每一个动作

这是我所做的

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

...

但应该在控制器和视图之间调用。

或者我应该将一个函数放在 View 模块中吗?

希望有更好的办法

您在这里寻找的是controller plugs which can indeed be inserted directly at the controller level. They will run before the controller action, so you will not have the opportunity when the plug runs to know if the attempted action will be successful. However you can use the controller plug to setup a callback,它将在运行控制器操作之后(但在发送响应之前)。一个例子可能是:

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?/1extract_action/1 留作 reader 的练习。