Class: Studio::Enumeral

Inherits:
ApplicationRecord
  • Object
show all
Defined in:
app/models/studio/enumeral.rb

Overview

A shared, DB-backed enumeration table for the whole ecosystem. Every “list of fixed, labeled, colored values” — Pokémon types (its first use), and later statuses, tiers, roles, … — is just rows in ONE studio_enumerals table, grouped by ‘category`. Each row is identity + presentation: a stable machine `key` (“fire”), a human `label` (“Fire”), a `color` hex (“#EE8130”), and a `position` for ordering within its category. `metadata` (jsonb) carries any category-specific extras off the columns.

Shipped by the gem like Studio::Link / Studio::EmailDelivery: the model lives here, the table lives in each consumer app (copy the reference migration into db/migrate). No behavior is attached — it is pure reference data the apps read, so a consumer adopts a new category by seeding rows, no code change.

Constant Summary collapse

HEX =
/\A#(?:\h{3}|\h{6})\z/

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.available?Boolean

True only when the table is actually migrated in this app’s DB, so a consumer that hasn’t installed the migration degrades to “empty” instead of crashing (mirrors Studio::EmailDelivery.available?).

Returns:

  • (Boolean)


35
36
37
38
39
# File 'app/models/studio/enumeral.rb', line 35

def available?
  connection.data_source_exists?(table_name)
rescue ActiveRecord::ActiveRecordError, NoMethodError
  false
end

.catalog(category) ⇒ Object

The ordered list of a category’s enumerals — the relation a view iterates (one query). Returns an empty relation when the table isn’t installed yet, so callers can ‘.each` safely pre-migration.



44
45
46
47
48
# File 'app/models/studio/enumeral.rb', line 44

def catalog(category)
  return none unless available?

  in_category(category).ordered
end

.color_for(category, key, fallback: nil) ⇒ Object

Just the color for a single (category, key), with an optional fallback when the key is unknown or the table isn’t installed yet.



66
67
68
69
70
# File 'app/models/studio/enumeral.rb', line 66

def color_for(category, key, fallback: nil)
  return fallback unless available?

  in_category(category).where(key: key.to_s).limit(1).pick(:color) || fallback
end

.color_map(category) ⇒ Object

{ key => color } for a category in ONE query — the shape a view wants: build it once, then look up each cell with no extra queries (avoids an N+1 when rendering many rows, e.g. the /pokemon type badges).



60
61
62
# File 'app/models/studio/enumeral.rb', line 60

def color_map(category)
  catalog(category).pluck(:key, :color).to_h
end

.emoji_map(category) ⇒ Object

{ key => emoji } for a category in ONE query — the metadata sibling of color_map, for decorative glyphs kept in ‘metadata` rather than a column.



74
75
76
# File 'app/models/studio/enumeral.rb', line 74

def emoji_map(category)
  catalog(category).pluck(:key, :metadata).to_h { |key, meta| [key, meta && meta["emoji"]] }
end

.lookup(category, key) ⇒ Object

The single enumeral for (category, key), or nil.



51
52
53
54
55
# File 'app/models/studio/enumeral.rb', line 51

def lookup(category, key)
  return nil unless available?

  in_category(category).find_by(key: key.to_s)
end

Instance Method Details

#emojiObject

A decorative glyph for the value, kept in ‘metadata` (not a column) since it’s a presentation extra — e.g. a Pokémon type’s emoji. Nil when unset.



81
82
83
# File 'app/models/studio/enumeral.rb', line 81

def emoji
   && ["emoji"]
end