You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为EEx.function_from_file指定目标模块名称

解决EEx模板子目录函数名冲突并生成子模块函数的方案

要实现子目录模板编译到对应子模块的需求,不能简单给函数名加前缀,而是需要根据目录结构动态创建子模块,再在子模块内编译模板函数。以下是具体实现步骤和代码:

核心思路

  1. 遍历所有模板文件(包括子目录),解析每个文件的相对路径
  2. 根据路径拆分出目录部分,将目录名转换为驼峰式的子模块名
  3. 根目录模板直接在当前模块生成函数,子目录模板则先创建对应子模块,再在子模块内生成函数

完整代码实现

defmodule MyApp.Templates do
  defmacro __using__(opts) do
    template_dir = Keyword.get(opts, :dir, "templates")

    quote bind_quoted: [template_dir: template_dir] do
      # 递归获取所有.eex模板文件
      template_files = Path.wildcard(Path.join(template_dir, "**/*.eex"))

      Enum.each(template_files, fn file ->
        relative_path = Path.relative_to(file, template_dir)
        # 移除扩展名并拆分路径为列表
        path_parts = relative_path |> Path.rootname() |> Path.split()
        # 提取函数名(路径最后一部分)
        fun_name = path_parts |> List.last() |> String.to_atom()
        # 提取目录部分并转换为驼峰式模块名
        module_parts = path_parts |> Enum.drop(-1) |> Enum.map(&Macro.camelize/1)

        if Enum.empty?(module_parts) do
          # 根目录模板:直接在当前模块定义函数
          EEx.function_from_file(:def, fun_name, file, [:assigns])
        else
          # 子目录模板:构建子模块全名
          child_module = Module.concat(__MODULE__, module_parts)
          # 避免重复定义子模块
          unless Module.defines?(child_module) do
            # 动态创建子模块并编译模板函数
            Module.create(child_module, quote do
              EEx.function_from_file(:def, unquote(fun_name), unquote(file), [:assigns])
            end, __ENV__)
          end
        end
      end)
    end
  end
end

代码说明

  • 路径解析:通过Path.relative_to获取文件相对于模板根目录的路径,再用Path.split拆分出目录和文件名
  • 模块名转换:使用Macro.camelize将下划线命名的目录(如sub_domain)转换为符合Elixir规范的驼峰式模块名(如SubDomain)
  • 子模块创建:通过Module.concat拼接父模块和子模块后缀,生成完整子模块名;用Module.create动态创建模块,同时用Module.defines?避免重复编译
  • 函数生成:根目录模板直接在父模块生成函数,子目录模板在对应子模块内生成函数,彻底解决函数名冲突问题

使用效果

  • templates/index.eex → 编译为MyApp.Templates.index/1函数
  • templates/sub_domain/index.eex → 编译为MyApp.Templates.SubDomain.index/1函数

内容的提问来源于stack exchange,提问作者mszmurlo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 01:27:12