Part 1: Ruby Introduction
This part of the lab will get everyone familiar with some Ruby basics and provides a review of other key concepts. This is a short introduction, but there are some 'on your own' exercises at the very end that students are strongly encouraged to try to solidify their understanding of Ruby.
-
We are going to begin by writing a simple program for Ruby to convert temperatures and then modify it several times. **Create a new folder named lab2 in your workspace[Mac/Windows/PaizaCloud], and you will save all your ruby files for this lab **. To begin, create a new file called temp_conversions.rb
using your preferred editor/IDE.
-
In this file, create a method called convert
that takes temp
as a parameter (temperature in Fahrenheit) and converts it to its equivalent in Celsius.
Run this code from the command line. Once this is running, set up a git repository and add this file to it.
- Add the test
puts convert("zero")
to the tests and rerun the code normally. Why did you get an error? To correct this, we will limit all temperatures to integers by adding a line before the calculation in our method:
return "Temperature must be an integer" unless temp.class == Integer
Rerun these tests after adding this line. If the tests pass, add the revision to the git repository.
- Add the test
puts convert(-500)
to the tests and rerun. Of course, remembering your basic physics leaves you distressed at this point because you know this answer is in error – Absolute Zero is at –474 degrees Fahrenheit or -270 degrees Celsius, making this result impossible. To make sure our program doesn't give silly answers, we will add another line after the last correction (and before the calculation):
return "Temperature below Absolute Zero" if temp < -474
Rerun the tests; assuming they pass, save the revision to the git repository.
- Of course, we have only half the temperature conversion problem – converting Fahrenheit to Celsius – and have no capability to convert Celsius to Fahrenheit. Create a new branch in git called
exp
. Now in your code, add another argument called measure
and using an if ... else ... end
construct, correct the code so that either a Fahrenheit or Celsius temperature is converted. Set up the measure
argument so its default value is "F". Add the test below:
puts convert(0, "C")
puts convert(10, "C")
puts convert(100, "C")
puts convert(-280, "C")
Rerun the code; if all tests pass, save to the repository.
- Looking at the results, we see that the code is still problematic: we get a result for –280 oC even though we know that value is below Absolute Zero. There are a number of ways to correct this, but for learning purposes here, we are going to create a new method called
below_absolute_zero?
which has two arguments: temp and measure. This method will simply return a boolean of true if the temperature for the measurement system is below the critical value; this is why this method will end in a question mark. Create the basic structure for this method now.
Back to the code: go to the convert method and change the if statement for the Absolute Zero condition so that it references this new method rather than the simple statement of temp < -474
. Rerun the code and make sure that everything is working properly. If so, save this code to the git repository. Checkout the master
branch, and then merge the exp
branch onto the master
branch.
Part 2: Interactive Ruby
-
We are going to switch gears now and start to interact with Ruby with irb [interactive ruby]. The irb prompt is a useful command line tool that can allow you to try out simple ruby constructs and methods.
-
Once in irb, type
a = Time.now
This gives us an object a with a Ruby timestamp. Now type in
require 'date'
b = Date.today
Compare this result with the results of the first command. What is the difference between these two objects? Be sure you are clear on the difference before proceeding.
-
Now type a.month
and note what is output is. Now type a.strftime("%B")
and note the output. How would you find the year of a
? (Guess ...) Try your idea in irb now.
-
Now type the command
a.month == b.month
What was returned? Type the command
a.day == b.day - 1
and see that result as well. As we noted earlier in the temp conversion method, Ruby is evaluating these statements as either true or false and returning the result.
-
Use the strftime
method to format the object a
in the format of 99/99/9999. To see the options with strftime
we can take advantage of a gem Prof. H uses sometimes in class: cheat. (To install this gem, run gem install cheat
in a terminal window that is not running irb; you can verify it is there by typing gem list | grep cheat
which simply pipes your list of gems to grep so it can search for any gems with 'cheat' in its name.) In that other terminal window/tab, type cheat strftime
and see the output returned – this should guide you in reformatting the timestamp. If you are having issues with this gem, you can also use an online reference strfti.me.
-
We are going to add three variables at once through multiple assignment (an option in Ruby). To do this, type into irb:
m1, d1, y1 = 04, 01, 2014
Now we will use these values to create a new timestamp in Ruby with the command:
c = Time.mktime(y1, m1, d1)
Now we have the timestamp for this year's April Fool's Day. Let's change it a little bit by typing d1 = 31
and rerunning the command: c = Time.mktime(y1, m1, d1)
. What did Ruby do with the date 04/31/2014?
You are technically done with this part of the lab. However, if you want to stretch yourself a bit and put this new Ruby knowledge to the test, then try the following: write a method called valid_date?
which takes year, month and day as arguments and returns true if the date is valid or false if not. Below are some test cases.
# Tests
valid_date?(2013, 1, 29) # => true
valid_date?(2013, 2, 28) # => true
valid_date?(2013, 2, 29) # => false
valid_date?(2014, 2, 29) # => false
valid_date?(2014, 9, 29) # => true
valid_date?(2014, 9, 31) # => false
valid_date?(2013, 12, 31) # => true
valid_date?(2013, 12, 32) # => false
valid_date?(2013, 13, 31) # => false
valid_date?("2014", "Jan", 31) # => false
Part 3: Ruby Blocks
In this part of the lab, you will work through block problems from a previous 67-272 exam. This section contains 4 problems, but you only need to complete the first 2 for full credit. However, you are encouraged to complete them all if time allows! They will be good practice for future exams and your projects.
In each problem, you will be given an expected output, and your task is to write a block that will generate this output. You can complete the problems in a separate file, and run it the same way as TempConverter.
- Add the following dictionaries to the top of your file, as these will be used in the problems.
cast = {bob_parr: :incredibles, helen_parr: :incredibles, lucius: :incredibles,
edna: :incredibles, woody: :toy_story, buzz: :toy_story, bopeep: :toy_story,
andy: :toy_story, merida: :brave, marlin: :finding_nemo, dory: :finding_nemo,
nemo: :finding_nemo, sulley: :monsters_inc, mike: :monsters_inc,
randall: :monsters_inc, sally: :cars, mcqueen: :cars, doc: :cars,
mater: :cars, jessie: :toy_story_3, big_baby: :toy_story_3}
toys = [:woody, :bopeep, :buzz, :jessie, :big_baby]
females = [:helen_parr, :edna, :bopeep, :dory, :sally, :jessie, :merida]
year_produced = {incredibles: 2004, toy_story: 1995, brave: 2012, finding_nemo: 2003, up: 2009, walle: 2008, monsters_inc: 2001, cars: 2006, bugs_life: 1998, toy_story_3: 2010}
- Create a block that prints out all the female toys in alphabetical order.
# EXPECTED OUTPUT:
bopeep
jessie
- Create a block that will print out a list of all the movies produced in the past 10 years.
# EXPECTED OUTPUT:
[:brave, :toy_story_3]
- Create a block that will print out a list of movies that have some cast members in the cast dictionary, arranged by year produced.
# EXPECTED OUTPUT:
Toy_story - 1995
Monsters_inc - 2001
Finding_nemo - 2003
Incredibles - 2004
Cars - 2006
Toy_story_3 - 2010
Brave - 2012
- Create a block that will print out a list of all movies in the year_produced dictionary in a user-friendly format (spacing and capitalization). Make sure they are in alphabetical order.
# EXPECTED OUTPUT:
Brave
Bugs Life
Cars
Finding Nemo
Incredibles
Monsters Inc
Toy Story
Toy Story 3
Up
Walle
Part 4: Classes and Objects
In this part, we want to build a micro-blogging platform Tweeter similar to Twitter. Users have a valid
account to be able to post tweets. A Tweet is 140 characters long text message that can contain hashtags
or referrers. A hashtag is a word that starts with the # character. A referrer is a word that starts with the
@ character and that refers to an existing ID of a Tweeter user. Users can see all the tweets posted by all
users.
1. The User Class
The User class is a structure that manages the characteristics of a given user.
Each user is identified with the following attributes:
-
id is the user's unique identifier in Tweeter (string).
-
firstname is the user's first name (string).
-
lastname is the user's last name (string).
-
password is the user's password (string).
1- Create the User class. In order to create a new user, one should provide the id, first name, last name, and password.
2- Write a class method get_full_name that returns a user's full name.
3- Write a class method check_password(p) that checks if a given password p matches the user's password. This method should return true if p matches the current user's password
2. The Tweet Class
The Tweet class is a structure that manages the characteristics of a given tweet.
Each tweet has:
- An owner: the user that published the tweet
- A message: a string representing the message of the tweet
1- Create and complete this class. Keep in mind that while creating a tweet the constructor (initialize method) should ensure that the message is 140 characters long. If the message given as input is longer, the message is truncated.
2- Write and test a class method get_hashtags that returns the list of hashtags conatined in the message.
3- Add a to_s method that returns a text representation of the tweet such as user name said message. For example:
Houda Bouamor said, "The next assignment in #cmuq67272 will be #easy"
or also
Ahmed Mohammad said, "Professor @HoudaBouamor has posted the latest #cmuq67272 lab"
3. The Tweeter Class
The Tweeter class is a structure that manages the characteristics of Tweeter.
Tweeter is defined by:
-
users: an array of users
-
tweets: an array of tweets
1- Create this class and define its initialize method. At first, there are no users no tweets.
2- Write and test a method signup(id, password, firstname, lastname) that creates
a new Tweeter user if the id is not already taken and returns true. It returns false otherwise.
3- Write and test a method signin(id, password) that returns the Tweeter user corresponding to the given Tweeter ID if and only if the password matches the one stored in the user's profile. It returns nil if either the user ID does not exist or if the password does not match.
4- Write and test a method add_tweet(user, message) that publishes a new tweet to Twitter.
5- Add the to_str method. It should return a text representation of the last 20 tweets only posted on Tweeter. Each Tweet should be separated by an empty line.