Skip to content

Instantly share code, notes, and snippets.

@nakajima
Forked from NYiPhoneDeveloper/gist:114328
Created May 19, 2009 20:03
Show Gist options
  • Save nakajima/114350 to your computer and use it in GitHub Desktop.
Save nakajima/114350 to your computer and use it in GitHub Desktop.
A simple, test-driven, object-oriented approach to converting Celsius to
Fahrenheit and vice-versa, hopefully it's simple enough to be useful for a
newcomer to programming.
# Converts temperatures
class Temperature
class NoUnitError < StandardError; end
class NoDegreesError < StandardError; end
# Store the input in an instance variable and checks its validity
def initialize(string)
@string = string.downcase
raise NoUnitError.new unless unit
raise NoDegreesError.new unless degrees
end
# Parse the degrees using a regular expression and String#match:
# http://ruby-doc.org/core/classes/String.html#M000793
def degrees
if match = @string.match(/\d+/)
match[0].to_i
else
nil
end
end
# Parse the unit from the string, or returns nil.
def unit
case
when @string.include?('f') then 'Fahrenheit'
when @string.include?('c') then 'Celsius'
else nil # This line is redundant, but it's good to be explicit
end
end
# Converts Celsius values to Fahrenheit, or returns the same value if
# already Fahrenheit
def to_fahrenheit
if unit == 'Fahrenheit'
degrees
else
(9.0 / 5.0) * degrees + 32
end
end
# Converts Fahrenheit value to Celsius, or returns the same value if
# already Celsius
def to_celsius
if unit == 'Celsius'
degrees
else
(5.0 / 9.0 * (degrees - 32.0))
end
end
end
# Runs the program.
if __FILE__ == $0
print "Enter a temperature. (example: 32C or 43F): "
begin
temperature = Temperature.new($stdin.gets.chomp)
rescue Temperature::NoDegreesError
puts "You didn't the degrees value."
exit 1 # Exits with an error status code
rescue Temperature::NoUnitError
puts "You didn't enter a valid unit (F or C)"
exit 1 # Exits with an error status code
end
puts "Celsius: #{temperature.to_celsius}"
puts "Fahrenheit: #{temperature.to_fahrenheit}"
end
require 'gistfile1'
require 'test/unit'
# Create a class to hold our test methods
class TemperatureTest < Test::Unit::TestCase
# This is sort of advanced, but I wanted a prettier way of defining tests.
def self.test(name, &blk)
define_method("test " + name, &blk)
end
test "parsing degrees" do
temperature = Temperature.new('32f')
assert_equal 32, temperature.degrees
end
test "parsing units" do
assert_equal 'Celsius', Temperature.new('32C').unit
assert_equal 'Fahrenheit', Temperature.new('32F').unit
end
test "raises NoDegreesError when no degrees specified" do
assert_raise Temperature::NoDegreesError do
Temperature.new('C')
end
end
test "raises NoUnitError when no unit specified" do
assert_raise Temperature::NoUnitError do
Temperature.new('32')
end
end
test "Fahrenheit to Fahrenheit is same" do
assert_equal 32, Temperature.new('32F').to_fahrenheit
end
test "Celsius to Fahrenheit converts degrees" do
temp = 100
correct_result = (9.0 / 5.0) * temp + 32
assert_equal correct_result, Temperature.new('100C').to_fahrenheit
end
test "Celsius to Celsius is same" do
assert_equal 100, Temperature.new('100C').to_celsius
end
test "Fahrenheit to Celsius converts degrees" do
temp = 100
correct_result = (5.0 / 9.0 * (temp - 32.0))
assert_equal correct_result, Temperature.new('100F').to_celsius
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment