unitsml 0.6.5 → 0.6.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "unitsdb"
4
+
5
+ module Unitsml
6
+ module Opal
7
+ class PayloadGenerator
8
+ DEFAULT_OUTPUT_PATH =
9
+ File.expand_path("database_payload.rb", __dir__).freeze
10
+
11
+ RECEIVER = "Unitsml::Unitsdb::Database"
12
+ METHOD = "load_opal_payload"
13
+
14
+ # Maps a scalar value's class to the serializer that emits its
15
+ # Ruby source representation. Kept as a constant so adding a new
16
+ # scalar type is a one-line change (OCP).
17
+ SCALAR_SERIALIZERS = {
18
+ String => :inspect.to_proc,
19
+ Symbol => ->(v) { ":#{v}" },
20
+ Integer => :to_s.to_proc,
21
+ Float => :to_s.to_proc,
22
+ }.freeze
23
+
24
+ def initialize(unitsdb_data_dir: default_data_dir)
25
+ @unitsdb_data_dir = unitsdb_data_dir
26
+ end
27
+
28
+ def call
29
+ "#{header}#{body}"
30
+ end
31
+
32
+ def write_to(path = DEFAULT_OUTPUT_PATH)
33
+ File.write(path, call)
34
+ path
35
+ end
36
+
37
+ private
38
+
39
+ attr_reader :unitsdb_data_dir
40
+
41
+ def header
42
+ <<~RUBY
43
+ # frozen_string_literal: true
44
+
45
+ # AUTO-GENERATED by `bundle exec rake unitsml:generate_opal_payload`.
46
+ # Do not edit by hand. Edit the YAML in unitsdb-ruby/data/ and
47
+ # regenerate. This file is loaded by lib/unitsml/opal.rb under Opal
48
+ # to satisfy Unitsml::Unitsdb::Database.from_db without a filesystem.
49
+ RUBY
50
+ end
51
+
52
+ def body
53
+ "#{RECEIVER}.#{METHOD}(#{serialize(database_hash)}.freeze)\n"
54
+ end
55
+
56
+ def database_hash
57
+ ::Unitsdb::Database.from_db(unitsdb_data_dir).to_hash
58
+ end
59
+
60
+ # Custom serializer rather than Hash#inspect so the output is
61
+ # byte-identical across Ruby versions (3.3 vs 3.4 changed Hash#inspect
62
+ # to add spaces around "=>"). String#inspect is itself stable for
63
+ # UTF-8 clean data.
64
+ def serialize(value)
65
+ case value
66
+ when Hash then serialize_hash(value)
67
+ when Array then serialize_array(value)
68
+ when true then "true"
69
+ when false then "false"
70
+ when nil then "nil"
71
+ else serialize_scalar(value)
72
+ end
73
+ end
74
+
75
+ def serialize_hash(value)
76
+ "{#{value.map { |k, v| "#{serialize(k)}=>#{serialize(v)}" }.join(',')}}"
77
+ end
78
+
79
+ def serialize_array(value)
80
+ "[#{value.map { |v| serialize(v) }.join(',')}]"
81
+ end
82
+
83
+ def serialize_scalar(value)
84
+ serializer = SCALAR_SERIALIZERS[value.class]
85
+ return serializer.call(value) if serializer
86
+
87
+ raise Unitsml::Errors::UnsupportedPayloadTypeError, value.class
88
+ end
89
+
90
+ def default_data_dir
91
+ ::Unitsdb.data_dir
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Opal entry point for unitsml.
4
+ #
5
+ # Under MRI, lib/unitsml.rb uses autoload for lazy loading. Under Opal,
6
+ # autoload does not lazy-execute, so this boot file eager-requires every
7
+ # entry point. Consumers (e.g. plurimath-js) add `-r unitsml/opal` to
8
+ # their Opal compile command.
9
+ #
10
+ # Load order rationale:
11
+ # 1. Upstream boot files first — unitsml depends on lutaml-model,
12
+ # unitsdb, mml (and transitively omml via plurimath-js consumers).
13
+ # 2. unitsml.rb next — sets up top-level autoloads and Configuration.
14
+ # 3. Errors before everything else (low-level, no deps).
15
+ # 4. The Opal payload — defines Unitsml::Unitsdb::Database::DATABASE
16
+ # so Unitsml::Unitsdb::Database.from_db can satisfy without a
17
+ # filesystem under Opal.
18
+ # 5. Unitsdb sub-files — define classes that subclass ::Unitsdb::*
19
+ # and call Configuration.register_model side-effects.
20
+ # 6. Model tree — declares the Unitsml XML model classes. Each parent
21
+ # module (Prefixes, Quantities, DimensionQuantities, Units) is
22
+ # required first to set up its own autoloads, then its leaves.
23
+ # 7. Parser/Transform/Prefix/Unit/Dimension etc. — top-level domain
24
+ # classes that reference Model and Unitsdb.
25
+
26
+ require "lutaml/model"
27
+ require "unitsdb/opal"
28
+ require "mml/opal"
29
+ require "omml/opal"
30
+
31
+ require "unitsml"
32
+
33
+ require "unitsml/version"
34
+ require "unitsml/errors"
35
+ require "unitsml/errors/base_error"
36
+ require "unitsml/errors/invalid_model_error"
37
+ require "unitsml/errors/opal_payload_not_bundled_error"
38
+ require "unitsml/errors/plurimath_load_error"
39
+ require "unitsml/errors/unsupported_payload_type_error"
40
+
41
+ require "unitsml/opal/database_payload"
42
+
43
+ require "unitsml/configuration"
44
+ require "unitsml/namespace"
45
+
46
+ require "unitsml/unitsdb"
47
+ require "unitsml/unitsdb/database"
48
+ require "unitsml/unitsdb/dimension_details"
49
+ require "unitsml/unitsdb/finders"
50
+ require "unitsml/unitsdb/prefix_reference"
51
+ require "unitsml/unitsdb/dimension"
52
+ require "unitsml/unitsdb/dimensions"
53
+ require "unitsml/unitsdb/unit"
54
+ require "unitsml/unitsdb/units"
55
+ require "unitsml/unitsdb/prefixes"
56
+ require "unitsml/unitsdb/quantities"
57
+
58
+ require "unitsml/model"
59
+ require "unitsml/model/dimension"
60
+ require "unitsml/model/dimension_quantities"
61
+ require "unitsml/model/dimension_quantities/amount_of_substance"
62
+ require "unitsml/model/dimension_quantities/electric_current"
63
+ require "unitsml/model/dimension_quantities/length"
64
+ require "unitsml/model/dimension_quantities/luminous_intensity"
65
+ require "unitsml/model/dimension_quantities/mass"
66
+ require "unitsml/model/dimension_quantities/plane_angle"
67
+ require "unitsml/model/dimension_quantities/quantity"
68
+ require "unitsml/model/dimension_quantities/thermodynamic_temperature"
69
+ require "unitsml/model/dimension_quantities/time"
70
+ require "unitsml/model/prefix"
71
+ require "unitsml/model/prefixes"
72
+ require "unitsml/model/prefixes/name"
73
+ require "unitsml/model/prefixes/symbol"
74
+ require "unitsml/model/quantities"
75
+ require "unitsml/model/quantities/name"
76
+ require "unitsml/model/quantity"
77
+ require "unitsml/model/unit"
78
+ require "unitsml/model/units"
79
+ require "unitsml/model/units/enumerated_root_unit"
80
+ require "unitsml/model/units/name"
81
+ require "unitsml/model/units/root_units"
82
+ require "unitsml/model/units/symbol"
83
+ require "unitsml/model/units/system"
84
+
85
+ require "unitsml/dimension"
86
+ require "unitsml/extender"
87
+ require "unitsml/fenced"
88
+ require "unitsml/fenced_numeric"
89
+ require "unitsml/formula"
90
+ require "unitsml/intermediate_exp_rules"
91
+ require "unitsml/mathml_helper"
92
+ require "unitsml/number"
93
+ require "unitsml/parse"
94
+ require "unitsml/parser"
95
+ require "unitsml/prefix"
96
+ require "unitsml/prefix_adapter"
97
+ require "unitsml/sqrt"
98
+ require "unitsml/transform"
99
+ require "unitsml/unit"
100
+ require "unitsml/utility"
101
+ require "unitsml/xml"
102
+ require "unitsml/xml/formatter"
@@ -32,7 +32,7 @@ module Unitsml
32
32
  array.each do |object|
33
33
  if object.is_a?(Sqrt)
34
34
  object = object.value
35
- if object.respond_to?(:power_numerator)
35
+ if object.is_a?(Unit)
36
36
  object.power_numerator = Number.new("0.5")
37
37
  else
38
38
  update_units_exponents([object], inverse, true)
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unitsml
4
+ # Value object that adapts the various "prefix-shaped" inputs flowing
5
+ # through Unitsml::Utility to a single, type-explicit interface.
6
+ #
7
+ # Dispatch is by `is_a?` / `case/when`, so type errors surface at the
8
+ # boundary instead of silently falling through.
9
+ #
10
+ # Recognized inputs:
11
+ # - `Unitsml::Prefix` — already adapted, has full API
12
+ # - `::Unitsdb::Prefix` — upstream record, has `symbols`
13
+ # - `Unitsml::Unitsdb::PrefixReference` — UnitsML reference, has `symbolid`
14
+ # - `::Unitsdb::PrefixReference` — bare id/type, needs lookup
15
+ # - `String` — prefix name, looked up
16
+ # - `nil` — null adapter
17
+ class PrefixAdapter
18
+ attr_reader :raw
19
+
20
+ def initialize(raw)
21
+ @raw = raw
22
+ end
23
+
24
+ def self.wrap(prefix)
25
+ return new(nil) if prefix.nil?
26
+ return prefix if prefix.is_a?(PrefixAdapter)
27
+
28
+ case prefix
29
+ when Unitsml::Prefix, ::Unitsdb::Prefix,
30
+ Unitsml::Unitsdb::PrefixReference
31
+ new(prefix)
32
+ when ::Unitsdb::PrefixReference
33
+ from_id(prefix.id)
34
+ when String
35
+ from_name(prefix)
36
+ else
37
+ new(nil)
38
+ end
39
+ end
40
+
41
+ def self.from_name(name)
42
+ return new(nil) unless Unitsml::Unitsdb.prefixes_array.include?(name)
43
+
44
+ new(Unitsml::Prefix.new(name))
45
+ end
46
+
47
+ def self.from_id(id)
48
+ new(Unitsml::Unitsdb.prefixes.find_by_id(id))
49
+ end
50
+ private_class_method :from_id
51
+
52
+ def null?
53
+ @raw.nil?
54
+ end
55
+
56
+ def base
57
+ @raw&.base
58
+ end
59
+
60
+ def power
61
+ @raw&.power
62
+ end
63
+
64
+ def symbolid
65
+ case @raw
66
+ when Unitsml::Prefix, Unitsml::Unitsdb::PrefixReference
67
+ @raw.symbolid
68
+ when ::Unitsdb::Prefix
69
+ @raw.symbols.first&.ascii
70
+ end
71
+ end
72
+
73
+ def prefix_name
74
+ case @raw
75
+ when Unitsml::Prefix
76
+ @raw.prefix_name
77
+ when ::Unitsdb::Prefix, Unitsml::Unitsdb::PrefixReference
78
+ symbolid
79
+ end
80
+ end
81
+ end
82
+ end
@@ -3,18 +3,31 @@
3
3
  module Unitsml
