How do I use a schema macro in an extension?

I want to make an Ash extension that adds a :uuid_v7_primary_key attribute to a resource. Adding an attribute via a macro: This is an antipattern but it’s a small example. The macro definition (Geo.Resources.Attributes.Id): https://github.com/dev-guy/geo/blob/e6aaf95d63961b4e40df6f51ac382393840c010a/lib/geo/resources/attributes/id.ex Using it: https://github.com/dev-guy/geo/blob/70baa42f3ea8a5b092345e478f61a552fb79d9fb/lib/geo/country/country.ex Adding an attribute via an extension: Macros are great but they are not Ashy. As with the macro, can I reuse uuid_v7_primary_key in an extension? Claude tried and got syntax errors (below) The extension definition: https://github.com/dev-guy/geo/blob/e6aaf95d63961b4e40df6f51ac382393840c010a/lib/geo/resources/extensions/id.ex Using it: https://github.com/dev-guy/geo/blob/e6aaf95d63961b4e40df6f51ac382393840c010a/lib/geo/geography/country.ex Do I have to essentially reimplement :uuid_v7_primary_key? Error:
== Compilation error in file lib/geo/geography/country.ex ==
** (RuntimeError) Exception in transformer Geo.Resources.Extensions.Id.Transformer on Geo.Geography.Country:

no function clause matching in anonymous fn/2 in Keyword.split/2
(elixir 1.18.4) lib/keyword.ex:1213: anonymous fn(:id, {[], []}) in Keyword.split/2
(elixir 1.18.4) lib/keyword.ex:1221: Keyword."-split/2-lists^foldl/2-1-"/3
(elixir 1.18.4) lib/keyword.ex:1221: Keyword.split/2
(spark 2.2.67) lib/spark/dsl/transformer.ex:177: Spark.Dsl.Transformer.do_build/2
lib/geo/resources/extensions/id.ex:19: Geo.Resources.Extensions.Id.Transformer.transform/1
(spark 2.2.67) lib/spark/dsl/extension.ex:661: anonymous fn/4 in Spark.Dsl.Extension.run_transformers/4
(elixir 1.18.4) lib/enum.ex:4968: Enumerable.List.reduce/3
geo/lib/geo/geography/country.ex:1: (file)
== Compilation error in file lib/geo/geography/country.ex ==
** (RuntimeError) Exception in transformer Geo.Resources.Extensions.Id.Transformer on Geo.Geography.Country:

no function clause matching in anonymous fn/2 in Keyword.split/2
(elixir 1.18.4) lib/keyword.ex:1213: anonymous fn(:id, {[], []}) in Keyword.split/2
(elixir 1.18.4) lib/keyword.ex:1221: Keyword."-split/2-lists^foldl/2-1-"/3
(elixir 1.18.4) lib/keyword.ex:1221: Keyword.split/2
(spark 2.2.67) lib/spark/dsl/transformer.ex:177: Spark.Dsl.Transformer.do_build/2
lib/geo/resources/extensions/id.ex:19: Geo.Resources.Extensions.Id.Transformer.transform/1
(spark 2.2.67) lib/spark/dsl/extension.ex:661: anonymous fn/4 in Spark.Dsl.Extension.run_transformers/4
(elixir 1.18.4) lib/enum.ex:4968: Enumerable.List.reduce/3
geo/lib/geo/geography/country.ex:1: (file)
Solution:
YOu can do Ash.Resource.Builder.add_new_attribute(dsl_state, ....)
Jump to solution
3 Replies
Terris
TerrisOP3mo ago
I think I see where Claude messed up. It used uuid_v7_primary_key as an atom instead of using the macro. This extension works: https://github.com/dev-guy/geo/blob/702c58a366687f383381dc9b69fd58c35432f0ac/lib/geo/resources/attributes/id.ex but I was hoping to leverage the uuid_v7_primary_key schema. Excerpt:
def transform(dsl_state) do
attribute = %Ash.Resource.Attribute{
name: :id,
type: :uuid_v7,
allow_nil?: false,
writable?: false,
public?: true,
primary_key?: true,
default: &Ash.UUIDv7.generate/0
}
def transform(dsl_state) do
attribute = %Ash.Resource.Attribute{
name: :id,
type: :uuid_v7,
allow_nil?: false,
writable?: false,
public?: true,
primary_key?: true,
default: &Ash.UUIDv7.generate/0
}
Solution
ZachDaniel
ZachDaniel3mo ago
YOu can do Ash.Resource.Builder.add_new_attribute(dsl_state, ....)
ZachDaniel
ZachDaniel3mo ago
or in your case if you just want to build it then Ash.Resource.Builder.build_attribute/3 nothing does the uuidv7 schema but you can copy build_attribute example to make your own for build_uuidv7_primary_key

Did you find this page helpful?