Class: BasicTemperature
- Inherits:
-
Object
- Object
- BasicTemperature
- Includes:
- Comparable
- Defined in:
- lib/basic_temperature.rb,
lib/basic_temperature/version.rb
Overview
Temperature is a simple Value Object for basic temperature operations like conversions from Celsius to Fahrenhait or Kelvin etc.
Supported scales: Celsius, Fahrenheit, Kelvin and Rankine.
Creating Temperatures
A new temperature can be created in multiple ways:
-
Using keyword arguments:
Temperature.new(degrees: 0, scale: :celsius) -
Using positional arguments:
Temperature.new(0, :celsius) -
Even more concise way using
Temperature.[](an alias ofTemperature.new):Temperature[0, :celsius]
Creating Temperatures from already existing temperature objects
Sometimes it is useful to create a new temperature from already existing one.
For such cases, there are #set_degrees[BasicTemperature#set_degrees and set_scale.
Since temperatures are Value Objects, both methods returns new instances.
Examples:
temperature = Temperature[0, :celsius]
# => 0 °C
new_temperature = temperature.set_degrees(15)
# => 15 °C
temperature = Temperature[0, :celsius]
# => 0 °C
new_temperature = temperature.set_scale(:kelvin)
# => 0 K
Conversions
Temperatures can be converted to diffirent scales.
Currently, the following scales are supported: Celsius, Fahrenheit, Kelvin and Rankine.
Temperature[20, :celsius].to_celsius
# => 20 °C
Temperature[20, :celsius].to_fahrenheit
# => 68 °F
Temperature[20, :celsius].to_kelvin
# => 293.15 K
Temperature[20, :celsius].to_rankine
# => 527.67 °R
If it is necessary to convert scale dynamically, to_scale method is available.
Temperature[20, :celsius].to_scale(scale)
All conversion formulas are taken from RapidTables.
Conversion precision: 2 accurate digits after the decimal dot.
Comparison
Temperature implements idiomatic <=> spaceship operator and mixes in Comparable module.
As a result, all methods from Comparable are available, e.g:
Temperature[20, :celsius] < Temperature[25, :celsius]
# => true
Temperature[20, :celsius] <= Temperature[25, :celsius]
# => true
Temperature[20, :celsius] == Temperature[25, :celsius]
# => false
Temperature[20, :celsius] > Temperature[25, :celsius]
# => false
Temperature[20, :celsius] >= Temperature[25, :celsius]
# => false
Temperature[20, :celsius].between?(Temperature[15, :celsius], Temperature[25, :celsius])
# => true
# Starting from Ruby 2.4.6
Temperature[20, :celsius].clamp(Temperature[20, :celsius], Temperature[25, :celsius])
# => 20 °C
Please note, if other temperature has a different scale, temperature is automatically converted to that scale before comparison.
Temperature[20, :celsius] == Temperature[293.15, :kelvin]
# => true
IMPORTANT !!!
degrees are rounded to the nearest value with a precision of 2 decimal digits before comparison.
This means the following temperatures are considered as equal:
Temperature[20.020, :celsius] == Temperature[20.024, :celsius]
# => true
Temperature[20.025, :celsius] == Temperature[20.029, :celsius]
# => true
while these ones are treated as NOT equal:
Temperature[20.024, :celsius] == Temperature[20.029, :celsius]
# => false
Math
Addition/Subtraction.
Temperature[20, :celsius] + Temperature[10, :celsius]
# => 30 °C
Temperature[20, :celsius] - Temperature[10, :celsius]
# => 10 °C
If second temperature has a different scale, first temperature is automatically converted to that scale before degrees addition/subtraction.
Temperature[283.15, :kelvin] + Temperature[10, :celsius]
# => 10 °C
Returned temperature will have the same scale as the second temperature.
It is possible to add/subtract numerics.
Temperature[20, :celsius] + 10
# => 30 °C
Temperature[20, :celsius] - 10
# => 10 °C
In such cases, returned temperature will have the same scale as the first temperature.
Also Ruby coersion mechanism is supported.
10 + Temperature[20, :celsius]
# => 30 °C
10 - Temperature[20, :celsius]
# => -10 °C
Negation
-Temperature[20, :celsius]
# => -20 °C
Defined Under Namespace
Classes: InitializationArgumentsError, InvalidDegreesError, InvalidNumericOrTemperatureError, InvalidScaleError
Constant Summary collapse
- CELSIUS =
'celsius'- FAHRENHEIT =
'fahrenheit'- KELVIN =
'kelvin'- RANKINE =
'rankine'- SCALES =
A list of all currently supported scale values.
[CELSIUS, FAHRENHEIT, KELVIN, RANKINE].freeze
- VERSION =
'0.2.2'
Instance Attribute Summary collapse
-
#degrees ⇒ Object
readonly
Degrees of the temperature.
-
#scale ⇒ Object
readonly
Scale of the temperature.
Class Method Summary collapse
-
.[](*args, **kwargs) ⇒ Object
Creates a new instance of Temperature.
Instance Method Summary collapse
-
#+(other) ⇒ Object
Performs addition.
-
#-(other) ⇒ Object
Performs subtraction.
-
#-@ ⇒ Object
Returns a new Temperature with negated
degrees. -
#<=>(other) ⇒ Object
Compares temperture with
othertemperature. -
#coerce(numeric) ⇒ Object
Is used by + and - for Ruby coersion mechanism.
-
#initialize(*positional_arguments, **keyword_arguments) ⇒ BasicTemperature
constructor
Creates a new instance of Temperature.
-
#inspect ⇒ Object
Returns a string containing a human-readable representation of temperature.
-
#set_degrees(degrees) ⇒ Object
Returns a new Temperature with updated
degrees. -
#set_scale(scale) ⇒ Object
Returns a new Temperature with updated
scale. -
#to_celsius ⇒ Object
Converts temperature to Celsius scale.
-
#to_fahrenheit ⇒ Object
Converts temperature to Fahrenheit scale.
-
#to_kelvin ⇒ Object
Converts temperature to Kelvin scale.
-
#to_rankine ⇒ Object
Converts temperature to Rankine scale.
-
#to_scale(scale) ⇒ Object
Converts temperature to specific
scale.
Constructor Details
#initialize(*positional_arguments, **keyword_arguments) ⇒ BasicTemperature
Creates a new instance of Temperature. Is aliased as [].
:call-seq:
new(degrees:, scale:)
new(degrees, scale)
226 227 228 229 230 231 232 233 234 |
# File 'lib/basic_temperature.rb', line 226 def initialize(*positional_arguments, **keyword_arguments) assert_either_positional_arguments_or_keyword_arguments!(positional_arguments, keyword_arguments) if keyword_arguments.any? initialize_via_keywords_arguments(keyword_arguments) else # positional_arguments.any? initialize_via_positional_arguments(positional_arguments) end end |
Instance Attribute Details
#degrees ⇒ Object (readonly)
Degrees of the temperature.
203 204 205 |
# File 'lib/basic_temperature.rb', line 203 def degrees @degrees end |
#scale ⇒ Object (readonly)
Scale of the temperature. Look at SCALES for possible values.
206 207 208 |
# File 'lib/basic_temperature.rb', line 206 def scale @scale end |
Class Method Details
.[](*args, **kwargs) ⇒ Object
Creates a new instance of Temperature. Alias for new.
:call-seq:
[](degrees:, scale:)
[](degrees, scale)
215 216 217 |
# File 'lib/basic_temperature.rb', line 215 def self.[](*args, **kwargs) new(*args, **kwargs) end |
Instance Method Details
#+(other) ⇒ Object
Performs addition. Returns a new Temperature.
Temperature[20, :celsius] + Temperature[10, :celsius]
# => 30 °C
If the second temperature has a different scale, the first temperature is automatically converted to that scale before degrees addition.
Temperature[283.15, :kelvin] + Temperature[20, :celsius]
# => 30 °C
Returned temperature will have the same scale as the second temperature.
It is possible to add numerics.
Temperature[20, :celsius] + 10
# => 30 °C
In such cases, returned temperature will have the same scale as the first temperature.
Also Ruby coersion mechanism is supported.
10 + Temperature[20, :celsius]
# => 30 °C
:call-seq:
+(temperature)
+(numeric)
493 494 495 496 497 498 499 500 501 502 503 504 505 |
# File 'lib/basic_temperature.rb', line 493 def +(other) assert_numeric_or_temperature!(other) degrees, scale = case other when Numeric [self.degrees + other, self.scale] when BasicTemperature [self.to_scale(other.scale).degrees + other.degrees, other.scale] end BasicTemperature.new(degrees, scale) end |
#-(other) ⇒ Object
Performs subtraction. Returns a new Temperature.
Temperature[20, :celsius] - Temperature[10, :celsius]
# => 10 °C
If the second temperature has a different scale, the first temperature is automatically converted to that scale before degrees subtraction.
Temperature[283.15, :kelvin] + Temperature[10, :celsius]
# => 10 °C
Returned temperature will have the same scale as the second temperature.
It is possible to subtract numerics.
Temperature[20, :celsius] - 10
# => 10 °C
In such cases, returned temperature will have the same scale as the first temperature.
Also Ruby coersion mechanism is supported.
10 - Temperature[20, :celsius]
# => -10 °C
:call-seq:
-(temperature)
-(numeric)
537 538 539 |
# File 'lib/basic_temperature.rb', line 537 def -(other) self + -other end |
#-@ ⇒ Object
Returns a new Temperature with negated degrees.
-Temperature[20, :celsius]
# => -20 °C
547 548 549 |
# File 'lib/basic_temperature.rb', line 547 def -@ BasicTemperature.new(-self.degrees, self.scale) end |
#<=>(other) ⇒ Object
Compares temperture with other temperature.
Returns 0 if they are considered as equal.
Two temperatures are considered as equal when they have the same amount of degrees.
Returns -1 if temperature is lower than other temperature.
Returns 1 if temperature is higher than other temperature.
If other temperature has a different scale, temperature is automatically converted to that scale before degrees comparison.
Temperature[20, :celsius] <=> Temperature[20, :celsius]
# => 0
Temperature[20, :celsius] <=> Temperature[293.15, :kelvin]
# => 0
IMPORTANT!!!
This method rounds degrees to the nearest value with a precision of 2 decimal digits.
This means the following:
Temperature[20.020, :celsius] <=> Temperature[20.024, :celsius]
# => 0
Temperature[20.025, :celsius] <=> Temperature[20.029, :celsius]
# => 0
Temperature[20.024, :celsius] <=> Temperature[20.029, :celsius]
# => -1
457 458 459 460 461 |
# File 'lib/basic_temperature.rb', line 457 def <=>(other) return unless assert_temperature(other) compare_degrees(self.to_scale(other.scale).degrees, other.degrees) end |
#coerce(numeric) ⇒ Object
Is used by + and - for Ruby coersion mechanism.
553 554 555 556 557 |
# File 'lib/basic_temperature.rb', line 553 def coerce(numeric) #:nodoc: assert_numeric!(numeric) [BasicTemperature.new(numeric, self.scale), self] end |
#inspect ⇒ Object
Returns a string containing a human-readable representation of temperature.
560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 |
# File 'lib/basic_temperature.rb', line 560 def inspect #:nodoc: rounded_degrees = round_degrees(degrees) printable_degrees = degrees_without_decimal?(rounded_degrees) ? rounded_degrees.to_i : rounded_degrees scale_symbol = case self.scale when CELSIUS '°C' when FAHRENHEIT '°F' when KELVIN 'K' when RANKINE '°R' end "#{printable_degrees} #{scale_symbol}" end |
#set_degrees(degrees) ⇒ Object
Returns a new Temperature with updated degrees.
temperature = Temperature[0, :celsius]
# => 0 °C
new_temperature = temperature.set_degrees(15)
# => 15 °C
246 247 248 |
# File 'lib/basic_temperature.rb', line 246 def set_degrees(degrees) BasicTemperature.new(degrees, scale) end |
#set_scale(scale) ⇒ Object
Returns a new Temperature with updated scale.
temperature = Temperature[0, :celsius]
# => 0 °C
new_temperature = temperature.set_scale(:kelvin)
# => 0 K
261 262 263 |
# File 'lib/basic_temperature.rb', line 261 def set_scale(scale) BasicTemperature.new(degrees, scale) end |
#to_celsius ⇒ Object
Converts temperature to Celsius scale. If temperature is already in Celsius, returns current temperature object.
Memoizes subsequent calls.
Conversion formulas are taken from RapidTables:
Temperature[0, :fahrenheit].to_celsius
# => -17.78 °C
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 |
# File 'lib/basic_temperature.rb', line 308 def to_celsius memoized(:to_celsius) || memoize(:to_celsius, -> { return self if self.scale == CELSIUS degrees = case self.scale when FAHRENHEIT (self.degrees - 32) * (5 / 9r) when KELVIN self.degrees - 273.15 when RANKINE (self.degrees - 491.67) * (5 / 9r) end BasicTemperature.new(degrees, CELSIUS) }) end |
#to_fahrenheit ⇒ Object
Converts temperature to Fahrenheit scale. If temperature is already in Fahrenheit, returns current temperature object.
Memoizes subsequent calls.
Conversion formulas are taken from RapidTables:
Temperature[0, :celsius].to_fahrenheit
# => 32 °F
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 |
# File 'lib/basic_temperature.rb', line 340 def to_fahrenheit memoized(:to_fahrenheit) || memoize(:to_fahrenheit, -> { return self if self.scale == FAHRENHEIT degrees = case self.scale when CELSIUS self.degrees * (9 / 5r) + 32 when KELVIN self.degrees * (9 / 5r) - 459.67 when RANKINE self.degrees - 459.67 end BasicTemperature.new(degrees, FAHRENHEIT) }) end |
#to_kelvin ⇒ Object
Converts temperature to Kelvin scale. If temperature is already in Kelvin, returns current
temperature object.
Memoizes subsequent calls.
Conversion formulas are taken from RapidTables:
Temperature[0, :kelvin].to_rankine
# => 0 °R
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 |
# File 'lib/basic_temperature.rb', line 372 def to_kelvin memoized(:to_kelvin) || memoize(:to_kelvin, -> { return self if self.scale == KELVIN degrees = case self.scale when CELSIUS self.degrees + 273.15 when FAHRENHEIT (self.degrees + 459.67) * (5 / 9r) when RANKINE self.degrees * (5 / 9r) end BasicTemperature.new(degrees, KELVIN) }) end |
#to_rankine ⇒ Object
Converts temperature to Rankine scale. If temperature is already in Rankine, returns current temperature object.
Memoizes subsequent calls.
Conversion formulas are taken from RapidTables:
Temperature[0, :rankine].to_kelvin
# => 0 K
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 |
# File 'lib/basic_temperature.rb', line 404 def to_rankine memoized(:to_rankine) || memoize(:to_rankine, -> { return self if self.scale == RANKINE degrees = case self.scale when CELSIUS (self.degrees + 273.15) * (9 / 5r) when FAHRENHEIT self.degrees + 459.67 when KELVIN self.degrees * (9 / 5r) end BasicTemperature.new(degrees, RANKINE) }) end |
#to_scale(scale) ⇒ Object
Converts temperature to specific scale. If temperature is already in desired scale, returns current temperature object.
Raises InvalidScaleError when scale can not be casted to any possible scale value (see SCALES).
Temperature[60, :fahrenheit].to_scale(:celsius)
# => 15.56 °C
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
# File 'lib/basic_temperature.rb', line 277 def to_scale(scale) casted_scale = cast_scale(scale) assert_valid_scale!(casted_scale) case casted_scale when CELSIUS to_celsius when FAHRENHEIT to_fahrenheit when KELVIN to_kelvin when RANKINE to_rankine end end |