lib/unit_measurements/unit.rb in unit_measurements-4.9.0 vs lib/unit_measurements/unit.rb in unit_measurements-4.10.0
- old
+ new
@@ -3,44 +3,141 @@
# -*- warn_indent: true -*-
require "set"
module UnitMeasurements
+ # The +UnitMeasurements::Unit+ class represents a unit of measurement and
+ # provides methods to interact with its properties and conversion factors.
+ #
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
+ # @since 1.0.0
class Unit
- attr_reader :name, :value, :aliases, :system, :unit_group
+ # The name of the unit.
+ #
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
+ # @since 1.0.0
+ attr_reader :name
+ # The conversion value of the unit. It can be a numeric value or a string in
+ # the form of a number followed by a unit name (e.g., “10 m”).
+ #
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
+ # @since 1.0.0
+ attr_reader :value
+
+ # A set of alternative names for the unit.
+ #
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
+ # @since 1.0.0
+ attr_reader :aliases
+
+ # The system to which the unit belongs (e.g., “metric”, “imperial”).
+ #
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
+ # @since 4.0.0
+ attr_reader :system
+
+ # The unit group to which the unit belongs.
+ #
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
+ # @since 1.0.0
+ attr_reader :unit_group
+
+ # Initializes a new +Unit+ instance.
+ #
+ # @param [String|Symbol] name The name of the unit.
+ # @param [String|Numeric] value The conversion value of the unit.
+ # @param [Array<String|Symbol>] aliases Alternative names for the unit.
+ # @param [String|Symbol|NilClass] system The system to which the unit belongs.
+ # @param [UnitGroup|NilClass] unit_group The unit group to which the unit belongs.
+ #
+ # @see UnitGroup
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
+ # @since 1.0.0
def initialize(name, value:, aliases:, system:, unit_group: nil)
@name = name.to_s.freeze
@value = value
@aliases = Set.new(aliases.map(&:to_s).sort.map(&:freeze)).freeze
@system = system
@unit_group = unit_group
end
+ # Returns a new +Unit+ instance with specified attributes.
+ #
+ # @param [String|Symbol] name The new name of the unit.
+ # @param [String|Numeric] value The new conversion value of the unit.
+ # @param [Set<String>] aliases New alternative names for the unit.
+ # @param [String|Symbol|NilClass] system The new system to which the unit belongs.
+ # @param [UnitGroup|NilClass] unit_group The new unit group to which the unit belongs.
+ #
+ # @return [Unit] A new unit with specified parameters.
+ #
+ # @see UnitGroup
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
+ # @since 1.0.0
def with(name: nil, value: nil, aliases: nil, system: nil, unit_group: nil)
self.class.new(
(name || self.name),
value: (value || self.value),
aliases: (aliases || self.aliases),
system: (system || self.system),
unit_group: (unit_group || self.unit_group)
)
end
+ # Returns an array containing the name of the unit and its aliases, sorted
+ # alphabetically.
+ #
+ # @example
+ # UnitMeasurements::Length.new(1, "m").unit.names
+ # => ["m", "meter", "meters", "metre", "metres"]
+ #
+ # @return [Array<String>] An array of unit names.
+ #
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
+ # @since 1.0.0
def names
(aliases + [name]).sort.freeze
end
+ # Returns the name of the unit as a string.
+ #
+ # @example
+ # UnitMeasurements::Length.new(1, "m").unit.to_s
+ # => "m"
+ #
+ # @return [String] The name of the unit.
+ #
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
+ # @since 1.0.0
def to_s
name
end
+ # Returns an object representation of the unit, including its aliases if present.
+ #
+ # @return [Object] An object representation of the +unit+.
+ #
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
+ # @since 1.0.0
def inspect
aliases = "(#{@aliases.join(", ")})" if @aliases.any?
"#<#{self.class.name}: #{name} #{aliases}>"
end
+ # Calculates the conversion factor for the unit. This method is recursively
+ # invoked to calculate the conversion factor of the unit, if unit conversion
+ # +value+ is specified with respect to the other unit.
+ #
+ # This method uses +parse_value+ method to extract the conversion value and
+ # the unit.
+ #
+ # @return [Numeric] The conversion factor as a numeric value.
+ #
+ # @see #parse_value
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
+ # @since 1.0.0
def conversion_factor
return value if value.is_a?(Numeric)
measurement_value, measurement_unit = parse_value(value)
conversion_factor = unit_group.unit_for!(measurement_unit).conversion_factor
@@ -48,10 +145,14 @@
conversion_factor * measurement_value
end
private
+ # Decimal prefixes for SI units.
+ #
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
+ # @since 1.0.0
SI_DECIMAL_PREFIXES = [
["q", %w(quecto), 1e-30],
["r", %w(ronto), 1e-27],
["y", %w(yocto), 1e-24],
["z", %w(zepto), 1e-21],
@@ -75,9 +176,35 @@
["Y", %w(yotta), 1e+24],
["R", %w(ronna), 1e+27],
["Q", %w(quetta), 1e+30]
].map(&:freeze).freeze
+ # Parses tokens and returns a +conversion value+ and the +unit+.
+ #
+ # This method is used internally to parse the conversion value of the unit
+ # while calculating the conversion factor. It handles cases where the value
+ # can be provided as a string or an array containing a number and a unit.
+ #
+ # For example, if the value is provided as a string in the form of "10 m",
+ # it will be parsed to return 10.0 as the conversion value and "m" as the
+ # unit.
+ #
+ # This method returns conversion value in +rational+ number to avoid precision
+ # errors and frozen string of unit name.
+ #
+ # @param [String|Array] tokens
+ # The value to be parsed. It can be either a string or an array containing
+ # a number and a unit.
+ #
+ # @return [Array<Numeric, String>] The array of conversion value and the unit.
+ #
+ # @raise [BaseError]
+ # if +tokens+ is not an instance of +Array+ or +String+, or +tokens+ array
+ # contains more than two elements.
+ #
+ # @see #conversion_factor
+ # @author {Harshal V. Ladhe}[https://shivam091.github.io/]
+ # @since 1.2.0
def parse_value(tokens)
case tokens
when String
tokens = Parser.parse(value)
when Array