Внутри каждого приложения Phoenix (Elixir Web Framework) в нижней части файла /lib/{yourapp}_web.ex
например: /lib/chat_web.ex
есть макрос __using__/1
, определенный как:
@doc """
When used, dispatch to the appropriate controller/view/etc.
"""
defmacro __using__(which) when is_atom(which) do
apply(__MODULE__, which, [])
end
__using__/1
используется для?Если можете, поделитесь (или ссылку на) пример использования, который поможет продемонстрировать его в контексте реальный мир.
Откуда взялась функция apply
, учитывая, что она не «импортирована» в файл /lib/{yourapp}_web.ex
, и каков эффект «применить»?
We have tried googling and reading several docs, tutorials, blog posts etc. on Macros. e.g:
Но все же не ближе к понимание, почему / когда / как мы будем использовать макрос __using__/1
... :-(
Если мы попытаемся закомментировать или удалить его из lib/chat_web.ex
, приложение не будет компилироваться, даже если это не призванный из chat_web.ex
... и excoveralls
(отчет о тестовом покрытии) сообщает, что выполняется нет.
Я считаю, что это сбивает с толку / не подходит для новичков, и поиск в руководстве по Phoenix (документы) не особенно полезен, например:
https://github.com/phoenixframework/phoenix/blob/29536f3b86154ab64647643a3eeeb263e33834cd/guides/controllers.md
В примере / руководстве Phoenix Chat: https://github.com/dwyl/phoenix-chat-example
Мы отслеживаем охват тестами как упражнение обучение ...
Есть только строка кода один, которая нет покрывается тестами:
https://codecov.io/gh/dwyl/phoenix-chat-example/src/b57cc174d7f1c9aac22947f23170b29d4c303776/lib/chat_web.ex#L65
Как получилось, что строка не выполняется («покрытый»), когда мы запускаем тесты, но если мы прокомментируем вне строку, тесты неудача?
Является ли этот макрос «магия» тем, что он «используется», но фактически не является называется? Любое понимание шошинмного приветствуется!
К вашему сведению: лучший источник - это документация по Elixir, а не руководства, учебные пособия и сообщения в блогах. Позвольте мне процитировать этот отрывок из Kernel.use/2
:
When calling:
use MyModule, some: :options
the
__using__/1
macro from theMyModule
module is invoked with the second argument passed to use as its argument. Since__using__/1
is a macro, all the usual macro rules apply, and its return value should be quoted code that is then inserted whereuse/2
is called.
Там также есть примеры, которые могут прояснить саму концепцию.
How is it that the line is not being executed (“covered”) when we run the tests, but if we comment out the line the tests fail?
Поскольку это макрос, это внедряется в вызывающий исходный код на этапе компиляции. Тем не менее, когда вызывается use ThisModule
, AST, возвращаемый __using__/1
вводится в контекст вызывающего абонента.
Я понятия не имею, почему Coverage так глупо отмечать эту строку.
Тема про проблемы с охватом макросов github.com/parroty/excoshops/issues/59
Недавно я наткнулся на то же самое и искал, но не нашел ответа. Но потом я реализовал это в своем проекте, и это имеет смысл. Приведу пример, в котором я его использую. У меня есть тестовые примеры, в которых тот же контроллер написан с макросом. поэтому он не подходит для меня. Я пишу аналогичные тестовые примеры для каждого контроллера. Поэтому я использовал макрос
__using__/1
. и включать этот макрос в каждый тест контроллера. Это решает мою проблему многократного написания одного и того же кода для каждого тестового контроллера.