convert pdf to md, add OVERVIEW and docs

This commit is contained in:
2026-08-17 22:30:18 +00:00
parent 95d5787868
commit 4df62d2609
44 changed files with 3307 additions and 1 deletions

View File

@@ -0,0 +1,67 @@
---
type: object
cluster: identity
universe: live
status: verified
entity: app/models/teacher.rb
---
# Teacher
A `User` with `type: "Teacher"` — runs classrooms and gradebooks. Owns no portfolio and
cannot trade.
Verified 2026-08-16 against commit `63732df`.
## Why this shape
Login is by `username` app-wide, but teachers think in email addresses. Rather than
splitting the auth key, `Teacher` **copies email into username** on every validation
(`app/models/teacher.rb:9,17-19`). So a teacher's username is their email, kept in sync
automatically — change the email and the login changes with it. This is the exact inverse
of [student](student.md), whose username is assigned and whose email is usually `nil`.
`attr_accessor :school_id` (`:4`) is a form-only field. It is **not a column and not
persisted** — a teacher reaches a school only through classrooms.
## Shape
- STI subclass of [user](user.md); no table of its own
- `has_many :teacher_classrooms`, `has_many :classrooms, through:` (`:6-7`)
- `before_validation :sync_username_from_email` (`:9`)
- `display_name` prefers `name`, then the email local-part (`:11-13`)
- Join table `teacher_classrooms` — unique on `[teacher_id, classroom_id]`
(`db/schema.rb:368`). No behaviour of its own, so it has no card.
## Connected to
- **owns:** [classroom](../org/classroom.md) (through `teacher_classrooms`)
- **owned-by:** —
- **joins:** `teacher_classrooms`
- **looks-like-but-is-not:** a teacher is not an admin. Admin is a boolean on `users`;
`teacher_or_admin?` (`app/models/user.rb:53-55`) exists precisely because the two are
independent and often both true.
## If you change this
- **Hits:** sign-in for every teacher if you touch `sync_username_from_email` — it
rewrites `username`, the auth key; `Order.for_teacher`
(`app/models/order.rb:40-42`), which scopes orders through
`users.classroom_id`, **not** through `teacher_classrooms`;
`Admin::Teachers::DeactivationsController` / `ReactivationsController`.
- **Does not hit:** [portfolio](../money/portfolio.md). `Portfolio` validates that its
user is a student (`app/models/portfolio.rb:102-104`), so no teacher change can create
or affect one.
## Surfaces
| Surface | Role |
|---|---|
| `Admin::TeachersController` | admin CRUD |
| `Admin::Teachers::DeactivationsController` / `ReactivationsController` | discard / restore |
| `ClassroomsController`, `GradeBooksController` | authorizes as teacher |
## See
- Source: `app/models/teacher.rb`
- Base class: [user](user.md)