4
4
  module Unitsdb
5
5
  class Database < ::Unitsdb::Database
6
- DATABASE = nil
7
-
8
6
  def self.from_db(dir_path, context: Unitsml::Configuration.context.id)
9
7
  return super unless RUBY_ENGINE == "opal"
10
8
 
11
9
  context_id = context.to_sym
12
- raise Unitsml::Errors::OpalPayloadNotBundledError unless DATABASE
10
+ raise Unitsml::Errors::OpalPayloadNotBundledError unless opal_payload
13
11
 
14
12
  Unitsml::Configuration.context
15
13
 
16
- from_hash(DATABASE, register: context_id)
14
+ from_hash(opal_payload, register: context_id)
15
+ end
16
+
17
+ def self.load_opal_payload(payload)
18
+ @opal_payload = payload
19
+ end
20
+
21
+ def self.reset_opal_payload
22
+ return unless instance_variable_defined?(:@opal_payload)
23
+
24
+ remove_instance_variable(:@opal_payload)
25
+ end
26
+
27
+ def self.opal_payload
28
+ @opal_payload
17
29
  end
30
+ private_class_method :opal_payload
18
31
 
19
32
  Configuration.register_model(self, id: :database)
20
33
  end
@@ -3,48 +3,38 @@
3
3
  module Unitsml
