Module: OpenLoam::Configs

Defined in:
lib/open_loam/configs.rb

Overview

The one way to read and write per-tenant settings.

OpenLoam::Configs.get("rental.late_fee_per_day")          # resolved for the current tenant
OpenLoam::Configs.set("rental.late_fee_per_day", 45)      # this tenant's override
OpenLoam::Configs.set("rental.currency", "PLN", scope: :global)
OpenLoam::Configs.reset("rental.late_fee_per_day")        # drop the override → fall back

Resolution order, most specific first:

1. the current tenant's OVERRIDE row (tenant_id = current tenant)
2. the GLOBAL row (tenant_id NULL)
3. the declared default in OpenLoam.config_defaults[key]
4. the `default:` argument (nil)

Reads are memoized per request in OpenLoam::Current.config_cache, keyed by [key, tenant_id], and the whole cache is dropped on any write. That is the deliberately-simple prototype cache; a Rails.cache-backed layer shared across requests is the scaling path, and it would slot in behind this same API.

Class Method Summary collapse

Class Method Details

.defined_keys ⇒ Object

Every key an admin might configure for the current tenant: declared defaults, plus any global or current-tenant rows already written. Sorted and de-duplicated, for the settings screen.



68
69
70
71
# File 'lib/open_loam/configs.rb', line 68

def defined_keys
  rows = OpenLoam::Config.where(tenant_id: [nil, OpenLoam.tenant&.id]).distinct.pluck(:key)
  (OpenLoam.config_defaults.keys + rows).map(&:to_s).uniq.sort
end

.get(key, default: nil) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/open_loam/configs.rb', line 21

def get(key, default: nil)
  key = key.to_s
  store = cache
  cache_key = [key, current_tenant_id]

  return store[cache_key] if store.key?(cache_key)

  # Only a value that actually RESOLVED (a row or a declared default) is
  # cached — never the caller's `default:` fallback. The cache key omits
  # `default:`, so caching it would make a later get with a different
  # default wrongly return the first one when nothing is configured.
  found, value = resolve(key)
  return default unless found

  store[cache_key] = value
end

.overridden?(key) ⇒ Boolean

Whether the current tenant has an override for this key (vs. inheriting the global/declared value). Drives the admin "overridden?" column.

Returns:

  • (Boolean)


61
62
63
# File 'lib/open_loam/configs.rb', line 61

def overridden?(key)
  row_for(key.to_s, :tenant).exists?
end

.reset(key) ⇒ Object

Drop the current tenant's override for a key so it falls back to the global row / declared default. Requires a tenant in context. No-op if there was no override. Returns true.



53
54
55
56
57
# File 'lib/open_loam/configs.rb', line 53

def reset(key)
  row_for(key.to_s, :tenant).delete_all
  clear_cache
  true
end

.set(key, value, scope: :tenant) ⇒ Object

Write a setting. scope: :tenant writes the current tenant's override and requires a tenant in context (a missing one raises, like every OpenLoam write); scope: :global writes the app-wide row (tenant_id NULL). Upsert.



41
42
43
44
45
46
47
48
# File 'lib/open_loam/configs.rb', line 41

def set(key, value, scope: :tenant)
  key = key.to_s
  record = row_for(key, scope).first_or_initialize
  record.value_json = value
  record.save!
  clear_cache
  value
end