【问题标题】:How to access parent module in Elixir?如何访问 Elixir 中的父模块?
【发布时间】:2016-04-26 18:57:43
【问题描述】:

我有一个用于从数据库中获取记录的通用加载器:

defmodule Loader do
  defmacro __using__(opts) do
    quote location: :keep, bind_quoted: [schema: opts[:schema]] do

      def one(id), do: unquote(schema) |> Repo.get(id)
      def all,     do: unquote(schema) |> Repo.all
    end
  end
end

以及来自特定模式的特定加载器:

defmodule Location.Loader do
  use Loader, schema: Location
end

有没有办法以其他方式与“使用”模块进行通信,例如__MODULE__.parent?

【问题讨论】:

  • 你想做什么?您可以像任何其他模块一样按名称引用模块。
  • 您尝试做的事情看起来有点过于复杂。我也想知道你想达到什么目标。
  • 如您所见,我想在Loader 中访问Location,这是使用Loader 的模块的“顶级”模块。
  • 你想访问Loader的原因是什么。 “访问”是什么意思 - 调用函数?如果是这样,您可以使用Loader.some_function() 调用公共函数。无法从另一个模块调用私有函数。
  • 我想使用Location.Loader.allLocation.Loader.one(123)。问题是我想知道一般Loader,它被调用的模块的名称,例如Location.Loader。我通过在opts 中传递它来实现这一点,但我想知道是否还有其他方法可以做到这一点。

标签: elixir


【解决方案1】:

您可以在Loader.__using__quote 内部使用__MODULE__,并使用Module.split/1Enum.drop/2Module.concat/1 来获取父模块。

defmodule Loader do
  defmacro __using__(opts) do
    quote location: :keep, bind_quoted: [schema: opts[:schema]] do
      @parent_module __MODULE__ |> Module.split |> Enum.drop(-1) |> Module.concat
      def one(id), do: IO.puts("#{@parent_module}:one:#{id}")
      def all,     do: IO.puts("#{@parent_module}:all")
    end
  end
end

defmodule Location.Loader do
  use Loader
end

Location.Loader.one 123
Location.Loader.all

打印

Elixir.Location:one:123
Elixir.Location:all

但是,我建议不要使用它并使用您的原始代码,因为它更明确,并且根据我的经验,被认为更惯用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多