Introducing ruby

Ruby is a programming language. It is different to HTML and CSS, which are just markup languages: in ruby you can do calculations.

Ruby is an incredibly powerful and flexible language. It is a modern language - created in the 1990s by Yukihiro Matsumoto (Matz). A large part of his design philosophy is centered around optimizing for developer happiness - making a language that is a pleasure to program in. If you haven’t already programmed in another language, you might not fully appreciate this, but - take it from someone who has - ruby is awesome!

Ruby really shot to fame around 2005, due to the Ruby on Rails web framework. Ruby on Rails is a free, open-source web programming toolkit, which makes it really quick and easy to build web applications. Many top startups and sites (e.g. yellowpages.com, airbnb.com, github.com, gocardless.com, grouper.com) are built with ruby on rails - its rapid prototyping capabilities make it one of the go-to choices, especially for startups. The first version of Twitter was built in Ruby on Rails!

In this course, we’ll be leaning the basics of ruby, in a web development context. We won’t be using ruby on rails, instead focussing on a simpler framework (called sinatra), which will give you a better understanding of what’s going on behind the scenes and allow you to be far more productive with rails, when you come onto it later.

Iteractive ruby: irb

Ruby is an interpreted language. One of the great things about an interpreted language is that it’s often possible to interact with the interpreter in real time. When you installed ruby, you also got a program called irb (interactive ruby), which allows you to interpret ruby on the command line. To start it you just type irb on the command line.

001: > 2 + 2
 => 4 
002: > 

2 + 2 is a ruby expression. The => symbol tells you what value this expression evaluates to. The interpreter has converts expressions to values.

If you just type the value 4 into irb, you will see that it will return 4 to you.

001: > 4
 => 4 
002: > 

Like all values in ruby, 4 is also an expression - it just evaluates to itself.

So far you’ve only seen values that are numbers. We’ll come across some other values soon.

Comments

In ruby, any part of a line that comes after a # is ignored. This is useful when you’re writing complicated programs, as it allows you to write human-readable comments to document your code.

001: > 2 + 2  # add together 2 and 2
 => 4 
002: > # this does nothing
003: > 

Notice how in line 002 above there is no => and no return value; comments don’t evaluate to anything - they’re completely ignored.

Task:
  1. Pick a partner.
  2. Open irb on one of your laptops.
  3. For each of the following ruby expressions, try to agree what value you think they evaluate to. Check if you're right in irb.
1 + 2

5 - 6

8 * 9

6 / 2

5 / 2

5.0 / 2

5 % 2

2.even?

3.even?

"hello " + "world"

"Bob" * 3

"Bob" + 3

"don't shout".upcase

"edam".reverse
Task:
  1. (Challenge for pairs who finish early). What does the operation ^ do? E.g.

     1 ^ 2
    
     2 ^ 5
    
     4 ^ 5

Exercise summary

Before we will move on to variables, we’ll quickly look at a few of the things that you found out in the previous exercise:

> 6 / 2
=> 3
> 5 / 2
=> 2
> 5.0 / 2
=> 2.5
> 5 % 2
=> 1

If you give ruby integers (whole numbers), it will do integer division. For example, 5 / 2 gives 2 as it is the largest whole number of times you can remove 2 from 5. The partner to integer division is the remainder 5 % 2, giving 1. Together these two operations tell you that 2 goes twice into 5 with remainder 1. If you give ruby decimals it will do normal division. Everyone gets caught out by this at some point. You have been warned!

> 2.even?
=> true

The line above is actually pretty special. We’ve just asked the value 2 a question and it’s responded. In programming terms, this works because 2 is an object - something that contains both data and methods that can query/manipulate the data. In this case, even? is the method that we called. In ruby all values are objects. This is unusual and isn’t true in many other programming languages. We’ll leave it at that for the time being, but you’ll learn more about this later.

> "hello " + "world"
=> "hello world"
> "don't shout".upcase
=> "DON'T SHOUT"

Here you met another third type of value: "hello" is a string. As you see here, you can add strings together. Like all ruby values, strings are also objects and therefore have methods. Here we used the upcase method, to change the string into uppercase. You can find out more about the methods that strings have in the ruby docs.

