Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions lib/quantity.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,12 @@ def initialize(value, unit = nil )
@reference_value = value[:reference_value] || (value[:value] * @unit.value)
@value = @unit.value_for(@reference_value) #dimension.reference.convert_proc(@unit).call(@reference_value)
#@value = @unit.convert_proc(@unit).call(@reference_value)
when Numeric
when Numeric, String
@unit = Unit.for(unit)
if @unit.nil?
@unit = Unit.from_string_form(unit)
end
@value = value
@value = value.is_a?(Numeric) ? value : value.to_f
@reference_value = value * @unit.value
end
end
Expand Down Expand Up @@ -133,10 +133,10 @@ def coerce(other)
def +(other)
if (other.is_a?(Numeric))
Quantity.new(@value + other, @unit)
elsif(other.is_a?(Quantity) && @unit.dimension == other.unit.dimension)
elsif compatible_with?(other)
Quantity.new({:unit => @unit,:reference_value => @reference_value + other.reference_value})
else
raise ArgumentError,"Cannot add #{self} to #{other}"
raise ArgumentError,"Cannot add #{self} (#{@unit.dimension}) to #{other} (#{other.class}" + (other.is_a?(Quantity) ? "-#{other.unit.dimension})" : ')')
end
end

Expand All @@ -147,10 +147,10 @@ def +(other)
def -(other)
if (other.is_a?(Numeric))
Quantity.new(@value - other, @unit)
elsif(other.is_a?(Quantity) && @unit.dimension == other.unit.dimension)
elsif compatible_with?(other)
Quantity.new({:unit => @unit,:reference_value => @reference_value - other.reference_value})
else
raise ArgumentError, "Cannot subtract #{other} from #{self}"
raise ArgumentError, "Cannot subtract #{other} (#{other.class}) from #{self} (#{@unit.dimension})"
end
end

Expand All @@ -161,7 +161,7 @@ def -(other)
def <=>(other)
if (other.is_a?(Numeric))
@value <=> other
elsif(other.is_a?(Quantity) && measures == other.measures)
elsif compatible_with?(other)
@reference_value <=> other.reference_value
else
nil
Expand Down Expand Up @@ -279,6 +279,11 @@ def to_f
@value.to_f
end

def compatible_with?(other)
return false if unit.nil?
other.respond_to?(:unit) && unit.compatible_with?(other.unit)
end

# Round this value to the nearest integer
# @return [Quantity]
def round
Expand Down
6 changes: 6 additions & 0 deletions lib/quantity/dimension.rb
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,12 @@ def <=>(other)
end
end


def compatible_with?(other)
self === other || (other.respond_to?(:name) && name == other.name)
end


# Returns a developer-friendly representation of this value.
#
# The string will be of the format `#<Quantity::Dimension::0x12345678(...)>`,
Expand Down
8 changes: 7 additions & 1 deletion lib/quantity/unit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ def calculate_value
@dimension.numerators.each do | component |
component.power.times do
# we might have a unit for a compound dimension, such as liters for length^3.
value *= @units[Quantity::Dimension.for(component.dimension)].value
value *= @units[Quantity::Dimension.for(component.dimension)].value if @units[Quantity::Dimension.for(component.dimension)]
end
end
@dimension.denominators.each do | component |
Expand All @@ -305,6 +305,12 @@ def calculate_value
@value = value
end


def compatible_with?(other)
other.respond_to?(:dimension) && dimension.compatible_with?(other.dimension)
end


# A vaguely human-readable form for this unit
# @return [String]
def string_form
Expand Down