wwaldner

wwaldner

How to create some form of module registry that can be used to lookup a module by name?

Has anyone come up with a good way to create some form of module registry that can be used to lookup a module by name. My use case is to have a module that can deserialize a list of heterogeneous items. I would like the different items to be added to a registry automatically. Ultimately, it would be nice to ‘auto’ generate the Filters module below.

defmodule Filters do
  @moduledoc """
  Module that aids in dealing with filters. It acts as a registry that 
  knows about all the filter types at compile time.
  Supports serializing and deserializing a list of heterogeneous filter types.
  """

  # Serialize a specific filter, adding name to serialized value.
  # this can be better handled with `Protocols` and defimpl in __using__ macro. 
  # This is not the difficult part.
  def serialize(%Filter1{} = filter) do
    %{
        type: "filter1",
        value: Filter1.serialize(filter)
      } |> Jason.encode!()
  end

  def deserialize(s) when is_binary(s) do
     # s is a json encoded string that needs to be 
     # deserialized into one of the filter modules below

    deserialize(Jason.decode!(s))
  end

 # THIS IS THE FUNCTION THAT I WOULD LIKE TO GET AUTO GENERATED, or have
 # some kind of registry that can give me the module for some arbitrary name.
 #
 # Some means to create a specific struct given some name, in this case, "filter1"
 def deserialize(%{type: "filter1", value: value}) do
  Filter1.deserialize(value)
 end
end

defmodule Filter1 do
  # can something be done in the declaration of this module
  # to add it to the Filters module?
  def serialize(filter), do...
  def deserialize(data), do...
end

defmodule Filter2 do
...
end

Most Liked

zachdaniel

zachdaniel

Creator of Ash

Having gone down this road many times (trying to build lists of modules dynamically based on properties) I’d advise against it. It can work well enough for production, but in development mode things can get very frustrating very quickly because of incremental recompilation.

My general suggestion for this is to instead have a module that lists all of these, i.e

defmodule MyFilters do
  def filters, do: [Filter1, Filter2, Filter3]
end

And then add this:

defmodule Filter do
  defmacro __using__(_) do
    quote do
       @behaviour Filter

       unless __MODULE__ in MyFilter.filters() do
          raise "Hey, don't forget to put this module into the list in MyFilter"
       end
    end
  end
end

Then in each filter, you say

use Filter

which sets up the behaviour and also validates that you are in the registry of filters. This way, when someone inevitably copies one and renames it, they get a helpful error. Its not as convenient as having a module magically detect other modules, but trust me that kind of thing has so many edge cases.

Where Next?

Popular in Questions Top

itssasanka
Hi all, Trying to get some more clarity over utc_datetime and naive_datetime for Ecto: https://hexdocs.pm/ecto/Ecto.Schema.html#module-...
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
tduccuong
Hi, is there any work on GUI with Elixir, that is similar to Electron/Javascript? My idea is to bundle Phoenix and BEAM into a single se...
New
fireproofsocks
I’m working on defining a simple Ecto schema for a table (in PostGres), but I don’t see where I can define a column as NOT NULL. Conside...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New

Other popular topics Top

pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
malloryerik
Hi, this is for people who, like me, have had some friction using .html.heex templates in VSCode. The solution seems to be, in a hyphena...
New
chensan
I have a User schema with a :from_id field set to type :string: defmodule TweetBot.Repo.Migrations.CreateUsers do use Ecto.Migration ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New

We're in Beta

About us Mission Statement