`:code.priv_dir(:my_app)` points to `priv` directory in `_build`

Hello,

I want to specify the path to the priv directory for user file uploads; I found this code:

:code.priv_dir(:my_app)

But it points to the priv directory in the _build directory:

‘c:/projects/my_app/_build/dev/lib/my_app/priv’

But then I was wondering, what is the difference with the priv directory in the root folder? I.e.

‘c:/projects/my_app/priv’

Are those two directories somehow in sync? Can I use the one or the other interchangeably?

3 Likes

We are just in sync, I had the same thoughts.

But it’s not the same priv directory… the one You mention is for release. While the other is being used when starting the project with mix.

If You run this as a release, You can use

:code.priv_dir(:my_app)

# or 

Application.app_dir(:my_app)

# They are not really equivalent! but You can choose between both.

When it is used with mix, You should use priv from application root folder, because it is served by plug static.

I configured a path for dev and test, and when it is not configured… for example in prod, I use this

# in dev and test
config :waffle, storage_dir: "priv/static/uploads"

# in the uploader
  def storage_dir(version, {_file, scope}) do
    Path.join uploads_root(), "/painting/display_images/#{version}/#{scope.id}"
  end

  defp uploads_root do
    Application.get_env(:waffle, :storage_dir) || Application.app_dir(:calabrese, "priv/static/uploads")
  end

This allows me to have a different config between dev (mix) and prod (release).

It’s not the only way, You can also test if Mix is available with.

function_exported? Mix, :__info__, 1

# true with mix
# false in release

I found it was more elegant to define a static path for dev and test only than checking if Mix is available.

1 Like

Why doesn’t Application.app_dir handle that? :sob:
I.e. if the app is run by mix, point to the root folder instead of the _build/dev/lib/... folder. You have to set some configs, add code, … to handle that; if the Elixir core function detected it that would have avoided all this code.

I am not a Core Team member :slight_smile:

But it’s easy to check how You run your application.

In dev mode, the my_app/priv dir is symlinked to to my_app/_build/dev/..... In prod it is copied to that dir. It’s actually controlled by the build_embedded key in the project/0 function in mix.exs.

This is because Elixir runs your compiled code which is stored in the my_app/_build directory. Since priv is build artifact, it is located there as well.

I think its better to consider the :code.priv_dir/1 to be part of the build process, not part of the runtime environment. And therefore I’d suggest considering an alternative location for your uploads.

8 Likes