我正试图了解elixir模块的生命周期,我注意到的一件事就是在调用控制器时调用 before_compile 块中的插件宏不执行插件。据我所知,这个块在编译之前就执行了,所以插件宏也会在模块中编译。
对于这个:
defmacro __before_compile__(env) do
quote do
plug :say_hi
end
end
使用phoinex控制器中的方法:
def say_hi(conn, _) do
IO.inspect("hello")
end
这不会打印hello,因为在使用块中具有相同的引用块。我错过了什么?
克里斯
答案 0 :(得分:1)
Per the relevant documentation on Module
and compilation callbacks,__before_compile__
需要在目标模块中使用@before_compile MyApp.MyModule
调用(其中MyApp.MyModule
是模块的名称)。
如果您尝试在__before_compile__
模块的其他模块中发生use
,则可以定义__using__
和 {{1像这样:
__before_compile__
Sugar web development framework有一个相对简单的现实演示,说明它在控制器代码中是如何工作的;当您在控制器模块中调用defmodule MyApp.MyModule do
defmacro __using__(_) do
quote do
@before_compile MyApp.MyModule
end
end
defmacro __before_compile__(env) do
quote do
plug :say_hi
end
end
end
(例如,use Sugar.Controller
)时,将调用MyApp.Controllers.Main
宏,从而导致Sugar.Controller.__using__/1
在{@before_compile Sugar.Controller
的上下文中被调用1}},因此做了一堆幕后插件相关的魔术(主要是实现MyApp.Controllers.Main
行为,但这点不在这里)。
Phoenix.Controller.Pipeline
是这种模式的另一个很好的证明(虽然更复杂)。
在一个不相关的说明中,我得到了非常复杂的结果,让Plug
或IO.inspect
(或IO.puts
任何东西(就此而言)实际显示在这种情况下情况。您可能想尝试IO.
。