user2694306
user2694306

Reputation: 4060

Elixir List All Modules in Namespace

I am working on an Elixir/Phoenix app that is intended to create a user in my UserController controller. There is a /lib/helpers/user_helpers directory with a number of modules (each in a separate file). These modules all have a common namespace UserHelpers.ModuleName. In each of these modules I have a function called apply which I want to apply to the user data. For example if I have the following file structure:

-lib
    -helpers
        -user_helpers
            -module1
            -module2
            -...
            -moduleN-1
            -moduleN

where each of module1 and module2 contains a function apply(user_info) which returns user_info. In my UserController I have the function create(conn, params) in which I want to run the following:

user_data
|> UserHelpers.Module1.create
|> UserHelpers.Module2.create
|> ...
|> UserHelpers.ModuleN-1.create
|> UserHelpers.ModuleN.create

But I'm unsure how to dynamically load all of the modules in the UserHelpers folders to do the above. Any suggestions?

Upvotes: 10

Views: 6062

Answers (1)

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121010

Assuming, that your application is called :my_app and helpers have the .ex extension and/or explicitly compiled into your application:

with {:ok, list} <- :application.get_key(:my_app, :modules) do
  list
  |> Enum.filter(& &1 |> Module.split |> Enum.take(1) == ~w|UserHelpers|)
  |> Enum.reduce(user_data, fn m, acc -> apply(m, :create, acc) end)
end

:application.get_key(:my_app, :modules) returns the list of modules, known to that application. The second line filters out those unneeded, and the latter one applies their :create functions to user_data subsequently.

You probably want to embed Enum.sort just before the last line to sort the modules to apply in the appropriate order.

Upvotes: 21

Related Questions