What’s the best approach to storing a simple Elixir struct as an Ash Resource attribute?
Should I be implementing the Ash.Type callbacks in the custom module?
I initially (naively!) tried to set the attribute to be of type Ash.Type.Struct - along the lines of:
attribute :foo, Ash.Type.Struct do
allow_nil? true
constraints instance_of: Play.Foo
end
And the Ash code generator created a migration adding a map to the table:
alter table(:things) do
add(:foo, :map)
end
All looks fine until I try to “commit” the changeset when I hit a type mismatch:
** (Ecto.ChangeError) value %Play.Foo{id: "John", name: 23} for Play.Model.Thing.foo in insert_all does not match type ash.Type.Struct.EctoType<[instance_of: Play.Foo, preserve_nil_values?: false]>
So is the correct approach to take control over the conversion using Ash.Type?
Thanks (and sorry for all of these questions - but I love exploring Ash)
You can specify the fields constraint and model the fields, which should allow you to do that. I fixed some bugs w/ the struct type recently so make sure to update.
attribute :foo, Ash.Type.Struct do
constraints instance_of: Play.Foo, fields: [foo: [type: :string, allow_nil?: false]]
end
You can use Ash.Type.NewType to make this more seamless:
defmodule Play.Foo do
destruct [:foo]
use Ash.Type.NewType, subtype_of: :struct, constraints: [
instance_of: __MODULE__,
fields: [foo: [type: :string, allow_nil?: false]]
]
end
I’m curious (however) as to what was the best path that I should have taken to discover the Ash.Type.NewType module. How best to attack the documentation and found it to exploit/use.
Is there a guide that mentions this as a strategy to explore?
I’ve just found it mentioned in the “Define Polymorphic Relationships” guide - but that wouldn’t have been a place that I would have considered for the scope of this mini-problem.
Yeah, you’re totally right. We should surface Ash.Type.NewType high up on the Ash.Type docs. If you could open a proposal or a PR that would be excellent