4
4
  module Unitsdb
5
5
  class Dimension < ::Unitsdb::Dimension
6
+ QUANTITY_KEYS = %i[
7
+ length
8
+ mass
9
+ time
10
+ thermodynamic_temperature
11
+ amount_of_substance
12
+ luminous_intensity
13
+ plane_angle
14
+ electric_current
15
+ ].freeze
16
+
6
17
  attr_reader :parsables,
7
18
  :parsable,
8
19
  :processed_keys,
9
20
  :vector
10
21
 
11
22
  def initialize(attrs)
23
+ @quantities = {}
12
24
  @parsables = {}
13
25
  @processed_keys = []
14
26
  @parsable = false
15
27
  super
16
28
  end
17
29
 
18
- def length=(value)
19
- quantities_common_code(:length, value)
20
- end
21
-
22
- def mass=(value)
23
- quantities_common_code(:mass, value)
24
- end
25
-
26
- def time=(value)
27
- quantities_common_code(:time, value)
28
- end
29
-
30
- def thermodynamic_temperature=(value)
31
- quantities_common_code(:thermodynamic_temperature, value)
32
- end
33
-
34
- def amount_of_substance=(value)
35
- quantities_common_code(:amount_of_substance, value)
36
- end
37
-
38
- def luminous_intensity=(value)
39
- quantities_common_code(:luminous_intensity, value)
40
- end
41
-
42
- def plane_angle=(value)
43
- quantities_common_code(:plane_angle, value)
44
- end
30
+ QUANTITY_KEYS.each do |key|
31
+ define_method("#{key}=") do |value|
32
+ register_quantity(key, value)
33
+ end
45
34
 
46
- def electric_current=(value)
47
- quantities_common_code(:electric_current, value)
35
+ define_method(key) do
36
+ @quantities[key]
37
+ end
48
38
  end
49
39
 
50
40
  def dim_symbols
@@ -69,11 +59,11 @@ module Unitsml
69
59
 
70
60
  private
71
61
 
72
- def quantities_common_code(instance_var, value)
62
+ def register_quantity(key, value)
73
63
  return if value.nil?
74
64
 
75
- instance_variable_set(:"@#{instance_var}", value)
76
- @processed_keys << instance_var.to_s
65
+ @quantities[key] = value
66
+ @processed_keys << key.to_s
77
67
  dim_symbols = dimension_symbols_for(value)
78
68
  return if Lutaml::Model::Utils.empty?(dim_symbols)
79
69
 
@@ -83,12 +73,10 @@ module Unitsml
83
73
 
84
74
  def dimension_symbols_for(value)
85
75
  return [] if value.nil?
76
+ return Array(value.dim_symbols) if value.is_a?(::Unitsdb::Dimension)
77
+ return Array(value.symbols) if value.is_a?(::Unitsdb::DimensionDetails)
86
78
 
87
- if value.respond_to?(:dim_symbols)
88
- Array(value.dim_symbols)
89
- else
90
- Array(value.symbols)
91
- end
79
+ []
92
80
  end
93
81
  end
94
82
 
@@ -3,6 +3,8 @@
3
3
  module Unitsml
4
4
  module Unitsdb
5
5
  class Dimensions < ::Unitsdb::Dimensions
6
+ include Unitsml::Unitsdb::Finders
7
+
6
8
  def dimensions=(value)
7
9
  super(value.map { |d| Dimension.new(d.to_hash) })
8
10
  end
@@ -13,11 +15,11 @@ module Unitsml
13
15
  end
14
16
 
15
17
  def find_by_id(d_id)
16
- find(:id, d_id)
18
+ find_first_in(dimensions, field: :id, value: d_id)
17
19
  end
18
20
 
19
21
  def find_parsables_by_id(d_id)
20
- find(:id, parsables[d_id])
22
+ find_first_in(dimensions, field: :id, value: parsables[d_id])
21
23
  end
22
24
 
23
25
  def parsables
