Compiling models before selected external dependency

I have Phoenix app which uses oauth2 protocol to provide protected api. In order to do that I use Shield library: https://github.com/mustafaturan/shield.

Problem that occurs in my case is related with compilation order. In Shield library on compile time I can provide my own model to be used as main resource. Since shield library is compiled before my project, it doesn’t know anything about existance of this model. I’m getting:

** (CompileError) lib/shield/policies/user/register.ex:21: MyApp.User.__struct__/1 is undefined, cannot expand struct MyApp.User

I tried this configuration:

def project do
    [app: :my_app,
     version: "0.0.1",
     elixir: "~> 1.4.1",
     elixirc_paths: elixirc_paths(Mix.env),
     compilers: [:phoenix, :gettext] ++ Mix.compilers,
     build_embedded: Mix.env == :prod,
     start_permanent: Mix.env == :prod,
     aliases: aliases(),
     deps: deps()]
end

def application do
    [mod: {MyApp, []},
     extra_applications: [:logger, :my_app, :shield]]
end

defp deps do
    [{:phoenix, "~> 1.2.4"},
     {:phoenix_pubsub, "~> 1.0"},
     {:phoenix_ecto, "~> 3.0"},
     {:postgrex, ">= 0.0.0"},
     {:phoenix_html, "~> 2.6"},
     {:phoenix_live_reload, "~> 1.0", only: :dev},
     {:gettext, "~> 0.11"},
     {:cowboy, "~> 1.0"},
     {:ex_machina, "~> 2.0"},
     {:shield, "~> 0.7.0"},
     {:timex, "~> 3.1.24"}]
end

And it didn’t help. How to make sure that my app models are compiled and visible for external libraries on compile time ?

Can you point to your code or to a minimal project that reproduces your error while not doing anything else?

With the code you’ve shown us, its not even clear why there pop ups a MyApp.User.

Taking a look into the github issues, it seems to be much more of a runtime than a compiletime error. I found the issue https://github.com/mustafaturan/shield/issues/34, which is describing a problem similar to yours.

It seems as if you need to remove :shield from your extra_applications and add it to :included_applications. You will need to start it on your own then, when your own application starts.

But that is only a rough guess, and I do not guarantee for anything. If you can’t get it to work, please consider opening an issue at the githuib project.

I reproduced it here: https://github.com/szsoppa/deps_issue.
In order to see an error you can try

mix deps.clean --all && mix deps.get && mix ecto.reset

The application in that project is fundamentally different from what you have shown us here!

Your sample application does use old :applications-key while your first example in the OP uses elixir 1.4 and application inference.

Solving the problem might be different in both cases. Have you tried my suggestion from my earlier answer?

I’m sorry - I was testing both solutions - with :applications and :extra_applications and pushed wrong version eventually. After all, both doesn’t work, as well as :included_applications as you proposed.

I pushed changes to this repo, to match with :extra_applications. You can try it now.

Okay, having taken a closer look, I have no clue how this could have ever worked for anyone when you define the owner in your main app.

As it seems, shield seems to require that your owner is part of another dependency, which you have to juggle around to actually be able to use it.

Perhaps anyone else can help you out, but I can’t :frowning: