--- 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)