Status: Draft · Last meaningful commit: 2015-06-09 · Plan written: 2026-06
unit adds scientific/computational units to Ruby (1.meter.in_kilometer,
Unit('1 m/s^2'), unit-aware arithmetic and conversions). The core library is
small (~600 LOC plus YAML unit definitions), dependency-free at runtime, and
still loads cleanly on modern Ruby. What has rotted is everything around the
code — CI, badges, gemspec metadata — plus two genuine correctness bugs. This
document is the roadmap for bringing it back to a releasable, maintained state.
| Area | State | Notes |
|---|---|---|
| Core library | 🟢 Good | Loads on Ruby 4.0.5 with zero warnings under ruby -w. Clean architecture. |
| Test suite | 🟡 2 failures | 49 examples, 2 failures via bundle exec rake. Both are real bugs (see below). |
| CI | 🔴 Dead | .travis.yml targets EOL Rubies (1.9.3–2.2, rbx, jruby-19mode); Travis CI is defunct for OSS. |
| README badges | 🔴 Dead | Gemnasium (shut down), badge.fury.io/*.png, Code Climate, travis-ci.org all gone. |
| Gemspec | 🟡 Warnings | No required_ruby_version; description == summary; non-reproducible s.date; unpinned rspec. |
| Releases / tags | 🟡 Out of sync | Only v0.4.1 is tagged; code and RubyGems are at 0.5.0. |
| Provenance | ℹ️ | upstream = minad/unit (Daniel Mendler); origin = nertzy/unit. |
Both failing specs share one root cause: Unit#normalize mutates its
receiver instead of operating on a copy.
spec/unit_spec.rb:110—#normalize"should not modify the receiver": afterUnit(1, 'joule').normalize, the original is mutated into1000 g·m^2·s^-2.spec/unit_spec.rb:152—(Unit('5 cm') - Unit('1 cm')).to_sreturns"(1/25) m"instead of"4 cm".+/-call.in(self)to convert back to the caller's unit, but the normalize mutation corrupts that round-trip, so subtraction/addition silently lose the chosen unit.
Root cause: lib/unit/class.rb normalize does @normalized ||= dup.normalize!,
but initialize_copy only shallow-dups @unit (an array of arrays).
reduce! / normalize! then mutate inner arrays still shared with the original.
Likely surfaced by Numeric/Rational/dup behavior changes in newer Ruby.
Each step is intended to be its own focused commit. Following the BDD/TDD workflow: drive the bug fix from the already-failing specs, then layer infra and metadata changes on top.
- Deep-dup
@unit(and reset memoized@normalized) ininitialize_copysonormalizenever touches its receiver. - Confirm
bundle exec rakereports49 examples, 0 failures. - Add a focused regression spec for add/subtract preserving the caller's
unit (e.g.
5 cm - 1 cm == 4 cmround-trips ascm).
- Add
.github/workflows/ci.ymlrunningbundle exec rakeon a current Ruby matrix (3.2, 3.3, 3.4, andhead). - Delete
.travis.yml. - (Optional) Add a JRuby/TruffleRuby leg once the suite is green on MRI.
- Remove the Gemnasium, Travis, Code Climate, and Fury PNG badges.
- Add a working RubyGems version badge and a GitHub Actions status badge.
- Verify all usage examples still run as written (they double as docs).
- Declare
required_ruby_version(proposed floor:>= 3.0). - Give
descriptionreal prose distinct fromsummary. - Remove
s.date = Date.today.to_s(RubyGems sets this; it breaks reproducible builds). - Pin dev dependency
rspecto~> 3.0(suite is already RSpec 3 syntax).
- Add
CHANGELOG.mddocumenting the bug fix and modernization. - Re-sync git tags (tag the current
0.5.0), then cut the next maintenance release (likely0.5.1for the bug fix). - Add a
.ruby-version/ confirmmiseconfig for a pinned dev Ruby.
- New unit systems or features — this pass is purely revival/maintenance.
- Performance work on the parser in
lib/unit/system.rb. - API changes; keep
0.5.xbackward compatible.
- Minimum supported Ruby — is
>= 3.0acceptable, or do we need to support older still-in-use versions?