Class: Labimotion::OntologyTerms
- Inherits:
-
Object
- Object
- Labimotion::OntologyTerms
- Defined in:
- lib/labimotion/libs/ontology_terms.rb
Overview
Resolve the selectable vocabulary behind an "ontology-select" field.
A template field pins ONE ontology root (its ontology_term); the picker in
chem-generic-ui then offers that root and everything below it. The AI data-fill
needs the same list — otherwise the model invents a plausible-sounding term that
is not in the ontology and the field renders a value the user could never have
chosen themselves.
The whole subtree arrives in ONE request via ?hierarchicalAncestor=, rather
than the dozens of round trips a /children walk costs; the result set is the
same terms, de-duplicated (a term with two parents appears twice in a walk).
What comes back is handed to Labimotion::OntologyStore, which is what actually keeps it — so the picker and the auto-fill read one list instead of resolving the same subtree separately.
Every failure path returns [] — no vocabulary simply means the field falls back to the free-text behaviour it had before, never a failed fill.
Constant Summary collapse
- DEFAULT_BASE_URL =
'https://api.terminology.tib.eu/api/v2'- PAGE_SIZE =
One page, sized past the largest root anyone points a field at (the biggest CHMO branch is ~650 terms).
1000- REQUEST_TIMEOUT =
20- MAX_TERMS_PER_FIELD =
Per-field and per-request budgets. A field aimed at a very general root would otherwise push tens of thousands of labels into the prompt and crowd out the document the model is supposed to be reading. Both limits SKIP a field rather than truncate its list: a partial vocabulary is the worst of both worlds — the missing terms become unproposable AND a correct answer naming one gets thrown away by validation. Sized well past any real root (the largest CHMO branch is ~650 terms).
1500- MAX_TERMS_TOTAL =
3000
Class Method Summary collapse
-
.base_url ⇒ Object
Public because the store records which service a file came from, so a subtree stored against one host can be told apart from another's.
-
.labels_for(ontology_term) ⇒ Array<String>
Selectable labels for one field's
ontology_term, root included, sorted and de-duplicated. -
.parse(ontology_term) ⇒ Object
Split a configured ontology_term into [{ ontology:, iri: }, ...].
-
.subtree(root) ⇒ Object
Every node of one root's subtree, the root included, as the store keeps them: { 'iri', 'label', 'description', 'parent' }.
Class Method Details
.base_url ⇒ Object
Public because the store records which service a file came from, so a subtree stored against one host can be told apart from another's.
83 84 85 86 87 88 89 90 |
# File 'lib/labimotion/libs/ontology_terms.rb', line 83 def base_url cfg = (Rails.configuration.labimotion_ai if defined?(Rails) && Rails.respond_to?(:configuration)) (cfg.is_a?(Hash) && cfg[:ontology_base_url].presence) || ENV['LABIMOTION_ONTOLOGY_BASE_URL'].presence || DEFAULT_BASE_URL rescue StandardError DEFAULT_BASE_URL end |
.labels_for(ontology_term) ⇒ Array<String>
Selectable labels for one field's ontology_term, root included, sorted and
de-duplicated. Accepts the shapes the designer writes: a { 'label', 'value' }
hash, a bare string, or an ARRAY of either (a field may pin several roots).
48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/labimotion/libs/ontology_terms.rb', line 48 def labels_for(ontology_term) roots = parse(ontology_term) return [] if roots.empty? labels = roots.flat_map { |root| Labimotion::OntologyStore.labels(root) } .uniq(&:downcase).sort_by(&:downcase) return labels if labels.size <= MAX_TERMS_PER_FIELD log("subtree of #{roots.map { |r| r[:iri] }.join(', ')} has #{labels.size} terms " \ "(over #{MAX_TERMS_PER_FIELD}); leaving the field unconstrained") [] end |
.parse(ontology_term) ⇒ Object
Split a configured ontology_term into [{ ontology:, iri: }, ...]. Mirrors parseOntologyTerm in chem-generic-ui/src/utils/ontologyApi.js, which is what actually wrote these strings.
77 78 79 |
# File 'lib/labimotion/libs/ontology_terms.rb', line 77 def parse(ontology_term) wrap_terms(ontology_term).filter_map { |term| parse_one(term) } end |
.subtree(root) ⇒ Object
Every node of one root's subtree, the root included, as the store keeps them: { 'iri', 'label', 'description', 'parent' }. The root is selectable in the picker, so it has to be in the list the model is offered too.
Two requests: the root is not in its own descendant query.
66 67 68 69 70 71 72 |
# File 'lib/labimotion/libs/ontology_terms.rb', line 66 def subtree(root) node = root_node(root) return [] if node.nil? nodes = ([node] + descendant_nodes(root)).uniq { |n| n['iri'] } resolve_parents(nodes, node['iri']) end |