Ah, sorry I was not trying to roast you I promise . I didn’t mean for that to sound rude. Only that this is the essentially the foundation of what I’m trying to do.
Ash doesn’t come with any cross-language code generation tools, but it is the general programming pattern with Ash. You describe your domain using data structures (i.e Ash.Resource
). It acts simultaneously as a tool to interact with your domain, and the source of truth for anything you project from it.
We generate migrations, for example, automatically. You can see for yourself:
Generate a scaffold of an app
mix archive.install hex igniter_new
mix igniter.new your_app --install ash,ash_postgres
cd your_app
mix ash.gen.resource YourApp.Accounts.User \
--uuid-v7-primary-key id \
--attribute username:string:required \
--default-actions create,read,update,destroy \
--timestamps \
--extend postgres
mix ash.gen.resource YourApp.Twitter.Tweet \
--uuid-v7-primary-key id \
--attribute text:string:required \
--relationship belongs_to:author:YourApp.Accounts.User \
--timestamps \
--extend postgres
Run codegen
Codegen by default only will generate the required migrations, but any extension can tap into the codegen step to add its own behavior.
mix ash.codegen initial_setup
That command generates:
defmodule YourApp.Repo.Migrations.InitialSetup do
@moduledoc """
Updates resources based on their most recent snapshots.
This file was autogenerated with `mix ash_postgres.generate_migrations`
"""
use Ecto.Migration
def up do
create table(:users, primary_key: false) do
add(:id, :uuid, null: false, default: fragment("uuid_generate_v7()"), primary_key: true)
add(:username, :text, null: false)
add(:inserted_at, :utc_datetime_usec,
null: false,
default: fragment("(now() AT TIME ZONE 'utc')")
)
add(:updated_at, :utc_datetime_usec,
null: false,
default: fragment("(now() AT TIME ZONE 'utc')")
)
end
create table(:tweets, primary_key: false) do
add(:id, :uuid, null: false, default: fragment("uuid_generate_v7()"), primary_key: true)
add(:text, :text, null: false)
add(:inserted_at, :utc_datetime_usec,
null: false,
default: fragment("(now() AT TIME ZONE 'utc')")
)
add(:updated_at, :utc_datetime_usec,
null: false,
default: fragment("(now() AT TIME ZONE 'utc')")
)
add(
:author_id,
references(:users,
column: :id,
name: "tweets_author_id_fkey",
type: :uuid,
prefix: "public"
)
)
end
end
def down do
drop(constraint(:tweets, "tweets_author_id_fkey"))
drop(table(:tweets))
drop(table(:users))
end
end