I was thinking of resources like images, XML files or documents in other text formats. Is there something similar to the resources folder in Java (“src/main/resources”)? The goal would be to add files to my package that can be accessed from code on runtime.
Or is this somehow a very un-Elixir-y way of thinking? Elixir is my first functional language - so what would be the “right” way to do it?
That is precisely what the /priv folder is for in your project root. It’ll get packaged up along with your application when you build a release. If you have a data.xml file in your /priv directory you can get to it in your code by doing
priv - Used for application specific files. For example, C executables are placed here. The function code:priv_dir/1 should be used to access this directory.
Per Jose:
“priv” is like “OTP” where its name made sense at the beginning but today it has grown beyond that. All it matters now is that we put in the “priv” directory any artifact that you need in production alongside your code.
I am unable to open a File.stream! for the file in my /priv folder when running my escript-build. Do I have to fallback to Erlang? Using a path generated the way you described only works when starting the application in iex.
Edit
From the Mix.Tasks.Escript.Build:
Note: escripts do not support projects and dependencies
that need to store or read artifacts from the priv directory.
produced the path /path/to/my_app/my_app/priv/data.xml, where the first my_app corresponds the escript build file.
By replacing :code.priv_dir(:my_app) with app_dir(:my_app), I can get rid off the priv sub-folder, but that still does not allow me to open a valid file stream.
Hi @smon and @benwilson512, I’d also like to know if there are options to access the /priv folder for a command line utility built with escript. Please update if you’ve found anything. Thank you in advance!
To confirm: although priv is the appropriate place, we can’t load files from priv inside escripts. What I usually do is to load the file at compilation time and store it as a module attribute:
Just out of curiosity, if there are huge static files in the priv folder, will this way make the compiled binary huge? as well as the module loading time…
Thank you @NobbZ. Please pardon me(a newbie) for digging a bit more:
Where are the artifects stored after being loaded as a module attribute at compile time?
using the example Jose mentioned above @bar_contents File.read! "priv/foo/bar" , if priv/foo/bar is a huge vidoe file, what is the @bar_contents after the program being compiled(in the BEAM)? Is it something a pointer to the bar file or a thing holding all the data of that file.
Thanks a lot @NobbZ . Sorry for my question is not related to this topic. Anyway, just to confirm what I’ve understood so far:
By “copying files into an attribute”, are you saying @bar_contents File.read! "priv/foo/bar" is actually copying the bar into attribute bar_contents? (hence it increase the module size)
Your question is indeed related, though I misunderstood your first phrasing of the question, as you asked solely about the Priv folder not about attributes. I should have scrolled back to the post you have quoted, then I might have seen it in the context…
Yes. File.read! returns the file content as a binary, so the attribute will contain the binary representing the files content. Though it won’t be saved as part of the module until the attribute is actually used in a way that would “generate appropriate code” or persisted into the module by using Module.register_attribute (I might misremember the function name).
Thank you very much @NobbZ. I’m clear now. I’ve compiled a simple code reading a big file into an attribute. The compiled beam file is big, so the loaded binary is indeed stored in the beam file( whereelse could it be anyway
I actually love this way to handle runtime resourcse that have to be deliveried along with the release. It make the release structure simple and neat. No matter they’re in the /priv folder or in beam files, you need pack them into somewhere in your release anyway.