问题
I have an elixir console configuration stored in .iex.exs
:
if Code.ensure_loaded?(MyApp.Repo) do
alias MyApp.Repo
end
I want to have an ability to run both iex
and iex -S mix
. I'll have exception if I remove condition on iex
.
But this conditions doesn't work well! Even on iex -S mix
I have (module Repo is not available)
error if I'm trying to invoke Repo.get(...)
. So, my questions are:
- Why
Code.ensure_loaded?
doesn't work here? - How can I fix that?
回答1:
This is a matter of scoping. Inside a block, you have this alias defined:
if Code.ensure_loaded?(MyApp.Repo) do
alias MyApp.Repo
Repo.get(...) #⇒ available
end
To define an alias
IEx-wide, you should call it outside of any block:
alias MyApp.Repo
You do not need a conditional if Code.ensure_loaded?(MyApp.Repo)
when IEx
is executed with iex -S mix
, all the dependencies will be loaded for you automagically. For pure iex
this might be done in more cumbersome way:
defmodule FileExt do
def ls_all(dir, acc \\ []) do
case File.ls(dir) do
{:ok, list} -> list |> Enum.reduce(acc, fn f, acc ->
fullname = dir <> "/" <> f
if fullname |> File.dir?, do: ls_all(fullname, acc), else: acc ++ [fullname]
end)
{:error, e} ->
IO.puts "Unable to list. Reason: #{e}"
acc
end
end
def require_lib do
try do
"lib" |> FileExt.ls_all |> Kernel.ParallelRequire.files
rescue
e in UndefinedFunctionError -> Code.ensure_loaded?(MyApp.Repo)
end
end
end
try do
MyApp.Repo.get
rescue
e in UndefinedFunctionError -> FileExt.require_lib
end
alias MyApp.Repo
The above would load all files from the "lib"
directory.
Though I would shut the perfectionism up here and go with iex -S mix
always, without check:
Code.ensure_loaded?(MyApp.Repo)
alias MyApp.Repo
来源:https://stackoverflow.com/questions/39503311/code-ensure-loaded-in-iex-exs