Files
project-work/worker-toolkit-stocks-in-the-future/repo/docs/map/objects/announcement.md

2.9 KiB

type, cluster, universe, status, entity
type cluster universe status entity
object content live verified app/models/announcement.rb

Announcement

A site-wide notice written by an admin, with rich text. One may be "featured" at a time.

Verified 2026-08-16 against commit 63732df.

Why this shape

Content is Action Text, not a column. has_rich_text :content (app/models/announcement.rb:4) stores the body in action_text_rich_texts (db/schema.rb:17-25) as a polymorphic association. So content is a record, not a string: it is not selectable, not sortable, and not searchable with a plain WHERE on this table.

The body column is a ghost. announcements.body exists (db/schema.rb:56) but is never read, written, validated, or permitted — announcement_params allows only title, content, featured (app/controllers/admin/announcements_controller.rb:79-81). It is the pre-Action-Text column, left behind. Do not write to it expecting it to appear.

"Only one featured" is a callback, not a constraint. before_save :unfeature_other_announcements demotes the current holder when a new one is featured (:9,27-32), and Announcement.current simply does find_by(featured: true) (:13-15). There is no unique index — concurrent writes can leave two featured rows, and current will then return an arbitrary one. The demotion also runs update (not update!) on the old record (:31), so a failure there is silent.

Shape

  • Table announcements, db/schema.rb:55-62 — title, featured, body (ghost), timestamps; index on created_at DESC (db/schema.rb:61)
  • validates :title, presence: true, length: { maximum: 255 } (:6)
  • validates :content, presence: true (:7) — validating the Action Text association
  • scope :latest — newest first (:11)
  • self.current — the featured one, or nil (:13-15)
  • excerpt(limit: 150) — plain-text truncation (:17-19)
  • published_at is an alias for created_at (:21-23); there is no publish workflow and no draft state

Connected to

  • owns: its Action Text record
  • owned-by: —
  • joins: —
  • looks-like-but-is-not: published_at is not a publication timestamp — an announcement is live from the moment it is created. And content is not a column.

If you change this

  • Hits: Admin::AnnouncementsController (full CRUD) and AnnouncementsController#show; the home page and any layout partial calling Announcement.current; Action Text and Active Storage if you touch content, since embedded attachments live there.
  • Does not hit: anything financial. Announcements touch no portfolio, order, or gradebook — this is the one object in the map with no path to money.

Surfaces

Surface Role
Admin::AnnouncementsController admin CRUD
AnnouncementsController#show everyone reads
HomeController#index reads the featured one

See

  • Source: app/models/announcement.rb, db/schema.rb:55-62