Welcome to
Ladies Learning Code
In partnership with
In partnership with
Content created by Dessy Deskalov
Ruby is a programming language.
Wait ... what's a programming language?
Let's backtrack a bit.
There are two things you should know about your computer.
This is how your computer wishes you could speak to it:
A programming language is a language that is relatively easy for you to learn, but can also be understood by the computer.
It's the middle ground between English and the language that the computer understands.
Your computer can only do what you tell it to if you give it exact instructions.
Suppose you had to teach a person how to make a peanut butter sandwich. You might give the person an easy to follow recipe.
1. Toast two slices of bread
2. Spread peanut butter on one slice of bread
3. Spread jam on the other slice of bread
4. Put the two pieces of bread together
5. Put the sandwich on a plate and serve it
We left out some parts of the process, but a person could figure out:
Where to find the ingredients
To use a butter knife to spread the peanut butter
To put the bread in a toaster in order to toast it
etc, etc, etc (there are many little steps)
This same recipe for a computer would be much, much longer.
What is bread?
Where is it found?
How do I open the bag?
What is a slice?
How do I slice the bread?
How do I "toast"?
What is a toaster?
How do I use a toaster?
etc, etc, etc
What is peanut butter?
How do I "spread" peanut butter?
What is a butter knife?
Where is it found?
How do I open the knife drawer?
Which slice do I spread it on?
How much peanut butter do I spread?
etc, etc, etc
A programming language makes it easier for you to give the computer instructions.
It's made up of simple elements, that when combined together, are used to write a set of instructions that the computer then breaks down and interprets as its own language.
Programming is writing out exact instructions that your computer can follow to do things.
Created in 1993 by Yukihiro Matsumoto, from Japan.
"I hope to see Ruby help every programmer in the world to be productive, and to enjoy programming, and to be happy. That is the primary purpose of the Ruby language."
Ruby is fun, it's easy to learn, and the syntax is very forgiving.
This is some code in Java:
class Person { private String name, int age; public void setName(String name) { this.name = name; } public String getName() { return name; } public void setAge(int age) { this.age = age; } public String getAge() { return age; } }
The equivalent code in Ruby looks like this:
class Person attr_accessor :name, :age end
Ruby is an interpreter.
Ruby understands the Ruby language and translates it into computer language.
We can give Ruby instructions with files or with IRB (Interactive Ruby).
IRB is like text messaging with Ruby.
You'll ask Ruby to do something, and she will respond.
OS X
Applications -> Utilities -> Terminal
Windows (C:\windows\system32\cmd.exe)
Start -> All Programs -> Accessories -> Command Prompt
irb
ruby-1.9.2-p290 :001 >
Let's ask Ruby to do something.
Ruby can do math, and she can do it much quicker than a person can.
> 1 + 1
=> 2
> 462 * 86
=> 39732
Ruby knows the difference between a number and a word...
> 1 + 2 + 3
=> 6
> "ladies" + "learning" + "code"
=> "ladieslearningcode"
...and can perform operations on them, too!
> "ladies learning code".reverse
=> "edoc gninrael seidal"
> "ladies learning code".upcase
=> "LADIES LEARNING CODE"
What if we don't want to type "ladies learning code" each time we want to use it?
We can use variables to store things for later use.
> llc = "ladieslearningcode"
=> "ladieslearningcode"
You've just assigned the String "ladieslearningcode to the variable llc.
A programmer would say that the variable llc points to the object "ladieslearningcode".
You told Ruby the variable llc points to the string "ladieslearningcode".
Ruby files "ladieslearningcode" away under llc.
Next time you want the string "ladieslearningcode", you just tell Ruby to use the value of llc.
A variable is called just that because the object it points to can change.
> llc = "a lady learning code"
=> "a lady learning code"
Now let's ask for the value of llc.
> llc
=> "a lady learning code"
Let's try some more
> llc = 99
=> 99
Let's ask for the value of llc once again.
> llc
=> 99
Let's introduce another variable.
> copy_cat = llc
=> 99
Let's ask for the value of each variable.
> llc
=> 99
> copy_cat
=> 99
Now set llc back to "ladieslearningcode"
> llc = "ladieslearningcode"
=> "ladieslearningcode"
Numbers without decimals are called INTEGERS. We just did some math with some integers.
Letters, words, and sentences are called STRINGS. We tell Ruby that we are intending to use a string by wrapping it in quotes.
Everything in Ruby is an Object.
Great, but what is an object?An OBJECT is an INSTANCE of a CLASS.
A what is a what of a what?Before she can do something with an object, Ruby needs to know what kind of object she's dealing with.
Why?
Toasting bread is not the same as toasting a marshmallow.
So how do classes help?
Classes define objects and what can be done with them.
The bread class will have different instructions for "toast" than the marshmallow class.
Objects have an IS A relationship with their classes.
We have already looked at 2 classes in Ruby: Integer and String
The number 1 IS AN Integer.
The word "ladies" IS A String.
1 and "ladies" are Objects.
Hint: Remember, an Object IS A instance of a Class!
Object | Class |
3 | Integer |
"3" | String |
London | City |
Jack of Spades | Playing Card |
Donald Duck | Duck |
Daisy Duck | Duck |
The Hobbit | Book/Movie |
Ruby uses what she knows about an object to perform actions on it.
When you give Ruby a set of instructions, she asks the following:
If she knows how to perform the action on the object, she does it. If she doesn't, you'll get an error.
The actions you can perform on an object are called methods.
Every object that IS A class can perform the methods defined by that class.
The Integer class has instructions for the methods next, odd?, and even?.
You can call next, odd?, and even? on ALL Objects that are Integers
The String class has instructions for the methods capitalize, upcase, and reverse.
You can call capitalize, upcase, and reverse on ALL Objects that are Strings.
Let's walk through some examples from Ruby's perspective
>counter = 0
>counter.next
What am I supposed to do with this object? | next |
Do I know how to do that action with this object? | Yes! The Integer class defines a method next and returns the next number. |
=>1
> 99.zero?
=> false
> 99.odd?
=> true
> 99.even?
=> false
>title = "Peter Rabbit"
>title.reverse
What am I supposed to do with this object? | reverse |
Do I know how to do that action on this object? | Yes! The String class defines a method reverse and returns the string in reverse order. |
=>"tibbaR reteP"
> "ladieslearningcode".capitalize
=> "Ladieslearningcode"
> "ladieslearningcode".upcase
=> "LADIESLEARNINGCODE"
> "LADIESLEARNINGCODE".downcase
=> "ladieslearningcode"
> "ladieslearningcode".reverse
=> "edocgninraelseidal"
>myNumber = 123
>myNumber.reverse
What am I supposed to do with this object? | reverse |
Do I know how to do that action on this object? | No. The Integer class does not define a method reverse. |
=>NoMethodError: undefined method `reverse' for 123:Fixnum from (irb):1 from :0
How can I find the class of my object?
> mysteryObject = "What am I?"
> mysteryObject.class
=> String
How do I know what methods I can call on my object?
> mysteryObject.methods
=> ["upcase!", "zip", "pretty_print_cycle"....]
How do I know what those methods do?
http://ruby-doc.org/Ruby comes with many built-in classes that we can use.
String, Integer, File, Hash, Array...
You can read about all the built-in objects here
What about City and Playing Card and Duck?
We won't do it today, but you can make your own classes and objects! Here's a teaser for you to start exploring on your own
class Duck attr_accessor :name def quack puts "Quack, quack!" end end
> donald = Duck.new
donald.name = "Donald Fauntleroy Duck"
donald.quack
=> "Quack, quack!"
> llc = "ladieslearningcode"
> llc.reverse
=> "edocgninraelseidal"
Try asking for the value of llc now.
> llc
=> "ladieslearningcode"
llc is still pointing to "ladieslearningcode". You didn't tell it to point to a different string.
If you want the value to change, you have to set it to something else.
> llc = llc.reverse
=> "edocgninraelseidal"
> llc
=> "edocgninraelseidal"
If you want the value of a variable to change, you have to explicitly tell it to change.
> llc.length
=> 18
You're probably starting to get a sense of how Twitter knows how many characters you've typed in.
> tweet = "I'm writing my first program at the @learningcode
Intro to Ruby workshop!"
=> "I'm writing my first program at the @learningcode
Intro to Ruby workshop!"
> tweet.length
=> 73
We now know enough to write a program.
Open any text editor, add the same code, and save it as twitter.rb in your llc directory.
tweet = "I'm writing my first program at the @learningcode
Intro to Ruby workshop!"
tweet.length
To run your program, type quit to exit from IRB, and then type:
ruby twitter.rb
Wait, what? Why didn't it show me the length of my string?
IRB is like back-and-forth text messaging.
A program has to be told when to output something
Modify your program:
tweet = "I'm writing my first program at the @learningcode
Intro to Ruby workshop!"
puts tweet.length
Integer
String
Class
Object
Method
Variable
Open puzzle_1.rb in the puzzles folder, and write down the output you expect to see if you were to run this script.
If you're not sure of something, remember that you can type irb again and try it out.
The real Twitter...
Asks you to type something.
Tells you how many characters you're working with.
So far, we've just been putting our tweet directly into the program.
The puts method is used for output, and the gets method is used for input. Try this:
The gets method warns Ruby that you're about to speak.
> tweet = gets
I'm learning Ruby with #ladieslearningcode
=> "I'm learning Ruby with #ladieslearningcode\n"
Wait, we didn't type \n in our tweet. What is that?
The \n is there because you hit the enter button after you typed your tweet. It represents a new line, and counts as exactly one character. To get rid of it, do this:
> tweet = gets.chomp
I'm learning Ruby with #ladieslearningcode
=> "I'm learning Ruby with #ladieslearningcode"
Now try this:
> tweet = gets.chomp
I'm a lady learning code with @learningcode #ladieslearningcode
=> "I'm a lady learning code with @learningcode #ladieslearningcode"
> puts tweet
I'm a lady learning code with @learningcode #ladieslearningcode
=> nil
You asked Ruby to output your tweet, and Ruby did just that.
Remember that in IRB, Ruby always responds to your message. This time, it gave the output, and had nothing else to say, so it returned nil.
nil is also an Object, and it just represents nothing.
Working with your group, modify your Twitter program to do the following:
1. Ask (politely!) for a tweet from the user.
2. Store the tweet in a variable, without \n
3. Output the tweet the user gave.
4. Output the number of characters in the tweet.
5. Output how many more characters the user can add until they hit 140 characters.
(answers in assignments/twitter_3.rb)
Twitter...
Lets you send your tweet if it is 140 characters or less
Tells you that your tweet is too long to send otherwise.
So far we know how to determine the length of the user's tweet.
We don't know how to tell them whether they can or cannot send their tweet, depending on it's length.
Programming is writing out sets of simple instructions for the computer to follow.
Let's break down out tweet logic into simple instructions.
We want our program to ...
if the tweet is greater than 140 characters, tell the user that they cannot send their tweet
if the tweet is less than or equal to 140 characters, tell the user that they can send their tweet
The math symbol for greater than is >
Try the code below in IRB:
> 200 > 140
=> true
Now try:
> number_of_characters = 200
=> 200
> number_of_characters > 140
=> true
Now try:
> number_of_characters = 80
=> 80
> number_of_characters > 140
=> false
The math symbol for less than is <
Try the code below in irb
> llc = "ladieslearningcode"
=> "ladieslearningcode"
> llc.length < 140
=> true
Let's simplify our if statements.
Remember that we're storing the user's tweet in the variable tweet.
Original if statements:
if the tweet is greater than 140 characters, tell the user that they cannot send their tweet
if the tweet is less than 140 characters, tell the user that they can send their tweet
if tweet.length > 140 puts "Your tweet is too long!"
if tweet.length < 140 puts "Tweet your heart out!"
Replace the puts statements in your Twitter program with the code below. (see assignments/twitter_4.rb if needed)
if tweet.length > 140
puts "Your tweet is too long!"
end
if tweet.length < 140
puts "Tweet your heart out!"
end
Using the tweets from tweets.txt, try out your new script! What's the problem here? What do you notice happened when using the tweets in tweets.txt?
We're not actually taking into account all possible tweet lengths.
Programming problems can be solved many different ways.
We'll look at three different solutions.
Since we're only missing one case, the case where the tweet is exactly 140 characters, we can just add another if statement.
Add this last if statement to the bottom of your file: (see assignments/twitter_5.rb if needed)
if tweet.length == 140
puts "Tweet your heart out!"
end
The == operator checks that the value of the objects on either side of it are equal.
Programmers are always refactoring (re-structuring, re-organizing) their code to make it cleaner and more readable. Right now is a great time to do that.
Three if statements are unnecessary. We can actually combine all of these if statements into one, like so:
if tweet.length > 140
puts "Your tweet is too long!"
elsif tweet.length < 140
puts "Tweet your heart out!"
elsif tweet.length == 140
puts "Tweet your heart out!"
end
(see assignments/twitter_6.rb if needed)
if tweet.length > 140
puts "Your tweet is too long!"
elsif tweet.length < 140
puts "Tweet your heart out!"
elsif tweet.length == 140
puts "Tweet your heart out!"
end
In the above code, if the first statement doesn't evaluate to true, then the next one is attempted, and so on.
if tweet.length > 140
puts "Your tweet is too long!"
elsif tweet.length < 140
puts "Tweet your heart out!"
elsif tweet.length == 140
puts "Tweet your heart out!"
end
Only one puts statement is ever executed. The statements are evaluated in the order they are written, so the first one to evaluate to true is the only one executed.
if tweet.length > 140
puts "Your tweet is too long!"
elsif tweet.length < 140
puts "Tweet your heart out!"
elsif tweet.length == 140
puts "Tweet your heart out!"
end
If none of the statements evaluate to true, then none of the puts statements are executed.
Notice that the line puts "Tweet your hear out!" is unnecessarily repeated?
Let's cut it out by replacing the entire if statement with the code below:
if tweet.length > 140
puts "Your tweet is too long!"
elsif tweet.length <= 140
puts "Tweet your heart out!"
end
(see assignments/twitter_7.rb if needed)
The <= operator checks for equality as well.
Checking for equality with greater than works exactly the same way, using the >= operator.
This is better, but look at the logic closely. Do we really even need to specify the second condition?
Replace your code again with the code below:
if tweet.length > 140
puts "Your tweet is too long!"
else
puts "Tweet your heart out!"
end
(see assignments/twitter_8.rb if needed)
if tweet.length > 140
puts "Your tweet is too long!"
else
puts "Tweet your heart out!"
end
Just like with if .. elsif, only one puts statement is ever executed. The difference here is that one of the puts statements is always executed.
if tweet.length > 140
puts "Your tweet is too long!"
else
puts "Tweet your heart out!"
end
The else is there are a catch-all. You can think of it like a last resort. If none of the other options are true, then just execute the puts statement after the else.
Operator | True | False |
== | 99 == 99 | 99 == 100 |
!= | 99 != 100 | 99 != 99 |
> | 100 > 99 | 99 > 100 |
< | 99 < 100 | 100 < 99 |
>= | 99 >= 99 | 99 >= 100 |
<= | 99 <= 99 | 100 <= 99 |
puts
gets
if .. elsif
if .. elsif .. else
if .. else
Look at the program in puzzle_2.rb.
The program asks the user for the month of their birthday, and then outputs a message about the season the user celebrates their birthday in.
Which months does this program consider to be spring, summer, winter, and fall?
Simplify the logic to make the program as few lines of code as possible?
Goal: 20 lines!
What if you want to be able to tell your program when to stop running? Create a new program with the following code, or run the program in assignments/loop_1.rb:
puts "Hi!" greeting = gets.chomp while greeting != "bye!" puts greeting greeting = gets.chomp end
This is called a while loop. The program will run while the user inputs anything other than "bye!"
Again, there are several ways to do this.
Create a new program with the following code, or use run the program in assignments/loop_2.rb:
3.times do puts "Hip-Hop-Hooray!" sleep 1 end
This program will output "Hip-Hip-Hooray!" exactly 3 times.
3.times do puts "Hip-Hop-Hooray!" sleep 1 end
The sleep 1 tells the program to wait 1 second after outputting each statement.
Try taking it out to see what happens. Not as exciting.
Create a new program with the following code, or use run the program in assignments/loop_3.rb:
puts "Okay, on the count of 5 ..." [1, 2, 3, 4, 5].each do |i| puts i sleep 1 end puts "GO!"
puts "Okay, on the count of 5 ..." [1, 2, 3, 4, 5].each do |i| puts i sleep 1 end puts "GO!"
This program loops through each Integer from 1 to 5, and outputs the Integer, again sleeping for 1 second in between.
Maybe we want a program that simulates a countdown.
Create a new program with the following code, or use run the program in assignments/loop_4.rb:
99.downto(1).each do |i| puts "#{i} bottles of beer on the wall, #{i} bottles of beer. Take one down, pass it around, and now there are #{i - 1} bottles of beer on the wall!" sleep 0.5 end
99.downto(1).each do |i| puts "#{i} bottles of beer on the wall, #{i} bottles of beer. Take one down, pass it around, and now there are #{i - 1} bottles of beer on the wall!" sleep 0.5 end
This program moves through each Integer from 99 down to 1, and outputs the Integer, this time sleeping for half a second in between.
Wait a second, how did we get an Integer in that String?
puts "#{i} bottles of beer on the wall, #{i} bottles of beer. Take one down, pass it around, and now there are #{i - 1} bottles of beer on the wall!"
You can use the syntax #{my_variable} inside of the String, and Ruby will treat the variable exactly like a String.
> lesson = "Ruby"
=> "Ruby"
> tweet = "I am learning all about #{lesson} at the
#ladieslearningcode workshop"
=> "I am learning all about Ruby at the
#ladieslearningcode workshop"
> lesson = "String Interpolation"
=> "String Interpolation"
> tweet = "I am learning all about #{lesson} at the
#ladieslearningcode workshop"
=> "I am learning all about String Interpolation at the
#ladieslearningcode workshop"
Create a new program with the following code, or use run the program in assignments/loop_5.rb:
puts "And the lucky numbers are ..." [7, 13, 14, 16, 14, 48].each do |i| puts i sleep 1 end puts "With a bonus number 32!"
What if we want to be able to leave a loop early, before we have finished looping?
We need a way to tell Ruby to stop looping. We do that using the command break.
break tells the loop to stop where it is.
Create a new program with the following code, or run the program in assignments/loop_6.rb:
puts "Time to play Blackjack! Let's simulate a losing game." sum = 0 [2, 4, 10, 9, 3].each do |card| sleep 1 puts "Dealing a card with value #{card}" sum = sum + card if sum > 21 puts "You lost!" break else puts "Hit me!" end end
Every time you were looping, regardless or whether you were counting using [1, 2, 3, 4, 5], or just looping over [7, 13, 14, 16, 14, 48], you were using arrays.
An array is simply a collection of objects. Loops are used to move from one element of an array to another.
Back in IRB, let's create an array of winning lottery numbers and store it in the variable lottery.
> lottery = [7, 13, 14, 16, 14, 48]
=> [7, 13, 14, 16, 14, 48]
> lottery.join(', ')
=> "7, 13, 14, 16, 14, 48"
> lottery
=> [7, 13, 14, 16, 14, 48]
> lottery[0]
=> 7
> lottery[1]
=> 13
> lottery[6]
=> nil
> lottery.uniq
=> [7, 13, 14, 16, 48]
> lottery
=> [7, 13, 14, 16, 14, 48]
> lottery.delete_at(0)
=> 7
> lottery
=> [13, 14, 16, 14, 48]
> lottery << 92
=> [13, 14, 16, 14, 48, 92]
> lottery
=> [13, 14, 16, 14, 48, 92]
What will be the output of puzzle 3?
Remember to think about which methods modify the array, and which do not.
Ruby became popular mostly because of Rails.
Ruby on Rails is a framework.
GREAT.
What's a framework?
Imagine you're building a house.
Many people before you have built houses.
Why do the boring work?
Rails gives you the foundation, the plumbing, the electrical work, and the structural walls.
Rails was extracted from work done on Basecamp at 37signals. (2004)
Let's write a program from scratch.
For the biggest challenge:
Create a new document called colours.rb and write the program from scratch.
For a little bit of guidance:
Open the file colours.rb in the assignments folder.
Answers can be found in assignments/answers/colours.rb
Write a program that does the following:
1. Loops through an array of the colours red, green, blue, and yellow.
2. For each colour, asks the user if it is their favourite.
3. If the user types yes, then a variable called favourite_colour is set to that colour.
4. If the user types anything else, the loop continues.
5. Once the loop is complete, if the user said yes to a colour, the program outputs their favourite colour to them. If the user did not say yes to any of the colours, it tells them that their favourite colour is not red, green, blue, or yellow.
Let's write something more complicated from scratch.
For the biggest challenge:
Create a new document called blackjack.rb and write the program from scratch.
For a little bit of guidance:
Open the file blackjack.rb in the assignments folder.
Answers can be found in assignments/answers/blackjack.rb
We're going to create a Blackjack game with some simplified rules.
At the start of the game, the player and the dealer each get 2 cards.
The player is told the sum of their two cards, and then has the opportunity to type h if they want to hit, or anything else if they want to stand.
The player continues to receive cards, and their sum continues to go up, until:
1. They no longer want to hit.
2. Their sum exceeds 21, in which case they lose.
3. Their sum amounts to exactly 21, in which case they win.
The player is told their current sum before every opportunity to hit.
If the player manages to make it through the hitting cycle without winning or losing, the dealer receives cards until their sum is greater than or equal to 17.
The sum of the player's cards and the sum of the dealer's cards are compared.
If the dealer's sum is greater than 21, then the player wins.
Otherwise if the player's sum is greater than the dealer's sum, then the player wins.
Otherwise if the player's sum is equal to the dealer's sum, then there is a tie.
In all other cases, the player loses.
Inspired by Chris Pine's Learn to Program
And finally...
Big, big thank you to
Startup Edmonton
for hosting us in their space!