@@ -25,12 +27,6 @@ module Unitsml
25
27
  object.merge!(dimension.parsables)
26
28
  end
27
29
  end
28
-
29
- private
30
-
31
- def find(field, matching_data)
32
- dimensions.find { |dim| dim.send(field) == matching_data }
33
- end
34
30
  end
35
31
 
36
32
  Configuration.register_model(Dimensions, id: :dimensions)
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Unitsml
4
+ module Unitsdb
5
+ # Shared lookup helpers for Unitsml collection wrappers. Each host
6
+ # collection (Units, Prefixes, Dimensions) keeps its own public
7
+ # find_by_* API; this module owns the two scanning shapes that the
8
+ # host implementations previously duplicated.
9
+ module Finders
10
+ # Find the first item in `collection` where `item.<field> == value`.
11
+ def find_first_in(collection, field:, value:)
12
+ collection.find { |item| item.public_send(field) == value }
13
+ end
14
+
15
+ # Find the first item in `collection` where `item.<via>` contains
16
+ # an element whose `<field>` equals `value`. Used for collections
17
+ # of items that expose a nested list of identifiers or symbols.
18
+ def find_first_through(collection, via:, field:, value:)
19
+ collection.find do |item|
20
+ item.public_send(via).any? do |inner|
21
+ inner.public_send(field) == value
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -3,12 +3,15 @@
3
3
  module Unitsml
4
4
  module Unitsdb
5
5
  class Prefixes < ::Unitsdb::Prefixes
6
+ include Unitsml::Unitsdb::Finders
7
+
6
8
  def find_by_id(p_id)
7
- find(p_id, :id, :identifiers)
9
+ find_first_through(prefixes, via: :identifiers, field: :id, value: p_id)
8
10
  end
9
11
 
10
12
  def find_by_symbol_name(ascii_sym)
11
- find(ascii_sym, :ascii, :symbols)
13
+ find_first_through(prefixes, via: :symbols, field: :ascii,
14
+ value: ascii_sym)
12
15
  end
13
16
 
14
17
  def ascii_symbols
@@ -19,16 +22,6 @@ module Unitsml
19
22
  names_array.concat(symbol)
20
23
  end
21
24
  end
22
-
23
- private
24
-
25
- def find(matching_data, field, prefix_method)
26
- prefixes.find do |prefix|
27
- prefix.public_send(prefix_method.to_sym).find do |object|
28
- object.public_send(field) == matching_data
29
- end
30
- end
31
- end
32
25
  end
33
26
 
34
27
  Configuration.register_model(Prefixes, id: :prefixes)
@@ -4,9 +4,11 @@ module Unitsml
4
4
  module Unitsdb
5
5
  class Unit < ::Unitsdb::Unit
6
6
  def dimension_url
7
- quantity_id = quantity_references[0].id
7
+ quantity_id = quantity_references.first&.id
8
+ return unless quantity_id
9
+
8
10
  quantity = Unitsml::Unitsdb.quantities.find_by_id(quantity_id)
9
- quantity.dimension_reference.id
11
+ quantity&.dimension_reference&.id
10
12
  end
11
13
 
12
14
  def en_name
@@ -3,12 +3,14 @@
3
3
  module Unitsml
4
4
  module Unitsdb
5
5
  class Units < ::Unitsdb::Units
6
+ include Unitsml::Unitsdb::Finders
7
+
6
8
  def find_by_id(u_id)
7
- find(u_id, :id, :identifiers)
9
+ find_first_through(units, via: :identifiers, field: :id, value: u_id)
8
10
  end
9
11
 
10
12
  def find_by_name(u_name)
11
- find(u_name, :id, :symbols)
13
+ find_first_through(units, via: :symbols, field: :id, value: u_name)
12
14
  end
13
15
 
14
16
  def filtered
@@ -30,16 +32,6 @@ module Unitsml
30
32
  unit.symbols&.each { |unit_sym| object[unit_sym.id] = unit }
31
33
  end
32
34
  end
33
-
34
- private
35
-
36
- def find(matching_data, field, unit_method)
37
- units.find do |unit|
38
- unit.public_send(unit_method.to_sym).find do |id|
39
- id.public_send(field) == matching_data
40
- end
41
- end
42
- end
43
35
  end
44
36
 
