From 99630a67fe54b3bda151bf6e9443f0e883da6f94 Mon Sep 17 00:00:00 2001 From: Grant Hutchins Date: Fri, 24 Jul 2026 11:15:24 -0500 Subject: [PATCH] Add Unit#value_in for bare-value conversion Unit#in returns a converted Unit and Unit#in! raises on a dimensionally incompatible target, but neither yields the raw number in the requested unit without a caller peeling off #value by hand. Add Unit#value_in(unit), which converts via #in! and returns the bare numeric value. An incompatible unit therefore raises TypeError rather than handing back a coerced number with residual dimensions. --- lib/unit/class.rb | 11 +++++++++++ spec/unit_spec.rb | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/lib/unit/class.rb b/lib/unit/class.rb index 3a9ef9e..6be1d6e 100644 --- a/lib/unit/class.rb +++ b/lib/unit/class.rb @@ -289,6 +289,17 @@ def in!(unit) result end + # Converts +self+ to +unit+ and returns the bare numeric value, dropping + # the dimension. Builds on +#in!+, so a dimensionally incompatible +unit+ + # raises +TypeError+ rather than returning a coerced number with residual + # units. + # + # Unit(1, "kilometer").value_in("meter") # => 1000 + # Unit(1, "meter").value_in("volt") # raises TypeError + def value_in(unit) + in!(unit).value + end + def inspect unit.empty? ? %{Unit("#{value}")} : %{Unit("#{value_string} #{unit_string('.')}")} end diff --git a/spec/unit_spec.rb b/spec/unit_spec.rb index 95732dc..e2dbae3 100644 --- a/spec/unit_spec.rb +++ b/spec/unit_spec.rb @@ -262,6 +262,15 @@ expect(Unit(1, "kilometer/hour").in("meter/second")).to eq(Unit(5, 18, 'meter/second')) end + it 'should extract the bare value in a target unit' do + expect(Unit(1, "kilometer").value_in("meter")).to eq(1000) + expect(Unit(1, "kilometer/hour").value_in("meter/second")).to eq(Rational(5, 18)) + end + + it 'should raise when value_in is given an incompatible unit' do + expect { Unit(1, "meter").value_in("second") }.to raise_error(TypeError) + end + it 'should have a working compatible? method' do expect(Unit(7, "meter").compatible?('kilogram')).to eq(false) expect(Unit(3, "parsec").compatible_with?('meter')).to eq(true)