tfwright
I have a library (MyLib) that I use for part of another app’s functionality (MyApp). I’d like to add some conditional code (an Ecto schema definition) to one of the library’s modules only if MyApp has a particular config that points to one of MyApp’s modules (also an Ecto schema). I was hoping to call a function on the MyApp module to get the info about it I need, but it appears to break compilation in certain circumstances because MyApp hasn’t been compiled yet (I was trying to call __schema__/2 to get info about an association).
One option would be to require the MyApp config specify all the data MyLib needs, but that feels a bit clunky and redundant. Is there a way to force MyApp to compile first so that MyLib can access its module’s functions during compilation time? Or is there another, better way to go about what I’m trying to do?
Appreciate any tips/suggestions.
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #blog-post
- #phoenix_html
- #ai
- #iex
- #graphql
- #elixirconf-us
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming










Showing Posts 1 to 10- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
kip
You may need to use
Code.ensure_compiled/1to force compilation order if it isn’t being detected the way you want.The documentation notes that this is not a function you should commonly reach for. However forcing compilation order at compile time is one reasonable use.
tfwright
This doesn’t seem to work for my use case, perhaps I using it incorrectly? My current implementation looks like this:
Instead of breaking compilation
#do something with modulefails to run and I get the warning instead. The docs says the functionI’m not sure what “project” technically means here. I had hoped it meant something like “MyApp and all deps except the current one”, but it looks like it just means “all files in MyLib except this one”?
kip
It would be helpful to know:
Application.get_env(:my_lib, :some_config)istfwright
Elixir.MyApp.ConfigModuleunavailablekip
Thanks. That return code pretty much says its compiled everything and that module wasn’t found. Just to be really sure, the module is actually defined as
defmodule MyApp.ConfigModulenotdefmodule Elixir.MyApp.ConfigModule?Is
:my_liba dependency of the project? So that it will be compiled first, before the current project?tfwright
Yep.
Is
:my_liba dependency of the project?Yes, exactly.
So when I compile the project (MyApp) I see
kip
Ah, I see. Compilation order is dependencies first, then the current project. Where current project is the one that has
mix.exsin it when you didmix.compile. Dependencies are compiled first and they do not create a transitive association with the “current” project. Understandably so - libraries aren’t built to make assumptions about the projects that use them.TLDR; A dependency depending on the consumer of the dependency isn’t going to work
kip
The common pattern in Elixir to handle this kind of situation is to introduce a new module into the current project and then
usethe code from the dependency so you can create a relationship. This is what I do heavily in theex_cldrlibs for pretty much the same reason you have - conditional compilation of library code based upon configuration in consumer code.kip
To explain additionally why conditional compilation in a dependency isn’t a good idea I should point out that the dependency could be used my multiple different consuming libraries in the same runtime environment and therefore unpredictable behaviour would ensue.
tfwright
I had a feeling that something like this would be the correct option. Otherwise the config is going to extremely unwieldy and redundant. I’m just not quite sure the right approach since coming from Ruby typically we’re able to just change everything at runtime (
), exactly the kind of thing I’m learning Elixir to get away from…
I’m thinking I need to add some sort of boilerplate module that the client app can
usein their own module, overriding the defaults somehow without actually changing how the original module is compiled. Does that sound generally like the right track to investigate?The lib I’m working on is open source, and the current code I’m working on is here, if you’re curious.