> "Bob" + 3
TypeError: can't convert Fixnum into String
from (irb):1:in `+'

Oh dear! Turns out that you can’t add a string to an integer. Have another read of the message that irb gave you. Can you figure out what it is saying? When something goes wrong, ruby tries to be as helpful as it can. Learning to interpret the errors that ruby gives is an important part of learning to become a programmer.

The ^ operator in the optional challenge is bitwise exclusive or.

Names & Variables

So far we’ve used irb as a clever calculator, by working with values directly. Programming becomes a lot more powerful when you’re able to give values names.

A name is just something that you can use to refer to a value. In ruby you create a name by using the assignment operator, =.

age = 5
age 5

You can change the value associated with a name at any point. It doesn’t even have to be the same type of value as the first value assigned to the name. Here we change the value associated with age to a string:

age = "almost three"
age “almost three”

Types of name

There are various different types of name in ruby:

  • local variables e.g. age: Local variables begin with a lower-case letter. They’re all we’ll be using for now.
  • constants e.g. PI: Any name that starts with a capital letter is deemed to be a constant. Ruby will complain if you try to change its value at a later date.
  • instance variables e.g. @name: Instance variables start with a single @ sign. They’re used to store values inside objects. More later.
  • class variables e.g. @@count: Class variables start with two @@ signs. They’re used to store values relevant to a set of objects. More on this later too.
  • global variables e.g. $last_error: Global variables start with a $ sign. They’re available anywhere in your program. Relying on global variables is normally a bad idea.

For the moment, we will just be using local variables. The important thing to take from the above tables is that local variables must start with a lower-case letter.

String interpolation

String interpolation is a way of taking a variable and putting it inside a string.

To write a string in ruby you can either use ' or ".

string1 = 'hello'
string2 = "hello"

In the code above, string1 and string2 are exactly the same. The difference between ' and " is that " allows you to do string interpolation:

age = 5
age_description = "My age is #{age}."
=> "My age is 5."

Any ruby expression inside the #{ } will be evaluated and inserted into the string. Here we gave it the variable age, which points to the value 5. As 5 is a value it evaluates to itself, so 5 is inserted into the string.

Task:
  1. With your partner, decide what each of the following instructions will do. Test to see if you're right in irb.
a = 1

a

a+1

a

a = a + 1

a

b = "hello"

b

c = b.capitalize

b

c

d = "hello"

e = d.capitalize!

d

e

name = "Dave"

f = "Hello #{name}! "

f

name = "Sarah"

f

f * 5
Task:
  1. (Extension for pairs who finish early.)[Note: this exercise has a lot more to do with maths than programming. If you dont get it dont worry!]

    Consider the expression x = (2 + 5*x - x**2)/5

    1. Let x = 1.1
    2. Write x = (2 + 5*x - x**2)/5 and then evaluate this multiple times (using the up arrow in irb)
    3. What happens? Can you explain why?
    4. Let x = 1 and do the same thing. What happens and why?

Exercise summary

> x = 1
=> 1
> x = x + 1
=> 2

This might seem really obvious, but it’s worth pointing out: = is an assignment operator; it means ‘set name on the left equal to the value on the right’. It isn’t the same equals as you see in maths! In maths x = x + 1 doesn’t really make sense -it’s an equation with no (finite) solutions. In ruby x = x + 1 makes perfect sense - just set x to be one more than it was before.

b = "hello"
c = b.capitalize

b #=> "hello"
c #=> "Hello"

d = "hello" 
e = d.capitalize!

d #=> "Hello"
e #=> "Hello"

This example is pretty important. In the first case capitalize gives back “HELLO”, but leaves the original string untouched.

b “hello” c “Hello”

In the second case, we use the in-place version of captialize!. It changes the actual string that d is pointing to, and sets e to point there too. In ruby, methods often come in two flavours like this, with the ! version modifying the original object in place. You could also try out reverse/reverse! and upcase/upcase!.

d e “Hello”
> name = "Dave"
=> "Dave"
> f = "Hello #{name}! "
=> "Hello Dave! "
> f
=> "Hello Dave! "
> name = "Sarah"
=> "Sarah"
> f
=> "Hello Dave! "

The above shows that string interpolation happens when you write it down. When you first write f = "Hello #{name}! " ruby immediately looks up name and bakes it straight into the string. Setting name to something differeny later on, won’t change this.

In the extra challenge, the expression gave an iterative approximation to sqrt(2). You can tell by rearranging and solving the equation, that any fixed point must be a sqrt of 2. In the final part, by giving it x=1 you forced ruby to do integer arithmetic. If you're into that sort of thing, you might like to try and find the fixed points in this case!

Introducing sinatra

Sinatra is a lightweight web framework written in ruby.

Getting sinatra

You can install sinatra on your laptop using rubygems - ruby’s excellent package manager. When people write their own ruby libraries, they usually release them as a gem, so that others can quickly and easily install them. Sinatra is one of these libraries. To install it do:

$ gem install sinatra

at the command line. We will also need a few other rubygems, so install these too:

$ gem install rack-test
Task:
  1. Install sinatra: at the command line run

     $ gem install sinatra
     $ gem install rack-test
  2. Download the code for the session:

     $ git clone https://github.com/code61/sinatra_c3s1.git

A simple ruby application

So far, we’ve only used ruby in irb. If we’re going to write ruby applications, we need to go beyond this. In this section, we’re going to have some code written in a file (a .rb file) and we’re going to run the whole file through the interpreter, using the ruby command.

We’re now going to look at a very simple ruby web application that uses sinatra.

# in app.rb:

require 'sinatra'

get '/' do
    "hello"
end

This file is very simple. The first line imports the sinatra library - this is what does most of the work here. The next bit tells sinatra how to respond to a certain type of request. In particular it says that if it receives a GET request to the root url it should send back the text “hello”.

To run this app you need to run the app.rb file using ruby.

$ cd sinatra_c3s1
$ ruby app.rb
== Sinatra/1.3.3 has taken the stage on 4567 for development with backup from Thin
>> Thin web server (v1.3.1 codename Triple Espresso)
>> Maximum connections set to 1024
>> Listening on 0.0.0.0:4567, CTRL+C to stop

Sinatra has started a webserver on your computer, which you can view in your browser. It will be displayed at the IP address 0.0.0.0 on port 4567. 0.0.0.0 always points to the machine you are currently using. Another way of saying this is to use the word localhost. You will be able to view the site by typing one of the following into your browser address bar:

  • 0.0.0.0:4567
  • localhost:4567

Changing the app

What just happened involved quite a lot of magic. Because of the line require sinatra, when you ran the file through ruby, the following happened:

  1. Sinatra started a webserver on your computer.
  2. It used the code in your file to tell the webserver how to respond to a certain type of request.
  3. The webserver sat on your computer, waiting for you to send it a request from your browser.

Right now, you don’t really need to understand how all this works. You just need to be able to understand the general overview and how to change certain bits.

We’re now going to change part of the app, so that the webserver says something different.

There are two steps to this:

  1. Make a change in app.rb.
  2. Restart the server, so it knows about the change you made. To do this, you need to first kill the server, using Ctrl-c in the terminal, and then restart it using ruby app.rb.
Task:
  1. Run the app. In the sinatra_c3s1 directory:

     $ ruby app.rb

    Check you can see the page in your webbrowser at localhost:4567.

  2. Make a change to app.rb so that it instead says "Hello there!". Check you can see the change in your browser (you will have to stop the server with Crtl-C then restart it again with ruby app.rb).

  3. Try visiting a different url (e.g. localhost:4567/about). What happens?

  4. (Extension for those who finish early.) Have a look in the file test1.rb. What do you think the test_default at the end of the file does? Try running the test file from the command line:

     $ ruby test1.rb

    If the test passes, change the code back to see what happens when it fails. If it fails, try and make it pass!

Basic app

Taking parameters from the url

Take a look at the following code:

# in app.rb:

require 'sinatra'

get '/' do
    "hello"
end

get '/:name' do
    name = params[:name]
    name
end

The /:name is a URL matcher. It will match / followed by any word, for example /tom, /gertrude or /this_isnt_a_name. Sinatra will make this value available in something called the ‘params hash’. You don’t need to worry about this at the moment. The first line of the block, pulls the value out of the params hash and sets it to the local variable name.

Task:
  1. Open app.rb in Sublime text and uncomment the code at the bottom.
  2. Change it so that visiting localhost:4567/tom shows "Hello Tom!" in the browser (and similarly for other names). [You will need to use string interpolation and a string method.]
  3. (Extension.) Check your result by running ruby test2.rb in the console.
  4. See if you can make it so that localhost:4567/tom/bye shows "Goodbye Tom" in the browser (and similarly for other names).
  5. (Extension - hard.) See if you can write another test in test2.rb to test your result.

Homework

Task:
  1. Finish the exercises from class.
  2. Do the Codecademy Ruby track Sections 1 and 2.
  3. Get a Heroku account and upload an ssh key (see below).

About Heroku

Heroku is a cloud-based web hosting solution, specifically designed for hosting web applications. It started out as a Rails host, but has since branched out into other frameworks (e.g. Sinatra, Node.js) and languages (e.g. Java, Python).

They aim to completely manage your apps online infrastructure: you provide them with the code, they set it up and run it online. If you have a lot of users and want to scale your app up, they make it easy to allocate more resources so you can handle the increased traffic (for a price!).

Setting up an account

Before you deploy your app to heroku you need to create an account.

Task:
  1. Sign up for an account at Heroku.
  2. After you log in, download and install the heroku toolbelt. (This will allow you to interact with heroku from the command line).

 Setting up ssh with heroku

The final part of the set up is to upload your ssh keys to Heroku. You might remember about ssh keys from the initial installation instructions: they’re basically a way of identifying yourself to a server without typing in your password each time.

The heroku toolbelt makes this very easy. On the command line (in any folder) type:

$ heroku keys:add

You can check it worked by typing:

$ heroku keys

It should list the ssh key that you just added.

Task:

Upload your ssh key to heroku by running

$ heroku keys:add