45
37
  Configuration.register_model(Units, id: :units)
@@ -2,24 +2,28 @@
2
2
 
3
3
  require "unitsdb"
4
4
 
5
- require_relative "unitsdb/database"
6
- require_relative "unitsdb/dimension_details"
7
- require_relative "unitsdb/prefix_reference"
8
- require_relative "unitsdb/dimension"
9
- require_relative "unitsdb/dimensions"
10
- require_relative "unitsdb/unit"
11
- require_relative "unitsdb/units"
12
- require_relative "unitsdb/prefixes"
13
- require_relative "unitsdb/quantities"
14
5
  module Unitsml
15
6
  module Unitsdb
7
+ autoload :Database, "unitsml/unitsdb/database"
8
+ autoload :DimensionDetails, "unitsml/unitsdb/dimension_details"
9
+ autoload :Finders, "unitsml/unitsdb/finders"
10
+ autoload :PrefixReference, "unitsml/unitsdb/prefix_reference"
11
+ autoload :Dimension, "unitsml/unitsdb/dimension"
12
+ autoload :Dimensions, "unitsml/unitsdb/dimensions"
13
+ autoload :Unit, "unitsml/unitsdb/unit"
14
+ autoload :Units, "unitsml/unitsdb/units"
15
+ autoload :Prefixes, "unitsml/unitsdb/prefixes"
16
+ autoload :Quantities, "unitsml/unitsdb/quantities"
17
+
16
18
  class << self
17
- REQUIRED_DATABASE_FILES = %w[
18
- prefixes.yaml
19
- dimensions.yaml
20
- units.yaml
21
- quantities.yaml
22
- unit_systems.yaml
19
+ CACHE_INSTANCE_VARIABLES = %i[
20
+ @units
21
+ @prefixes
22
+ @dimensions
23
+ @quantities
24
+ @prefixes_array
25
+ @sized_prefixes
26
+ @database
23
27
  ].freeze
24
28
 
25
29
  def units
@@ -65,19 +69,23 @@ module Unitsml
65
69
  @database ||= load_database
66
70
  end
67
71
 
72
+ def reset_caches
73
+ CACHE_INSTANCE_VARIABLES.each do |ivar|
74
+ remove_instance_variable(ivar) if instance_variable_defined?(ivar)
75
+ end
76
+ end
77
+
68
78
  private
69
79
 
80
+ # Delegates to the upstream loader, falling back to the UnitsML
81
+ # Database subclass when the upstream cannot satisfy the request
82
+ # (e.g. context substitution not yet wired up). Both paths load
83
+ # from `Unitsdb.data_dir` — the upstream `Unitsdb.database` calls
84
+ # `Database.from_db(data_dir, ...)` internally, and so does the
85
+ # fallback.
70
86
  def load_database
71
87
  context_id = Configuration.context.id
72
88
 
73
- if ::Unitsdb.respond_to?(:database)
74
- return load_unitsdb_database(context_id)
75
- end
76
-
77
- Database.from_db(database_path, context: context_id)
78
- end
79
-
80
- def load_unitsdb_database(context_id)
81
89
  ::Unitsdb.database(context: context_id)
82
90
  rescue ::Unitsdb::Errors::DatabaseNotFoundError,
83
91
  ::Unitsdb::Errors::DatabaseFileNotFoundError
@@ -85,27 +93,7 @@ module Unitsml
85
93
  end
86
94
 
87
95
  def database_path
88
- candidate_database_paths.find do |path|
89
- database_files_present?(path)
90
- end ||
91
- File.join(unitsdb_gem_path, "vendor", "unitsdb")
92
- end
93
-
94
- def candidate_database_paths
95
- [
96
- File.join(unitsdb_gem_path, "data"),
97
- File.join(unitsdb_gem_path, "vendor", "unitsdb"),
98
- ]
99
- end
100
-
101
- def database_files_present?(dir_path)
102
- REQUIRED_DATABASE_FILES.all? do |file_name|
103
- File.exist?(File.join(dir_path, file_name))
104
- end
105
- end
106
-
107
- def unitsdb_gem_path
108
- Gem.loaded_specs.fetch("unitsdb").full_gem_path
96
+ ::Unitsdb.data_dir
109
97
  end
110
98
  end
111
99
  end