Skip to content

Resource generator: many-to-many, views, no-PK tables, and prompt UX#748

Merged
zachdaniel merged 8 commits into
ash-project:mainfrom
weljoda:feature/resource-generator-improvements
May 14, 2026
Merged

Resource generator: many-to-many, views, no-PK tables, and prompt UX#748
zachdaniel merged 8 commits into
ash-project:mainfrom
weljoda:feature/resource-generator-improvements

Conversation

@weljoda
Copy link
Copy Markdown
Contributor

@weljoda weljoda commented May 13, 2026

Contributor checklist

Leave anything that you believe does not apply unchecked.

  • I accept the AI Policy, or AI was not used in the creation of this PR.
  • Bug fixes include regression tests
  • Chores
  • Documentation changes
  • Features include unit/acceptance tests
  • Refactoring
  • Update dependencies

This PR improves mix ash_postgres.gen.resources adding many_to_many detection, views and better conflict resolution. See: https://discordapp.com/channels/711271361523351632/1495458363960721629

I also set up an example project with a legacy DB schema, to test the generator on a real-world schema. https://github.com/weljoda/gen_resources_example

New capabilities

  • many_to_many detection. When a table is a pure join table (two FKs to two distinct tables, identity backed by either a composite primary key or a unique index over both FK columns), the generator now emits a many_to_many on each endpoint alongside the has_many to the join resource.
  • PostgreSQL VIEW / MATERIALIZED VIEW support via --include-views. View-backed resources are emitted with migrate? false and a :read-only default action. The underlying introspection queries were ported from information_schema to pg_catalog so views are discoverable at all.
  • Tables without a primary key are now generated with require_primary_key? false and a :read, create: :* default action, each carrying a # WARNING: comment pointing the user at the fix.
  • --skip-many-to-many flag for users who prefer just has_many on join tables.

Conflict-resolution UX overhaul

When multiple FKs produce duplicate default relationship names, the generator now:

  • Shows full conflict context (resource, type, destination, FK column, constraint name) and a suggests an alternative name when common naming patterns are detected.
  • Offers a menu with the following options: use suggested, auto-resolve remaining on this resource, skip this relationship.
  • Tracks a [seen/total] progress counter so you know how many prompts are left per resource.
  • Resolves names against existing attributes and previously named relationships, recursing until no collisions remain.

In my usecase this reduced the prompts by using auto-resolve to 4 from 58 previously.

Bug fixes folded in

  • opts[:yes] was being checked as opts[:yes?], so --yes never actually short-circuited the conflict prompts. Fixed.
  • add_primary_key/2 was called with a boolean instead of the attribute struct, so its pattern match never fired and composite-PK join tables. Previously the compiler raised an error when generating resources with composite-PK join tables.

Generated-code ordering

  • relationships do now groups by type (belongs_to → has_one → has_many → many_to_many) then alphabetical within each group, instead of all-alphabetical with many_to_many interspersed.
  • references do is alphabetical by relationship name, matching the belongs_to order rather than FK-insertion order.

weljoda added 8 commits May 13, 2026 09:30
instead of composite primary keys

join_table?/1 previously required the table's primary key to equal the
two FK columns. Hibernate / legacy schemas commonly enforce join-table
uniqueness with a UNIQUE INDEX over (a, b) instead of a PRIMARY KEY
constraint, so those tables silently fell through and no many_to_many
was generated.

Accept either signal: composite PK matching the FK columns, OR a
unique index (with no WHERE clause) covering exactly the FK columns.
@zachdaniel zachdaniel merged commit 6f6695c into ash-project:main May 14, 2026
111 of 121 checks passed
@zachdaniel
Copy link
Copy Markdown
Contributor

🚀 Thank you for your contribution! 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants