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

hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a > b) do {:ok, "a"} end if (a < b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
LegitStack
I’m trying to make a websocket server in Phoenix or raw Elixir. I heard about gun, I think I could use cowboy, but since I’m not that sma...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New

Other popular topics Top

hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a > b) do {:ok, "a"} end if (a < b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
TunkShif
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
274 41989 114
New
Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
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
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New

We're in Beta

About us Mission Statement