Skip to main content

Runtime CRUD

This page defines the recommended CRUD contract for application code.

Core rule

Use one of these two creation paths:
Interpretation:
  • new User() means a transient in-memory model instance
  • save() persists the current instance state
  • User.create(...) persists immediately and returns the created model
Do not treat User.create(...) and save() as the same step.

Create

Use new User() when

  • you want to build the model gradually
  • you want to call fill(...) before persistence
  • the code reads better as an explicit instance lifecycle

Use User.create(...) when

  • the payload is already validated
  • you want a one-shot insert
  • you want a concise service method
Do not immediately call save() after User.create(...) unless you changed the model again.

Use User.createMany(...) when

  • you already have multiple validated payloads
  • the service owns an explicit bulk insert operation
  • you want hydrated created models back in input order

Read

Use primary-key and safe-finder reads before mutation:
Use new User().all() when you explicitly want the instance collection-read path:

Update

This is the preferred public runtime path:
Why this is the preferred path:
  • the record is loaded first
  • the code reads like a model lifecycle
  • it works well with dirty tracking, hooks, and service-level decisions

Partial update with patch()

Use patch() when the instance already exists and you are intentionally updating a subset of fields.
Use patch() when:
  • the row is already loaded
  • the service is applying a narrow change
  • you do not want the full update(...); save() flow

Bulk update and patch

Use bulk helpers only when the service already owns an explicit list of ids or patch rows.

Delete

This is the cleanest public path because:
  • the code reads as “load then delete”
  • soft-delete behavior stays attached to the model runtime
  • service logic can branch on “record exists” before deletion

Restore

Restore applies only when the model supports soft deletes.
Use restore when:
  • the model includes soft-delete behavior
  • the service is intentionally exposing record recovery
  • the controller is generated with or supports a restore route

Bulk delete and restore

Explicit by-id helpers

Use these helpers only when you intentionally want a direct by-id service path:
Use them when:
  • the service already owns the target primary key
  • you do not want the full loaded-instance lifecycle
  • the code is intentionally thin and explicit
Do not use these helpers as the first-choice teaching path for most application logic. Bulk helpers and by-id helpers are both explicit service paths. Prefer loaded-instance flows when the service already reads the record first.
Do not treat these as the primary public teaching path:
  • new User().create(...)
  • new User().update(id, data)
  • new User().delete(id)
They may exist for compatibility or lower-level flows, but they are not the preferred runtime contract for consumer-facing code.