diff --git a/lib/unitsml/unitsdb/database.rb b/lib/unitsml/unitsdb/database.rb index 7a5be53..e0ff20b 100644 --- a/lib/unitsml/unitsdb/database.rb +++ b/lib/unitsml/unitsdb/database.rb @@ -3,18 +3,29 @@ module Unitsml module Unitsdb class Database < ::Unitsdb::Database - DATABASE = nil + def self.load_opal_payload(payload) + @opal_payload = payload + 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 + # Ensure the UnitsML context is registered when context: is direct. Unitsml::Configuration.context - from_hash(DATABASE, register: context_id) + from_hash(opal_payload, register: context_id) + end + + def self.opal_payload + 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 cfe495f..91e24a9 100644 --- a/spec/unitsml/unitsdb/database_spec.rb +++ b/spec/unitsml/unitsdb/database_spec.rb @@ -21,7 +21,29 @@ end context "when running on opal" do - before { stub_const("RUBY_ENGINE", "opal") } + 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") + 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 expect do @@ -29,6 +51,27 @@ end.to raise_error(Unitsml::Errors::OpalPayloadNotBundledError, /not bundled/) end + + it "loads the bundled Opal payload" do + payload = { "units" => [] } + described_class.load_opal_payload(payload) + allow_from_hash(described_class) + + expect(described_class.from_db("/does/not/matter", + context: :unitsml_ruby)).to eq(:database) + expect_loaded_payload(described_class, payload) + end + + 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