From 4d42bab51453f29c9008a0613e2ee86db98ac37f Mon Sep 17 00:00:00 2001 From: suleman-uzair Date: Fri, 24 Apr 2026 22:23:40 +0500 Subject: [PATCH 1/2] fix: add Opal database payload loader --- lib/unitsml/unitsdb/database.rb | 12 ++++++++++-- spec/unitsml/unitsdb/database_spec.rb | 19 ++++++++++++++++++- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/lib/unitsml/unitsdb/database.rb b/lib/unitsml/unitsdb/database.rb index 7a5be53..0aa3abc 100644 --- a/lib/unitsml/unitsdb/database.rb +++ b/lib/unitsml/unitsdb/database.rb @@ -5,15 +5,23 @@ module Unitsdb class Database < ::Unitsdb::Database DATABASE = nil + def self.load_opal_payload(database) + @opal_payload = database + end + def self.from_db(dir_path, context: Unitsml::Configuration.context.id) return super unless RUBY_ENGINE == "opal" context_id = context.to_sym - raise Unitsml::Errors::OpalPayloadNotBundledError unless DATABASE + raise Unitsml::Errors::OpalPayloadNotBundledError unless opal_payload Unitsml::Configuration.context - from_hash(DATABASE, register: context_id) + from_hash(opal_payload, register: context_id) + end + + def self.opal_payload + @opal_payload ||= const_get(:DATABASE, false) if const_defined?(:DATABASE, false) end Configuration.register_model(self, id: :database) diff --git a/spec/unitsml/unitsdb/database_spec.rb b/spec/unitsml/unitsdb/database_spec.rb index cfe495f..605a8c3 100644 --- a/spec/unitsml/unitsdb/database_spec.rb +++ b/spec/unitsml/unitsdb/database_spec.rb @@ -21,7 +21,11 @@ end context "when running on opal" do - before { stub_const("RUBY_ENGINE", "opal") } + before do + stub_const("RUBY_ENGINE", "opal") + described_class.remove_instance_variable(:@opal_payload) if + described_class.instance_variable_defined?(:@opal_payload) + end it "raises a clear error when the bundled payload is missing" do expect do @@ -29,6 +33,19 @@ end.to raise_error(Unitsml::Errors::OpalPayloadNotBundledError, /not bundled/) end + + it "loads the bundled Opal payload" do + described_class.load_opal_payload({ "units" => [] }) + allow(described_class).to receive(:from_hash).and_return(:database) + + result = described_class.from_db("/does/not/matter", context: :unitsml_ruby) + + expect(result).to eq(:database) + expect(described_class).to have_received(:from_hash).with( + { "units" => [] }, + register: :unitsml_ruby, + ) + end end end From 64ec644154cb0759b06f1d1205da47725ad6e9f9 Mon Sep 17 00:00:00 2001 From: suleman-uzair Date: Mon, 27 Apr 2026 13:09:47 +0500 Subject: [PATCH 2/2] fix: clean up Opal database payload loader --- lib/unitsml/unitsdb/database.rb | 13 +++++--- spec/unitsml/unitsdb/database_spec.rb | 46 +++++++++++++++++++++------ 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/lib/unitsml/unitsdb/database.rb b/lib/unitsml/unitsdb/database.rb index 0aa3abc..e0ff20b 100644 --- a/lib/unitsml/unitsdb/database.rb +++ b/lib/unitsml/unitsdb/database.rb @@ -3,10 +3,8 @@ module Unitsml module Unitsdb class Database < ::Unitsdb::Database - DATABASE = nil - - def self.load_opal_payload(database) - @opal_payload = database + def self.load_opal_payload(payload) + @opal_payload = payload end def self.from_db(dir_path, context: Unitsml::Configuration.context.id) @@ -15,14 +13,19 @@ def self.from_db(dir_path, context: Unitsml::Configuration.context.id) context_id = context.to_sym raise Unitsml::Errors::OpalPayloadNotBundledError unless opal_payload + # Ensure the UnitsML context is registered when context: is direct. Unitsml::Configuration.context from_hash(opal_payload, register: context_id) end def self.opal_payload - @opal_payload ||= const_get(:DATABASE, false) if const_defined?(:DATABASE, false) + return @opal_payload if instance_variable_defined?(:@opal_payload) + return unless const_defined?(:DATABASE, false) + + @opal_payload = const_get(:DATABASE, false) end + private_class_method :opal_payload Configuration.register_model(self, id: :database) end diff --git a/spec/unitsml/unitsdb/database_spec.rb b/spec/unitsml/unitsdb/database_spec.rb index 605a8c3..91e24a9 100644 --- a/spec/unitsml/unitsdb/database_spec.rb +++ b/spec/unitsml/unitsdb/database_spec.rb @@ -21,10 +21,28 @@ end context "when running on opal" do + def clear_opal_payload + return unless described_class.instance_variable_defined?(:@opal_payload) + + described_class.remove_instance_variable(:@opal_payload) + end + before do stub_const("RUBY_ENGINE", "opal") - described_class.remove_instance_variable(:@opal_payload) if - described_class.instance_variable_defined?(:@opal_payload) + clear_opal_payload + end + + after do + clear_opal_payload + end + + def allow_from_hash(database_class) + allow(database_class).to receive(:from_hash).and_return(:database) + end + + def expect_loaded_payload(database_class, payload) + expect(database_class).to have_received(:from_hash) + .with(payload, register: :unitsml_ruby) end it "raises a clear error when the bundled payload is missing" do @@ -35,16 +53,24 @@ end it "loads the bundled Opal payload" do - described_class.load_opal_payload({ "units" => [] }) - allow(described_class).to receive(:from_hash).and_return(:database) + payload = { "units" => [] } + described_class.load_opal_payload(payload) + allow_from_hash(described_class) - result = described_class.from_db("/does/not/matter", context: :unitsml_ruby) + expect(described_class.from_db("/does/not/matter", + context: :unitsml_ruby)).to eq(:database) + expect_loaded_payload(described_class, payload) + end - expect(result).to eq(:database) - expect(described_class).to have_received(:from_hash).with( - { "units" => [] }, - register: :unitsml_ruby, - ) + it "falls back to a legacy DATABASE constant" do + payload = { "units" => [:from_const] } + subclass = Class.new(described_class) + subclass.const_set(:DATABASE, payload) + allow_from_hash(subclass) + + expect(subclass.from_db("/does/not/matter", + context: :unitsml_ruby)).to eq(:database) + expect_loaded_payload(subclass, payload) end end end