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
othertemperature. -
#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 |