Class: Fosm::Current

Inherits:
ActiveSupport::CurrentAttributes
  • Object
show all
Defined in:
lib/fosm/current.rb

Overview

Per-request cache for FOSM RBAC role lookups.

Loads ALL role assignments for the current actor in ONE SQL query on first access, then serves subsequent checks from an in-memory hash (O(1) lookup). Resets automatically at the end of each request via ActiveSupport::CurrentAttributes.

Cache structure:

{ "User:42" => { "Fosm::Invoice" => { nil => [:owner], "5" => [:approver] } } }
          ↑ actor key           ↑ type-level         ↑ record-level

Class Method Summary collapse

Class Method Details

.invalidate_for(actor) ⇒ Object

Invalidate the cached roles for a specific actor (e.g., after granting a new role).



36
37
38
# File 'lib/fosm/current.rb', line 36

def self.invalidate_for(actor)
  _access_cache&.delete(cache_key(actor))
end

.roles_for(actor, model_class, record_id = nil) ⇒ Array<Symbol>

Retrieve cached roles for a given actor + model class + optional record ID. Loads from DB on first call for this actor (one query per actor per request).

Parameters:

  • actor (Object)

    an ActiveRecord user object with .class.name and .id

  • model_class (Class)

    the FOSM model class (e.g. Fosm::Invoice)

  • record_id (Integer, String, nil) (defaults to: nil)

    specific record ID, or nil for type-level only

Returns:

  • (Array<Symbol>)

    list of role names this actor has on the resource



21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/fosm/current.rb', line 21

def self.roles_for(actor, model_class, record_id = nil)
  actor_key = cache_key(actor)

  unless _access_cache&.key?(actor_key)
    self._access_cache ||= {}
    self._access_cache[actor_key] = load_for_actor(actor)
  end

  actor_data  = _access_cache[actor_key]
  type_roles   = actor_data.dig(model_class.name, nil) || []
  record_roles = record_id ? (actor_data.dig(model_class.name, record_id.to_s) || []) : []
  (type_roles + record_roles).uniq
end