Skip to content

Reduce enum boilerplate: single rename attribute for DbEnum types #258

Description

@martsokha

Problem

Every nvisy_postgres DB enum repeats each variant's string value across three attributes:

/// Workspace settings or metadata were updated
#[db_rename = "workspace.updated"]
#[serde(rename = "workspace.updated")]
#[strum(serialize = "workspace.updated")]
WorkspaceUpdated,
  • The string is duplicated 3× per variant. A typo in one silently diverges the DB value from the wire value — a real correctness hazard, not just verbosity.
  • ~19 enums under crates/nvisy-postgres/src/types/enums/ follow this pattern; the largest (activity_type, 32 variants; webhook_event, 24) are mostly this boilerplate (152 lines for 24 variants).

Proposed direction

Collapse the three renames into one value, while keeping the enum, its derives, per-variant doc comments, and hand-written impl blocks exactly as they are (readability + rustdoc + grep intact):

/// Workspace settings or metadata were updated
#[db_str = "workspace.updated"]   // expands to db_rename + serde(rename) + strum(serialize)
WorkspaceUpdated,

This enforces the three stay in sync by construction.

Design notes / caveats (from investigation)

  • A full postgres_enum! generator that owns the enum is NOT recommended. The enums aren't uniform: they differ in derives (IntoStaticStr on some), #[default] variants, Hash, the schema cfg_attr, section comments, and each has custom impls (category(), DOCUMENTS, as_subject()). A generator would either drop that expressiveness or become as noisy as what it replaces.
  • Container-level #[serde(rename_all)] + #[strum(serialize_all)] won't work for the dotted event enums (WorkspaceUpdatedworkspace.updated is not a mechanical case transform). It could work for the simple lowercase enums (Originaloriginal) but that's a minority and mixing approaches adds inconsistency.
  • file_kind currently omits strum(serialize) (its strum Display is the variant name, not the db value) — so the enums aren't even consistent about which three attributes apply. The macro must not silently change that enum's Display output.
  • A per-variant attribute macro requires a proc-macro crate (attribute macros can't be macro_rules!) — a new workspace crate + syn/quote. That's the main cost to weigh. Alternative: a macro_rules! that generates the enum but only handles the common case, leaving irregular enums hand-written (no new crate, less flexible).

Decision needed

Proc-macro attribute (cleanest, new crate) vs. macro_rules! generator (no new crate, less flexible). Behavior must be identical for every existing enum — verify file_kind's Display and all DB round-trips are unchanged.

Metadata

Metadata

Assignees

No one assigned

    Labels

    postgresORM, models, queries, migrationsrefactorcode restructuring without behavior change

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions