One approach that can help make macros more powerful to use and easier to write: avoid parsing the contents of do blocks if you can.
An example in Ecto.Schema:
block is the block passed to the schema macro, which sets up a “prelude” and “postlude” and then expands the block as regular AST. This side-steps the need for code like Nexus.build_subcommands and lets users do things like:
schema do
%w(foo bar baz wat)a
|> Enum.each(fn name ->
field name, :string
end)
end
Calls to field accumulate data in module attributes, then the postlude built by schema uses them to construct __schema__ and so forth.
Another spot in that file worth reviewing for inspiration - the code in embeds_one and embeds_many that handles declaring a (nested) schema inline using a nested module:
One more technique to consider: use __before_compile__ to generate code “at the end” of the module.
use Nexuswould set up a@before_compile- then each call to
defcommandwould accumulate details in module attributes - then the
before_compilecould generate the@typeanddefstructlines using all the accumulated commands


















