Пользовательские Mix-задачи
Создание пользовательских Mix-задач для ваших Elixir проектов.
Введение
Расширение функциональности приложений Elixir с помощью пользовательских Mix-задач — это распространенная практика. Прежде чем мы научимся создавать Mix-задачи специально для наших проектов, давайте взглянем на одну уже существующую:
$ mix phx.new my_phoenix_app
* creating my_phoenix_app/config/config.exs
* creating my_phoenix_app/config/dev.exs
* creating my_phoenix_app/config/prod.exs
* creating my_phoenix_app/config/prod.secret.exs
* creating my_phoenix_app/config/test.exs
* creating my_phoenix_app/lib/my_phoenix_app.ex
* creating my_phoenix_app/lib/my_phoenix_app/endpoint.ex
* creating my_phoenix_app/test/views/error_view_test.exs
...
Как можно понять из вышеуказанной консольной команды, у фреймворка Phoenix есть Mix-задача для генерации нового проекта. Можем ли мы сделать что-то похожее для нашего проекта? Отличная новость — мы можем, и это очень просто благодаря Elixir.
Настройка
Давайте создадим простое Mix-приложение.
$ mix new hello
* creating README.md
* creating .formatter.exs
* creating .gitignore
* creating mix.exs
* creating lib
* creating lib/hello.ex
* creating test
* creating test/test_helper.exs
* creating test/hello_test.exs
Your Mix project was created successfully.
You can use "mix" to compile it, test it, and more:
cd hello
mix test
Run "mix help" for more commands.
Теперь в сгенерированном файле lib/hello.ex создадим простую функцию, которая выводит на экран “Hello, World!”.
defmodule Hello do
@doc """
Выводит на экран `Hello, World!`.
"""
def say do
IO.puts("Hello, World!")
end
end
Пользовательские Mix-задачи
Давайте создадим пользовательскую Mix-задачу. Создайте новую директорию и файл hello/lib/mix/tasks/hello.ex. В этом файле напишем следующие 7 строк кода на Elixir.
defmodule Mix.Tasks.Hello do
@moduledoc "The hello mix task: `mix help hello`"
use Mix.Task
@shortdoc "Просто вызывает функцию Hello.say/0."
def run(_) do
# вызываем функцию Hello.say(), описанную ранее
Hello.say()
end
end
Обратите внимание: мы начинаем выражение defmodule
с Mix.Tasks
и имени, при помощи которого мы хотим вызывать нашу команду.
На второй строке мы используем use Mix.Task
, чтобы добавить поведение Mix.Task
в наше пространство имён.
Далее напишем функцию, которая пока не принимает аргументы.
Внутри этой функции вызовем функцию say
модуля Hello
.
Загрузка вашего приложения
Mix не запускает наше приложение или какие-либо его зависимости автоматически, что хорошо для многих сценариев использования задач Mix. Но что, если нам нужно использовать Ecto
и взаимодействовать с базой данных?
В этом случае нам нужно убедиться, что приложение, стоящее за Ecto.Repo, запущено.
У нас есть два способа справиться с этим: явная инициализация конкретного приложения или инициализация всего нашего приложения, которое, в свою очередь, инициализирует все остальные зависимости.
Давайте посмотрим, как мы можем обновить нашу Mix-задачу, чтобы запустить наше приложение и зависимости:
defmodule Mix.Tasks.Hello do
@moduledoc "The hello mix task: `mix help hello`"
use Mix.Task
@shortdoc "Simply calls the Hello.say/0 function."
def run(_) do
# This will start our application
Mix.Task.run("app.start")
Hello.say()
end
end
Использование Mix-задач
Давайте проверим.
Мы находимся в той же директории, поэтому задача должна сработать.
Выполним mix hello
в командной строке и увидим следующее:
$ mix hello
Hello, World!
Mix обладает достаточно дружественным интерфейсом. Он понимает, что все порой допускают ошибки, и поэтому использует технику неполного соответствия строк, чтобы предлагать рекомендации:
$ mix hell
** (Mix) The task "hell" could not be found. Did you mean "hello"?
Наверняка вы заметили новый атрибут @shortdoc
. Он может пригодиться при использовании нашего приложения, например, когда пользователь выполнит команду mix help
в терминале.
$ mix help
mix app.start # Starts all registered apps
...
mix hello # Просто выполняет команду Hello.say/0.
...
Обратите внимание: наш код должен быть скомпилирован, прежде чем новые задачи появятся в выводе mix help
.
Это можно сделать либо запустив mix compile
напрямую, либо запустив нашу задачу, как мы сделали с mix hello
, что запустит компиляцию за нас.
Важно отметить, что имена задач формируются на основе имени модуля, поэтому Mix.Tasks.MyHelper.Utility
станет my_helper.utility
.
Caught a mistake or want to contribute to the lesson? Edit this lesson on GitHub!