Short form vs long form (inline --fields vs YAML --from)

When each shines, and exactly what the long form lets you express that the short form can't.

8 minmedium

You've been mixing them all chapter β€” the inline --fields "…" form for quick resources, the --from x.yaml form when you needed default: or unique: on a belongs_to. This lesson is the explicit comparison: when each one earns its keep, and which one you reach for in which situation.

The same resource, both ways

Here's a realistic Article resource β€” title with slug, hero image, formatted body, status with a default β€” written in both forms side-by-side.

Short form (inline --fields)

Terminal
$grit generate resource Article \
$ --fields "title:string,slug:slug,cover:string,body:richtext,published:bool"

Long form (YAML)

article.yaml
name: Article
fields:
- name: title
type: string
required: true
- name: slug
type: slug
slug_source: title
- name: cover
type: string # URL heuristic β†’ VARCHAR(500)
- name: body
type: richtext
- name: status
type: string
default: draft # ← only YAML can set defaults
- name: published
type: bool
default: false
Terminal
$grit generate resource Article --from article.yaml

Both produce the same 8 generated files except the YAML version also sets the database defaults (status = 'draft', published = false) and is committed into the repo β€” which means the next teammate who pulls can regenerate the resource from scratch by re-running the same command.

What each form supports

FeatureInline --fieldsYAML --from
All 13 field typesβœ“βœ“
required / optional / uniqueβœ“βœ“
default valuesβœ—βœ“
unique on a belongs_to (one-to-one)βœ—βœ“
Slug slug_source overrideβœ“ (third colon)βœ“ (explicit key)
Re-runnable / version-controllableSort of (commit message)βœ“ (committed file)
Comments next to each fieldβœ—βœ“
Reads cleanly past 5 fieldsβœ— (one long line)βœ“

YAML field reference β€” the full spec

Each field entry under fields: accepts seven keys. Most have inline equivalents β€” two don't:

- name: <field_name> # camelCase or snake_case β€” required
type: <field_type> # one of the 13 types β€” required
required: true|false # default depends on type (string=true, others=false)
unique: true|false # adds DB unique index. Works on belongs_to (1-to-1!).
default: <value> # DB default. YAML-only.
slug_source: <field_name> # for type: slug β€” which field to slugify from
related_model: <ModelName> # for type: belongs_to or many_to_many β€” what it points at

That's the whole long-form vocabulary. The inline form compresses the first four into colons (name:type:modifier) and uses the third colon-separated slot for slug_source / related_model:

InlineYAML equivalent
name:string{ name: name, type: string, required: true }
phone:string:optional{ name: phone, type: string, required: false }
email:string:unique{ name: email, type: string, required: true, unique: true }
slug:slug:sku{ name: slug, type: slug, slug_source: sku }
group:belongs_to:Group{ name: group, type: belongs_to, related_model: Group }
tags:many_to_many:Tag{ name: tags, type: many_to_many, related_model: Tag }

When to reach for which

Use the short form when…

  • You have 1–5 fields and no defaults.
  • You're prototyping β€” the field list will probably change before this resource is real.
  • You want the command to fit in a commit message or a chat message to a teammate.
  • You're pairing live and reading the spec out loud.

Use the long form (YAML) when…

  • You need default values, or you need unique on a belongs_to (one-to-one).
  • You have more than 5 fields and the inline string stops fitting on one line.
  • You want the resource spec checked into git so anyone can re-generate from scratch later. Drop article.yaml next to grit.config.ts.
  • You're generating multiple resources at once and want them all in resources/*.yaml so a script can regenerate the lot.
  • The resource spec is reviewed in a PR before code is written β€” the YAML is the design doc and the source.

The third option β€” interactive

Don't forget about -i when you genuinely don't know the fields yet:

Terminal
$grit generate resource Article -i

The CLI walks you through each field one prompt at a time, and at the end it shows you the equivalent --fields string. Great for pairing or for when you're still designing the model in your head.

Many teams keep both: a resources/ directory full of committed YAML files for the "real" resources, and ad-hoc inline commands for prototypes and experiments. Once a prototype settles, copy the inline command into a YAML and commit it.

Quick check

A teammate asks you to generate an Invoice resource with: number (unique string), amount (money), description (text), due_date (date), and a default status of 'pending'. Which form fits?

Try it

Take this five-field resource and write it both ways in your notes.md, then actually generate it once using YAML:

  • Resource: Project
  • name β€” string, required, unique
  • slug β€” auto-generated from name
  • description β€” text, optional
  • status β€” string with default active
  • archived β€” bool with default false

Save the YAML as project.yaml, run grit generate resource Project --from project.yaml, then grit migrate. Confirm in the admin panel that a new Project starts with status = active and archived = false without you typing them.

What's next

You can now write any field shape Grit supports in either form. One last topic for the chapter: grit sync β€” what to run after you edit a Go struct by hand so the TypeScript types catch up.

Spot a typo? Have an idea?

Help us improve this lesson. One click opens a GitHub issue with the lesson URL pre-filled β€” suggest clearer wording, report a bug, or request more depth. The course keeps improving thanks to learners like you.

Suggest an improvement on GitHub