Reputation: 697
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
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