Class: BasicTemperature::Temperature
- Inherits:
-
Object
- Object
- BasicTemperature::Temperature
- Includes:
- AdditionalHelpers, Assertions, Casting, Errors, Initialization, Memoization, Rounding, Comparable
- Defined in:
- lib/basic_temperature/temperature.rb,
lib/basic_temperature/temperature/errors.rb,
lib/basic_temperature/temperature/casting.rb,
lib/basic_temperature/temperature/rounding.rb,
lib/basic_temperature/temperature/assertions.rb,
lib/basic_temperature/temperature/memoization.rb,
lib/basic_temperature/temperature/initialization.rb,
lib/basic_temperature/temperature/additional_helpers.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 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
Queries
Temperature[0, :celsius].boil_water?
# => false
Temperature[0, :celsius].freeze_water?
# => true
Defined Under Namespace
Modules: AdditionalHelpers, Assertions, Casting, Errors, Initialization, Memoization, Rounding
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
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
Compares temperture with
other
temperature. -
#boil_water? ⇒ Boolean
Returns true when temperature boils water (is greater than or equal to 100 °C), false otherwise.
-
#coerce(numeric) ⇒ Object
Is used by + and - for Ruby coersion mechanism.
-
#freeze_water? ⇒ Boolean
Returns true when temperature freezes water (is less than or equal to 0 °C), false otherwise.
-
#initialize(*positional_arguments, **keyword_arguments) ⇒ Temperature
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) ⇒ Temperature
Creates a new instance of Temperature. Is aliased as []
.
:call-seq:
new(degrees:, scale:)
new(degrees, scale)
235 236 237 238 239 240 241 242 243 |
# File 'lib/basic_temperature/temperature.rb', line 235 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.
212 213 214 |
# File 'lib/basic_temperature/temperature.rb', line 212 def degrees @degrees end |
#scale ⇒ Object (readonly)
Scale of the temperature. Look at SCALES for possible values.
215 216 217 |
# File 'lib/basic_temperature/temperature.rb', line 215 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)
224 225 226 |
# File 'lib/basic_temperature/temperature.rb', line 224 def self.[](*args, **kwargs) new(*args, **kwargs) end |
Instance Method Details
#<=>(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
466 467 468 469 470 |
# File 'lib/basic_temperature/temperature.rb', line 466 def <=>(other) return unless assert_temperature(other) round_degrees(self.to_scale(other.scale).degrees) <=> round_degrees(other.degrees) end |
#boil_water? ⇒ Boolean
Returns true when temperature boils water (is greater than or equal to 100 °C), false otherwise.
476 477 478 |
# File 'lib/basic_temperature/temperature.rb', line 476 def boil_water? self.to_celsius.degrees >= 100 end |
#coerce(numeric) ⇒ Object
Is used by + and - for Ruby coersion mechanism.
490 491 492 493 494 |
# File 'lib/basic_temperature/temperature.rb', line 490 def coerce(numeric) #:nodoc: assert_numeric!(numeric) [Temperature.new(numeric, self.scale), self] end |
#freeze_water? ⇒ Boolean
Returns true when temperature freezes water (is less than or equal to 0 °C), false otherwise.
484 485 486 |
# File 'lib/basic_temperature/temperature.rb', line 484 def freeze_water? self.to_celsius.degrees <= 0 end |
#inspect ⇒ Object
Returns a string containing a human-readable representation of temperature.
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 |
# File 'lib/basic_temperature/temperature.rb', line 497 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
255 256 257 |
# File 'lib/basic_temperature/temperature.rb', line 255 def set_degrees(degrees) Temperature.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
270 271 272 |
# File 'lib/basic_temperature/temperature.rb', line 270 def set_scale(scale) Temperature.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
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 |
# File 'lib/basic_temperature/temperature.rb', line 317 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 Temperature.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
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 |
# File 'lib/basic_temperature/temperature.rb', line 349 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 Temperature.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
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 |
# File 'lib/basic_temperature/temperature.rb', line 381 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 Temperature.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
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 |
# File 'lib/basic_temperature/temperature.rb', line 413 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 Temperature.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
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 |
# File 'lib/basic_temperature/temperature.rb', line 286 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 |