Arjun Singh
Arjun Singh

Reputation: 697

Storing module names inside map in database

I am creating a notification service for an IOT app using Elixir/Ecto/Phoenix. A sensor in this app can have multiple values e.g.

temperature: ["temp"],
accelerometer: ["ax", "ay", "az"]

To create a generic notification policy I have to store the module name with the sensor which will implement the logic for handling eligibility rule. Also, since each sensor can have multiple values associated with it accelerometer -> ax, ay, az the module can be different for different values.

  schema("acqdat_sensor_notifications") do
    field(:rule_values, :map)
    field(:alarm_status, :boolean, default: false)
    belongs_to(:sensor, Sensor, on_replace: :delete)

    timestamps()
  end

The rule values column will store data in the following format e.g. for accelerometer sensor.

%{
  "ax" => %{ 
    module: "NotificationPolicyA", 
    module_preferences: {"prefA": valuea, "prefb": valueb}
  },
  "ay" => %{ 
    module: "NotificationPolicyB", 
    module_preferences: {"pref1": value1, "pref2": value2}
  },
}

The problem here is storing the module name which will handle the logic. I can not use enumeration library like ecto_enum as the values are stored in a jsonb map which is not constant(can not use embeds here). It keeps changing with the sensor name and the module used for processing it.

At present I am handling it by using a map

%{
  NotificationPolicyA: 0, 
  NotificationPolicyA: 1 
  .
  .
  .
}

and then storing the integers in the db so that if the module name is modified only the map is changed.

"ax" => %{ 
    module: 0, 
    module_preferences: {"prefA": valuea, "prefb": valueb}
  }

What could be alternate approach to handle this kind of scenario with ecto?

Upvotes: 0

Views: 155

Answers (1)

Marcos Tapajós
Marcos Tapajós

Reputation: 564

You can store the module name as string on the database, use String.to_existing_atom/1 to convert it and Kernel.apply/3 to run any function that you need.

Example:

iex(2)> apply(String.to_existing_atom("Elixir.MyApp.Version"), :run, [1])
0.29.1

Upvotes: 2

Related Questions