diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ef0dca..11206a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +## [5.13.0](https://github.com/shivam091/unit_measurements/compare/v5.12.0...v5.13.0) - 2023-11-27 + +### What's new + +- Added `Measurement#to_primitive` to convert the measurement to the primitive unit. +- Added `#cbrt` method to calculate cube root of the measurement quantity. +- Added `#sqrt` method to calculate square root of the measurement quantity. +- Aliased `#to_primitive` method as `#in_primitive` and `#as_primitive`. + +---------- + ## [5.12.0](https://github.com/shivam091/unit_measurements/compare/v5.11.1...v5.12.0) - 2023-11-25 ### What's new diff --git a/Gemfile.lock b/Gemfile.lock index 7ce291e..50031c6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - unit_measurements (5.12.0) + unit_measurements (5.13.0) activesupport (~> 7.0) GEM diff --git a/README.md b/README.md index 2272912..3ddee5b 100644 --- a/README.md +++ b/README.md @@ -116,10 +116,12 @@ UnitMeasurements::Length.new(1, "km").convert_to!("m") You can convert the measurement directly to the `primitive` unit of the unit group as: ```ruby -UnitMeasurements::Length.new(1, "cm").convert_to("primitive") +UnitMeasurements::Length.new(1, "cm").to_primitive #=> 0.01 m ``` +Note: `#to_primitive` method is aliased as `#in_primitive` and `#as_primitive`. + **Parse string without having to split out the quantity and source unit:** This method provides `use_cache` parameter which defaults to `false` to indicate whether the caching of conversion factors should happen. @@ -444,7 +446,7 @@ unit group using the `primitive` method. You can specify cache file name in unit ```ruby UnitMeasurements::MyUnitGroup = UnitMeasurements.build do - # Set primitive unit for the unit group (optional). + # Set primitive unit for the unit group. primitive "s" # Group units by the unit system (optional). diff --git a/lib/unit_measurements/math.rb b/lib/unit_measurements/math.rb index 483d51c..3fa1dce 100644 --- a/lib/unit_measurements/math.rb +++ b/lib/unit_measurements/math.rb @@ -87,5 +87,34 @@ def floor(ndigits = 0) def ceil(ndigits = 0) self.class.new(quantity.ceil(ndigits), unit) end + + # Returns square root of the measurement quantity. + # + # @example + # UnitMeasurements::Length.new(9, "m").sqrt + # => 3.0 m + # + # @return [Measurement] A new +Measurement+ instance with square root of quantity. + # + # @author {Harshal V. Ladhe}[https://shivam091.github.io/] + # @since 5.13.0 + def sqrt + self.class.new((quantity ** Rational(1, 2)), unit) + end + + # Returns cube root of the measurement quantity. + # + # @example + # UnitMeasurements::Length.new(27, "m").cbrt + # => 3.0 m + # + # @return [Measurement] + # A new +Measurement+ instance with cube root of quantity. + # + # @author {Harshal V. Ladhe}[https://shivam091.github.io/] + # @since 5.13.0 + def cbrt + self.class.new((quantity ** Rational(1, 3)), unit) + end end end diff --git a/lib/unit_measurements/measurement.rb b/lib/unit_measurements/measurement.rb index 856455d..016920c 100644 --- a/lib/unit_measurements/measurement.rb +++ b/lib/unit_measurements/measurement.rb @@ -131,15 +131,11 @@ def initialize(quantity, unit) # UnitMeasurements::Length.new(1, "m").convert_to("cm") # => 100.0 cm # - # UnitMeasurements::Length.new(1, "cm").convert_to("primitive") - # => 0.01 m - # - # UnitMeasurements::Length.new(1, "m").convert_to("cm", use_cache: true) - # => 100.0 cm + # UnitMeasurements::Length.new(1, "m").convert_to("mm", use_cache: true) + # => 1000.0 cm # # @param [String|Symbol] target_unit - # The target unit for conversion. Specifing +primitive+ will convert the - # measurement to a primitive unit of the unit group. + # The target unit for conversion. # @param [TrueClass|FalseClass] use_cache # Indicates whether to use cached conversion factors. # @@ -147,20 +143,10 @@ def initialize(quantity, unit) # A new +Measurement+ instance with the converted +quantity+ and # +target unit+. # - # @raise [MissingPrimitiveUnitError] - # if primitive unit is not set for the unit group. - # # @author {Harshal V. Ladhe}[https://shivam091.github.io/] # @since 1.0.0 def convert_to(target_unit, use_cache: false) - target_unit = if target_unit.to_s.eql?("primitive") - primitive_unit = self.class.primitive - - raise MissingPrimitiveUnitError if primitive_unit.nil? - primitive_unit - else - unit_from_unit_or_name!(target_unit) - end + target_unit = unit_from_unit_or_name!(target_unit) return self if target_unit == unit conversion_factor = calculate_conversion_factor(target_unit, use_cache) @@ -177,15 +163,11 @@ def convert_to(target_unit, use_cache: false) # UnitMeasurements::Length.new(1, "m").convert_to!("cm") # => 100.0 cm # - # UnitMeasurements::Length.new(1, "cm").convert_to!("primitive") - # => 0.01 m - # - # UnitMeasurements::Length.new(1, "m").convert_to!("cm", use_cache: true) - # => 100.0 cm + # UnitMeasurements::Length.new(1, "m").convert_to!("mm", use_cache: true) + # => 1000.0 mm # # @param [String|Symbol] target_unit - # The target unit for conversion. Specifing +primitive+ will convert the - # measurement to a primitive unit of the unit group. + # The target unit for conversion. # @param [TrueClass|FalseClass] use_cache # Indicates whether to use cached conversion factors. # @@ -205,6 +187,41 @@ def convert_to!(target_unit, use_cache: false) alias_method :in!, :convert_to! alias_method :as!, :convert_to! + # Converts the measurement to its primitive unit and returns a new instance + # of the +Measurement+. + # + # The method first retrieves the primitive unit of the unit group associated + # with the measurement. If the primitive unit is not set, it raises a + # +MissingPrimitiveUnitError+. + # + # @example + # UnitMeasurements::Length.new(1, "m").to_primitive + # => 1 m + # + # UnitMeasurements::Length.new(1, "cm").to_primitive + # => 0.01 m + # + # @param [TrueClass|FalseClass] use_cache + # Indicates whether to use cached conversion factors. + # @return [Measurement] + # A new +Measurement+ instance representing the measurement in its + # primitive unit. + # + # @raise [MissingPrimitiveUnitError] + # If the primitive unit is not set for the unit group associated with the + # measurement. + # + # @author {Harshal V. Ladhe}[https://shivam091.github.io/] + # @since 5.13.0 + def to_primitive(use_cache: false) + primitive_unit = self.class.primitive + raise MissingPrimitiveUnitError if primitive_unit.nil? + + convert_to(primitive_unit, use_cache: use_cache) + end + alias_method :in_primitive, :to_primitive + alias_method :as_primitive, :to_primitive + # Returns an object representation of the +Measurement+. # # @param [TrueClass|FalseClass] dump If +true+, returns the dump representation. diff --git a/lib/unit_measurements/version.rb b/lib/unit_measurements/version.rb index 8636abe..c8f5bf1 100644 --- a/lib/unit_measurements/version.rb +++ b/lib/unit_measurements/version.rb @@ -4,5 +4,5 @@ module UnitMeasurements # Current stable version. - VERSION = "5.12.0" + VERSION = "5.13.0" end diff --git a/spec/unit_measurements/math_spec.rb b/spec/unit_measurements/math_spec.rb index b151595..1e64635 100644 --- a/spec/unit_measurements/math_spec.rb +++ b/spec/unit_measurements/math_spec.rb @@ -6,7 +6,7 @@ RSpec.describe UnitMeasurements::Math do describe "#round" do - let(:measurement) { UnitMeasurements::Length.new(17.625, :m) } + let(:measurement) { UnitMeasurements::Length.new(17.625, "m") } context "when parameter ndigits is not specified" do it "rounds quantity to nearest integer" do @@ -24,7 +24,7 @@ end describe "#abs" do - let(:measurement) { UnitMeasurements::Length.new(-17.625, :m) } + let(:measurement) { UnitMeasurements::Length.new(-17.625, "m") } it "returns absolute value of the quantity." do expect(measurement.abs.quantity).to eq(17.625) @@ -32,7 +32,7 @@ end describe "#floor" do - let(:measurement) { UnitMeasurements::Length.new(17.625, :cm) } + let(:measurement) { UnitMeasurements::Length.new(17.625, "cm") } it "rounds quantity to next lower integer" do expect(measurement.floor.quantity).to eq(17) @@ -40,10 +40,26 @@ end describe "#ceil" do - let(:measurement) { UnitMeasurements::Length.new(17.625, :m) } + let(:measurement) { UnitMeasurements::Length.new(17.625, "m") } it "rounds quantity to next higher integer" do expect(measurement.ceil.quantity).to eq(18) end end + + describe "#sqrt" do + let(:measurement) { UnitMeasurements::Length.new(4, "m") } + + it "returns square root of measurement quantity" do + expect(measurement.sqrt.quantity).to eq(2.0) + end + end + + describe "#cbrt" do + let(:measurement) { UnitMeasurements::Length.new(27, "m") } + + it "returns cube root of measurement quantity" do + expect(measurement.cbrt.quantity).to eq(3.0) + end + end end diff --git a/spec/unit_measurements/measurement_spec.rb b/spec/unit_measurements/measurement_spec.rb index 7ecd8e8..4d640c7 100644 --- a/spec/unit_measurements/measurement_spec.rb +++ b/spec/unit_measurements/measurement_spec.rb @@ -82,10 +82,26 @@ expect(converted_length.quantity).to eq(1e-5) end + end + + describe "#convert_to!" do + let(:measurement) { UnitMeasurements::Length.new(300, "cm") } + + it "modifies the measurement object" do + expect(measurement.quantity).to eq(300) + expect(measurement.unit).to eq(cm) + + measurement.convert_to!("m") + + expect(measurement.quantity).to eq(3) + expect(measurement.unit).to eq(m) + end + end + describe "#to_primitive" do context "when the primitive unit is set to unit group" do it "converts to a primitive unit" do - converted_length = other_length.convert_to("primitive") + converted_length = other_length.to_primitive expect(converted_length.quantity).to eq(1) expect(converted_length.unit).to eq(m) @@ -97,26 +113,12 @@ allow(UnitMeasurements::Length).to receive(:primitive).and_return(nil) expect { - UnitMeasurements::Length.new(1, "m").convert_to("primitive") + UnitMeasurements::Length.new(1, "cm").to_primitive }.to raise_error(UnitMeasurements::MissingPrimitiveUnitError, "The primitive unit is not set for the unit group.") end end end - describe "#convert_to!" do - let(:measurement) { UnitMeasurements::Length.new(300, "cm") } - - it "modifies the measurement object" do - expect(measurement.quantity).to eq(300) - expect(measurement.unit).to eq(cm) - - measurement.convert_to!("m") - - expect(measurement.quantity).to eq(3) - expect(measurement.unit).to eq(m) - end - end - describe "#inspect" do it "returns a formatted string representation" do expect(base_length.inspect).to eq("1 m")