minad/unit — Issue #20: Loading order of units is broken in Ruby 1.8.7
Author: esb
Created: 2012-02-22 22:38:43+00:00
State: open

The loading order of the unit definitions is important because one unit definition may refer to another unit definition, and the current load algorithm assumes the units are created in the order in which they are defined in the yaml file.

The load function uses a hash of unit definitions and under Ruby 1.9 the order of the hash keys is determined by the order in which they were created. Under Ruby 1.8, this order is undefined and it appears that until the recent changes to the hash algorithm this wasn't a problem, as the random order didn't cause any problems with undefined units. With the latest Ruby 1.8.7 release, this is no longer the case and the code breaks when it is loaded.

The solution is to load all unit definitions before attempting to parse them. This requires a simple change which defers the calling of the parse_unit function.

The modified code from the load function in system.rb is -

```ruby
(data['units'] || {}).each do |name, unit|
name = name.to_sym
symbols = [unit['sym'] || []].flatten
$stderr.puts "Unit #{name} already defined" if @unit[name]
@unit[name] = { :symbol => symbols.first, :defs => unit['def'] }
symbols.each do |sym|
$stderr.puts "Unit symbol #{sym} for #{name} already defined" if @unit_symbol[name]
@unit_symbol[sym] = name
end
@unit_symbol[name.to_s] = name
end

@unit.each do |name, unit|
defs = unit.delete(:defs)
unit[:def] = parse_unit(defs) if defs
validate_unit(unit[:def])
end
```

The definition is initially stored under the :defs key as an unparsed string. Once the units have been loaded, every :defs key is parsed and the result stored under the :def key.