Skip to main content

Taxonomy::CategoryRequest

Purpose

A CategoryRequest records what an employer wanted when none of the 18 job categories fit. When an employer selects "Others" in the job form's category picker, an optional input appears — "What kind of job is this?" — and what they type is saved here, together with a JSON snapshot of the job form at that moment.

This table is the evidence behind the taxonomy growth rules: a new category is added when 3+ distinct employers ask for the same concept, or 5+ similar Others postings pile up. Before this table existed, the weekly review could only guess from job titles filed under Others.

The row is saved when the input loses focus, not when the job is submitted. An employer who types "dog groomer", finds no fitting category, and abandons the form is the strongest signal that the taxonomy has a gap — waiting for a successful job submit would lose exactly those cases. That is why careers_job_snapshot may hold values from a form that was never submitted.

Model Context

ContextDetails
Written byPOST /employers/taxonomy/category_requests (employers actor). The frontend fires it once per form session, on input blur, re-firing only if the text changed. Failures are silent — the request never blocks posting a job.
Read byThe weekly Others review, via Metabase or the console. No admin UI in v1.
LifecycleAppend-only. Rows are never updated or deleted, and there is deliberately no status column (our convention: append-only tables carry no status). The outcome of a request lives in the taxonomy itself — a promoted or widened category — not as per-row workflow state.

Schema

Table: taxonomy_category_requests

ColumnTypeConstraintsNotes
idbigintpk
uuidstringunique, not nullstandard for every new table
namestringnot nullthe employer's answer to "What kind of job is this?"; max 100 characters, enforced in the validator
careers_job_snapshotjsonbnot null, default {}the job form values at request time — the context behind the request; may be from an unsubmitted form
created_bybigintnot null, FK → org_membershipswho asked; joined to company for the distinct-employer count
created_attimestamptznot nullthe weekly review reads new rows by this
updated_attimestamptznot null

How the weekly review uses it

  • name says what was asked for.
  • careers_job_snapshot shows the job behind the request (title, description, pay) — enough to judge whether two requests are the same concept.
  • created_by joined to org_memberships → company gives the distinct-employer count for the promote bar.

Refs