Class: Unitsdb::Config

Inherits:
Object
  • Object
show all
Defined in:
lib/unitsdb/config.rb

Constant Summary collapse

CONTEXT_ID =
:unitsdb_v2

Class Method Summary collapse

Class Method Details

.build_registryObject



148
149
150
151
152
153
# File 'lib/unitsdb/config.rb', line 148

def build_registry
  Unitsdb.eager_load_models!
  registry = Lutaml::Model::TypeRegistry.new
  registered_models.each { |model_id, klass| registry.register(model_id, klass) }
  registry
end

.capture_stateObject


Test support — snapshot/restore/isolate



159
160
161
162
163
164
165
# File 'lib/unitsdb/config.rb', line 159

def capture_state
  {
    registered_models: registered_models.dup,
    explicit_registers: explicit_registers.dup,
    context_id: @context_id,
  }
end

.context(id = context_id()) ⇒ Object

Return the context for id, creating it via populate_context when missing. Non-destructive: existing contexts (whether Config-created or externally-managed) are returned as-is. Use populate_context directly to force-rebuild.



94
95
96
# File 'lib/unitsdb/config.rb', line 94

def context(id = context_id())
  find_context(id) || populate_context(id: id)
end

.context_idObject

The currently-active default context id. Config-populated contexts are created on demand under this id.



10
11
12
# File 'lib/unitsdb/config.rb', line 10

def context_id
  @context_id ||= CONTEXT_ID
end

.ensure_default_context!Object

Convenience: ensure the default context exists. Idempotent. Used as the single bootstrap site for Unitsdb.database and Database.from_db.



114
115
116
117
118
# File 'lib/unitsdb/config.rb', line 114

def ensure_default_context!
  return if find_context(context_id)

  populate_context(id: context_id)
end

.explicit_registersObject



74
75
76
# File 'lib/unitsdb/config.rb', line 74

def explicit_registers
  @explicit_registers ||= {}
end

.find_context(id) ⇒ Object


Context lifecycle



82
83
84
# File 'lib/unitsdb/config.rb', line 82

def find_context(id)
  Lutaml::Model::GlobalContext.context(id.to_sym)
end

.model_for(model_name) ⇒ Object

Look up a registered model by id. Kept as a stable public API for downstream gems (e.g. unitsml) that previously used the Configuration module.



40
41
42
# File 'lib/unitsdb/config.rb', line 40

def model_for(model_name)
  registered_models[model_name.to_sym]
end

.models=(user_models) ⇒ Object

Bulk-register models from a hash. Reads back through register_model so there is a single source of truth.



31
32
33
34
35
# File 'lib/unitsdb/config.rb', line 31

def models=(user_models)
  user_models.each do |id, klass|
    register_model(klass, id: id.to_sym)
  end
end

.populate_context(id: context_id, fallback_to: [:default], substitutions: []) ⇒ Object

Force-create a context under id, replacing any prior context (owned or external).



100
101
102
103
104
105
106
107
108
109
# File 'lib/unitsdb/config.rb', line 100

def populate_context(id: context_id, fallback_to: [:default],
                     substitutions: [])
  Lutaml::Model::GlobalContext.unregister_context(id) if find_context(id)

  opts = { registry: build_registry, fallback_to: fallback_to, id: id }
  Lutaml::Model::GlobalContext.create_context(
    substitutions: resolve_substitutions(substitutions, **opts),
    **opts,
  )
end

.populate_register(id: context_id, fallback_to: [:default], substitutions: []) ⇒ Object

Create a Lutaml::Model::Register for id, enabling from_hash(register: id) deserialization. Power-user API — most callers want populate_context only.



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/unitsdb/config.rb', line 57

def populate_register(id: context_id, fallback_to: [:default], substitutions: [])
  register_id = id.to_sym
  context(register_id)

  model_register = Lutaml::Model::Register.new(register_id, fallback: fallback_to)
  resolve_substitutions(
    substitutions,
    registry: build_registry,
    fallback_to: fallback_to,
    id: "#{register_id}_register",
  ).each do |substitution|
    model_register.register_global_type_substitution(**substitution)
  end

  explicit_registers[register_id] = Lutaml::Model::GlobalRegister.register(model_register)
end

.register_id_for(context_id = context_id()) ⇒ Object

Look up the Lutaml::Model::Register id (or nil) that was explicitly created for context_id via populate_register.



50
51
52
# File 'lib/unitsdb/config.rb', line 50

def register_id_for(context_id = context_id())
  explicit_registers[context_id.to_sym]
end

.register_model(klass, id:) ⇒ Object

Register a model class under id. Single registration API; models= is a thin enumerator over this.



20
21
22
23
# File 'lib/unitsdb/config.rb', line 20

def register_model(klass, id:)
  registered_models[id.to_sym] = klass
  klass
end

.registered_modelsObject



25
26
27
# File 'lib/unitsdb/config.rb', line 25

def registered_models
  @registered_models ||= {}
end

.resolve_substitution_type(value, resolution_context) ⇒ Object



142
143
144
145
146
# File 'lib/unitsdb/config.rb', line 142

def resolve_substitution_type(value, resolution_context)
  return value if value.is_a?(Class)

  Lutaml::Model::TypeResolver.resolve(value, resolution_context)
end

.resolve_substitutions(substitutions, registry:, fallback_to:, id:) ⇒ Object


Substitution resolution



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/unitsdb/config.rb', line 124

def resolve_substitutions(substitutions, registry:, fallback_to:, id:)
  resolution_context = Lutaml::Model::TypeContext.derived(
    id: "#{id}_substitution_resolution",
    registry: registry,
    fallback_to: fallback_to,
  )

  Array(substitutions).map do |substitution|
    from_key = substitution[:from_type] || substitution[:from]
    to_key = substitution[:to_type] || substitution[:to]

    {
      from_type: resolve_substitution_type(from_key, resolution_context),
      to_type: resolve_substitution_type(to_key, resolution_context),
    }
  end
end

.resolve_type(type_name, context: context_id) ⇒ Object



86
87
88
# File 'lib/unitsdb/config.rb', line 86

def resolve_type(type_name, context: context_id)
  Lutaml::Model::GlobalContext.resolve_type(type_name, context.to_sym)
end

.restore_state(snapshot) ⇒ Object



167
168
169
170
171
# File 'lib/unitsdb/config.rb', line 167

def restore_state(snapshot)
  @registered_models = snapshot[:registered_models]
  @explicit_registers = snapshot[:explicit_registers]
  @context_id = snapshot[:context_id]
end

.with_isolated_configObject

Run a block against a fresh Lutaml global context, then restore Config state so subsequent specs see bundled defaults.



175
176
177
178
179
180
181
182
# File 'lib/unitsdb/config.rb', line 175

def with_isolated_config
  snapshot = capture_state
  Lutaml::Model::GlobalContext.reset!
  yield
ensure
  restore_state(snapshot) if snapshot
  Lutaml::Model::GlobalContext.reset!
end