Do you want to pick up from where you left of?
Take me there

Користувацькі Mix завдання

Створюємо користувацькі Mix завдання для ваших Elixir проектів.

Вступ

Бажання розширити функціонал своїх Elixir додатків шляхом додавання користувацьких Mix завдань є досить поширеним. Перед тим, як ми дізнаємось як створювати особливі Mix завдання для наших проектів, давайте глянемо на вже існуюче завдання:

$ mix phoenix.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 .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.

Давайте створимо просту функцію для виведення “Hello, World!” в нашому файлі lib/hello.ex, який для нас згенерував Mix.

defmodule Hello do
  @doc """
  Щоразу виводить `Hello, World!`.
  """
  def say do
    IO.puts("Hello, World!")
  end
end

Користувацькі Mix завдання

Давайте створимо наше користувацьке Mix завдання. Створіть папку hello/lib/mix/tasks. Всередині створіть новий файл з назвою hello.ex та скопіюйте до нього код, наведений нижче:

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
    # викликає функцію Hello.say() з попереднього файлу
    Hello.say()
  end
end

Зауважте, як ми почали defmodule з Mix.Tasks й імені, за яким ми хочемо викликати завдання з командного рядку. В другому рядку у нас use Mix.Task, що привносить поведінку Mix.Task у цей простір назв. Потім ми оголошуємо функцію run, яка (поки що) ігнорує будь-які аргументи. Всередині цієї функції ми викликаємо наш модуль Hello і його функцію say.

Mix завдання в дії

Давайте перевіримо наше завдання 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             # Simply calls the Hello.say/0 function.
...

Зауваження: Наш код має скомпілюватися перед тим, як нові завдання з’являться в результаті виконання mix help. Це можна зробити або виконавши mix compile напряму, або виконуючи конкретно наше завдання. Другий спосіб ми використали раніше для того щоб скомпілювати mix hello.

Caught a mistake or want to contribute to the lesson? Edit this lesson on GitHub!