Эликсир — вызов функции модуля из оболочки

Есть ли в Эликсире способ вызвать функцию модуля непосредственно из оболочки, без необходимости запуска сеанса iex -S mix? Позвольте мне проиллюстрировать это сценарием:

Как часть моего приложения Phoenix, я написал вспомогательный модуль, который должен запускаться из соседнего сеанса iex -S mix. Вот супер-упрощенная версия:

defmodule MyApp.Helper do
  # For the demo, these imports/aliases are not used - but they're there in real life.
  import Ecto.Query
  alias MyApp.Repo

  def start do
    {:ok, "Done"}
  end
end

Если я запускаю сеанс с iex -S mix, а затем запускаю функцию из модуля, все работает нормально:

$ iex -S mix
Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Compiling 2 files (.ex)
Interactive Elixir (1.5.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> MyApp.Helper.start
{:ok, "Done"}

А затем ctrl-c a, чтобы закрыть сеанс.

Однако, если я попробую что-то вроде:

$ iex -S mix MyApp.Helper.start

Это приводит к

Erlang/OTP 20 [erts-9.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Compiling 2 files (.ex)
** (Mix) The task "MyApp.Helper.start" could not be found

В качестве альтернативы я попытался переопределить свой модуль как пользовательскую смешанную задачу, как описано здесь: https://elixirschool.com/en/lessons/basics/mix-tasks/#custom-mix-task

но это также не удалось, потому что мой модуль зависит от некоторых импортов/псевдонимов, таких как MyApp.Repo, и попытка выполнить файл с mix helper или iex -S mix helper привела к

** (ArgumentError) repo MyApp.Repo is not started, please ensure it is part of your supervision tree

Если нет никакого способа обойти это, и сценарий может быть успешно выполнен только из работающего iex -S mix, это нормально... но если бы был способ настроить все таким образом, чтобы однострочный код мог запускаться из оболочки, чтобы заставить это выполниться по мере необходимости, это будут колени пчелы.


person skwidbreth    schedule 04.04.2018    source источник


Ответы (1)


Вы можете использовать mix run с аргументом -e для этого:

$ mix run -e MyApp.Helper.start

или если у вас есть аргументы для передачи функции:

$ mix run -e "MyApp.Helper.start(:foo, :bar)"

От mix help run:

Если есть желание выполнить скрипт в текущем приложении или настроить приложение через флаги командной строки, это можно сделать, передав в команду файл скрипта или выражение eval:

mix run my_app_script.exs arg1 arg2 arg3
mix run -e "MyApp.start" -- arg1 arg2 arg3
person Dogbert    schedule 04.04.2018
comment
+1 — стоит добавить, что если вы хотите запустить однострочный код вне микс-проекта, вы можете передать --no-mix-exs в качестве аргумента; например: mix run --no-mix-exs -e 'IO.puts(:hello)' - person Darragh Enright; 12.03.2021