DRY在多个控制器上复制代码

时间:2016-06-07 18:59:17

标签: elixir phoenix-framework

我在/users/:user_id/...下有几个嵌套路由,控制器需要user。在所有这些控制器中,我有以下代码。但我不想在所有控制器中使用相同的代码,只能在一个地方使用。适合放置的地方在哪里?我该怎么干?

defmodule MyApp.XyzController do
  use MyApp.Web, :controller
  plug :assign_user

  [...]

  defp assign_user(conn, _opts) do
    case conn.params do
      %{"user_id" => user_id} ->
        case Repo.get(MyApp.User, user_id) do
          nil  -> invalid_user(conn)
          user -> assign(conn, :user, user)
        end
      _ -> invalid_user(conn)
    end
  end

  defp invalid_user(conn) do
    conn
    |> put_flash(:error, "Invalid user!")
    |> redirect(to: page_path(conn, :index))
    |> halt
  end
end

1 个答案:

答案 0 :(得分:3)

您应该为此创建一个Plug。我通常将其放在lib/plugs/web/plugs/中,文件名与模块的最后一部分相同(例如此插件的fetch_user.ex)。

像(未经测试)的东西:

defmodule MyApp.Plugs.FetchUser do
  import Plug.Conn

  alias MyApp.Repo

  def init(_) do
    nil
  end

  def call(conn, _opts) do
    case conn.params do
      %{"user_id" => user_id} ->
        case Repo.get(MyApp.User, user_id) do
          nil  -> invalid_user(conn)
          user -> assign(conn, :user, user)
        end
      _ -> invalid_user(conn)
    end
  end

  defp invalid_user(conn) do
    conn
    |> put_flash(:error, "Invalid user!")
    |> redirect(to: page_path(conn, :index))
    |> halt
  end
end

然后在你的控制器中写下:

plug MyApp.Plugs.FetchUser