如何从模块访问父导入函数
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/0
和 post/2
函数上。 build_conn/0
在 Maru.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__
.这样您就可以在包括原始模块在内的所有模块中调用它。
我正在尝试创建一个测试助手来测试使用 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/0
和 post/2
函数上。 build_conn/0
在 Maru.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__
.这样您就可以在包括原始模块在内的所有模块中调用它。