如何从模块访问父导入函数

How to access Parent imported functions from Module

我正在尝试创建一个测试助手来测试使用 Maru Framework 的应用程序。这是我想要实现的简化版本:

defmodule App.ExtendedMaru do
  @moduledoc false

  defmacro __using__(opts) do
    quote do
      use Maru.Test, unquote(opts)
    end
  end

  def post_body(url, body) do
    build_conn()
    |> Plug.Conn.put_req_header("content-type", "application/json")
    |> put_body_or_params(Poison.encode! body)
    |> post(url)
  end
end

问题出在 build_conn/0post/2 函数上。 build_conn/0Maru.Test 中定义,因此可以通过此模块内的 import Maru.Test 访问。

然而,post/2 是私有函数 defined inside the __using__ macro for Maru.Test。因此,它存在于使用该模块的模块中,但对 post_body/2 不可用。我不能只 use Maru.Test 在这里,因为我需要通过选择,但还没有找到方法。

是否可以访问应该在包含此模块的模块中定义的 post/2 函数?


编辑:代码如何结束:

defmodule Legacy.ExtendedMaru do
  @moduledoc """
  Adds a few extra function helpers for testing using the Maru framework. Use
  it as you would Maru.Test, ie:

    `use Legacy.ExtendedMaru, for: An.Api.Module`
  """

  defmacro __using__(opts) do
    quote do
      use Maru.Test, unquote(opts)
      unquote(add_post_body())
    end
  end

  defp add_post_body() do
    quote do
      @doc """
      Makes a POST request with the given body. Correctly encodes the body in the
      requested format and sets Content-Type headers.

      ## Parameters

        - url: The URL for the POST request
        - body: The body to send on the request
        - opts: For customizing function behaviour:
          - format: What format to send the body in. Defaults to 'json'.

      """
      @spec post_body(String.t, map(), keyword(String.t)) :: Plug.Conn.t
      def post_body(url, body, opts \ []) do
        format = opts[:format] || "json"

        build_conn()
        |> add_content(body, format)
        |> post(url)
      end

      def add_content(conn, body, "json") do
        Plug.Conn.put_req_header(conn, "content-type", "application/json")
        |> put_body_or_params(Poison.encode! body)
      end
    end
  end
end

您的问题来自两件事:

  • post_body 方法是私有的,因此您不能在 Module 之外调用它。

  • post_body 方法不在 __using__ 宏中,因此它对 use 它的任何其他模块不可用。

有两种简单的解决方法:

  • post_body 方法移到 __using__ 宏中。执行此操作后,use 它的所有模块将能够调用 post_body,但原始模块除外。

  • (or) 创建 post_body 方法 public 并在其内部调用 defdelegate __using__.这样您就可以在包括原始模块在内的所有模块中调用它。