I'm wanting to store a tree structure in Postgres, and I'm hoping to embed an arbitrary Elixir struct on each node of the tree, something like this:
defmodule Node do
use Ecto.Schema
schema "nodes" do
belongs_to :parent_node, Node
embeds_one :struct, ArbitraryDataType
end
end
However, I believe embeds_one
requires a specific struct data type to be specified, which won't work for my case. Is there a way around this?
My backup plan is to use two fields, one for the struct type
and one for the struct fields
, like this:
defmodule Node do
use Ecto.Schema
schema "nodes" do
belongs_to :parent_node, Node
field :struct_type, :string
field :fields, :map
end
end
In order to save the record in the first place, I would need to use the __struct__
field to determine the struct type. Then, I would use logic something like the following to rebuild the original struct after retrieving the node from the database:
Enum.reduce(
retrieved_node.fields,
String.to_atom("Elixir.#{retrieved_node.struct_type}") |> struct,
fn {k,v}, s -> Map.put(s, String.to_atom(k), v) end
)
struct_type
? Structs are basically nothing but a map with__struct__
field. I would just store it as is (as a plain old good map) and you’ll getArbitraryDataType
out of the box. Am I missing something? – Indecipherablestruct_type
in the first place. – Resolve__struct__
key/value info. Therefore, when I retrieve the row from the database, I get a "regular" old map, not the struct I was hoping for — the type information is lost. – Downes