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.
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.
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.
irb
on one of your laptops.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
(Challenge for pairs who finish early). What does the operation ^
do? E.g.
1 ^ 2
2 ^ 5
4 ^ 5
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.
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
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"
There are various different types of name in ruby:
age
: Local variables begin with a lower-case letter. They’re all we’ll be using for now.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.@name
: Instance variables start with a single @
sign. They’re used to store values inside objects. More later.@@count
: Class variables start with two @@
signs. They’re used to store values relevant to a set of objects. More on this later too.$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 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.
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
Consider the expression
x = (2 + 5*x - x**2)/5
x = 1.1
x = (2 + 5*x - x**2)/5
and then evaluate this multiple times (using the up arrow in irb)x = 1
and do the same thing. What happens and why?> 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.
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!
.
> 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!
Sinatra is a lightweight web framework written in ruby.
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
Install sinatra: at the command line run
$ gem install sinatra
$ gem install rack-test
Download the code for the session:
$ git clone https://github.com/code61/sinatra_c3s1.git
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
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:
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:
app.rb
.Ctrl-c
in the terminal, and then restart it using ruby app.rb
.Run the app. In the sinatra_c3s1
directory:
$ ruby app.rb
Check you can see the page in your webbrowser at localhost:4567.
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
).
Try visiting a different url (e.g. localhost:4567/about). What happens?
(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!
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
.
app.rb
in Sublime text and uncomment the code at the bottom.ruby test2.rb
in the console.test2.rb
to test your result.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!).
Before you deploy your app to heroku you need to create an account.
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.
Upload your ssh key to heroku by running
$ heroku keys:add