So far we’ve just used ruby to evaluate simple expressions. Coding becomes a lot more interesting when you can use your code for simple logic tasks:
if age >= 18
"Here's the vodka you wanted."
else
"Move along please."
end
The code within the if
block will only be run if the statement is true. If the statement is false, the code in the else
block will be run instead.
There are some basic comparisons that will be useful when using if statments
Symbol | Meaning |
---|---|
== | Is equal to |
> | Greater than |
< | Less than |
>= | Greater than or equal to |
<= | Less than or equal to |
!= | Not equal to |
Comparisons evaluate to true
or false
.
Working with a partner, try out each of these comparisons in irb:
4 == 5
'five'.length > 5
a = 20
a <= 20
true >= false
'aardvark' < 'anteater'
'we' != 'done yet'
Last time we looked at responding to get
requests:
get '/' do
"Hello there!"
end
As you know from the Introduction to Web Programming course, GET
is only one of several types of web requests. Another is the POST
request, which is commonly used for submitting data from a web form.
Suppose we have the following HTML form:
<form method="post" action='/'>
<input type='text' name='user_name'>
<input type='text' name='user_age'>
<input type='submit'>
</form>
The form will submit via a POST
request to the root url, /
. We can respond to this using the following sinatra block:
post '/' do
name = params[:user_name]
age = params[:user_age]
"Hello #{name}. You are #{age} years old."
end
Note that, like the words matched in the url, the value of the user_name
field is made available in the params
hash. (If you want to have a look at the params hash you could put a raise params.inspect
at the beginning of the method.)
sinatra_c3s2
project in Sublime Text and have a read through app.rb
. See if you can predict what the app will do.ruby app.rb
), to see if you were right.raise params.inspect
right at the top of the post block. Restart the app and see what happens. When you've had a look, make sure you remove the line again!We’re now going to look at how to get the Sinatra app online, a process known as deployment. We’re going to deploy the app to Heroku, which offers easy hosting for a variety of web frameworks - all you need to do is push up a git repository, and they take care of everything else!
You should have set up a heroku account and uploaded your ssh keys for homework.
There are a few files sinatra_c3s2
that we need if we’re going to deploy the app to heroku:
config.ru
contains the lines
require './app.rb'
run Sinatra::Application
These lines are to tell Heroku which file to find your application (app.rb
) and how to run it (using Sinatra).
The Gemfile
is a way of specifying which gems your project uses. Heroku needs to know this so it knows which libraries it needs to run your app. The Gemfile
is also really helpful way of remembering yourself which gems you need and is invaluable when working with others.
# Gemfile
source 'https://rubygems.org'
gem 'sinatra'
Along with rubygems, ruby has a tool called bundler. Bundler helps you manage your ruby gems. If you run bundle install
it will look in the Gemfile
and install any gems that you don’t already have.
$ bundle install
will also create a Gemfile.lock
which specifies the exact version of the gems (e.g. the sinatra library) that you are using. This means that heroku (and anyone else you’re collaborating with using git) now knows exactly which gems you are using and can pick to use the same versions. You need to check this in to your repository:
$ git add --all
$ git commit -m "Added Gemfile.lock"
Once your app is prepared, the first thing you need to do is create a new empty heroku application. To do this you use the heroku create
command:
$ heroku create
Creating arcane-gorge-2129... done, stack is cedar
http://arcane-gorge-2129.herokuapp.com/ | git@heroku.com:arcane-gorge-2129.git
Git remote heroku added
You’ll see that it created an app for you. In my case the app is called arcane-gorge-2129
and can be found at http://arcane-gorge-2129.herokuapp.com. It also added a git remote for you.
$ git remote -v
heroku git@heroku.com:arcane-gorge-2129.git (fetch)
heroku git@heroku.com:arcane-gorge-2129.git (push)
origin git@github.com:code61/sinatra_project_1.git (fetch)
origin git@github.com:code61/sinatra_project_1.git (push)
You deploy your repository by pushing to this remote. Heroku will serve whatever is in the master
branch. Here we push the master
branch up to the heroku
remote:
$ git push heroku master
Counting objects: 11, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (6/6), done.
Writing objects: 100% (11/11), 1.08 KiB, done.
Total 11 (delta 1), reused 0 (delta 0)
-----> Ruby/Rack app detected
-----> Using Ruby version: ruby-1.9.3
-----> Installing dependencies using Bundler version 1.3.2
Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin --deployment
Fetching gem metadata from https://rubygems.org/..........
Fetching gem metadata from https://rubygems.org/..
Installing rack (1.5.2)
Installing rack-protection (1.5.0)
Installing tilt (1.4.1)
Installing sinatra (1.4.3)
Using bundler (1.3.2)
Your bundle is complete! It was installed into ./vendor/bundle
Cleaning up the bundler cache.
-----> Discovering process types
Procfile declares types -> (none)
Default types for Ruby/Rack -> console, rake, web
-----> Compiled slug size: 25.0MB
-----> Launching... done, v3
http://arcane-gorge-2129.herokuapp.com deployed to Heroku
To git@heroku.com:arcane-gorge-2129.git
* [new branch] master -> master
After you push, heroku automatically updates the app and launches it for you. You can now see the app by visiting the url (in this case http://arcane-gorge-2129.herokuapp.com).
Deploy your sinatra_c3s2
app to Heroku:
Install your bundle to get a Gemfile.lock
. In your sintara_c3s2
directory run:
$ bundle install
Add your work (and new Gemfile.lock
) to your repository:
$ git add --all
$ git commit -m 'Added Gemfile.lock'
Create a new heroku app:
$ heroku create
Push your work to Heroku
$ git push heroku master
(for subsequent updates you should be ok with just git push heroku
).
Visit the url that heroku provide, to check that your app is running!
So far we’ve just returned text to the browser. It would be better if we could return proper HTML pages. We can do this by using HTML templates.
# in app.rb
require 'sinatra'
get '/' do
erb :form
end
<!-- in views/form.erb -->
<!DOCTYPE html>
<html>
<head>
<title>Barman 2.0</title>
</head>
<body>
<div class='container'>
<form method="post" action='/'>
<input type='text' name='user_name' placeholder='name'>
<input type='text' name='user_age' placeholder='age'>
<button type='submit'>Submit</button>
</form>
</div>
</body>
</html>
The line erb :form
tells sinatra to look for a file called form.erb
in a folder called views
. It then processes that file using the erb
(embedded ruby) templating language and returns the result to the user.
The form.erb
above isn’t very interesting: it is just a static template and doesn’t have any ruby embedded in it. Let’s look at a slightly better example:
# in app.rb
get '/' do
erb :form
post '/' do
@name = params[:user_name]
@age = params[:user_age]
erb :welcome
end
<!-- in views/welcome.erb -->
<!DOCTYPE html>
<html>
<head>
<title>hello</title>
</head>
<body>
<h1>Hello <%= @name %>. You are <%= @age %> years old.</h1>
</body>
</html>
The important bits are:
app.rb
we assign params[:name]
to a special type of variable @name
. The special type of variable is an instance variable which has to begin with a single @
.views/greet.erb
inside a special erb tag <%= ... %>
. The erb templater looks for these tags and interprets the inside as ruby.Sinatra emphasises convention over configuration: rather than specifying the exact place to find the template, you just give the name and Sinatra ‘knows’ where to look. This means you have to write less code in the long run, but also that you have to know the conventions before you start.
erb :template_name
.template_name.erb
in the views
folder.@
) will be shared with the template.<%= @my_variable >
Uncomment the bottom part of sinatra_c3s2/app.rb
and comment out the top two blocks.
Restart your server and check you can see the new page h1
sections.
Add twitter bootstrap to your templates, linking to the online hosted version as described on the Bootstrap CDN section of the bootstrap docs.
Add a div class='container'
around the page content, and add some styling to the form
(see here).
Add and commit your changes to your local git repo.
Deploy your changes:
git push heroku
It’s often useful to combine various conditions:
if age < 12 || height < 1.2
"You are allowed on the ride."
else
"Try a different helter-skelter. There's nothing for you here."
end
It the above snippet of code the ||
means or. If the person is under 12 or is smaller than 1.2m they are allowed on the ride.
Ruby has three ways of combining conditions:
&&
)If you use an &&
the output is true only if both inputs are true. You can write this in terms of a truth table:
false && false #=> false
false && true #=> false
true && false #=> false
true && true #=> true
||
)If you use the ||
the output is true if at least one of the inputs is true. ||
means one or the other or both:
false || false #=> false
false || true #=> true
true || false #=> true
true || true #=> true
!
)The !
is not. It is a quick way of reversing the truth of the condition:
!false #=> true
!true #=> false
irb
to see if you're right.1 > 2 && 3 > 4
1==1 || 10 ==9
!(5<6)
(1<=2 && 3>4) || (3 <= 4 && "ham")
In the last exercise you found out something interesting:
true && "ham" #=> "ham"
Which is a bit weird. There are actually two things going on here:
ham
is considered to be true
In ruby there are only two values that are considered false: false
and nil
. We say that false
and nil
are falsey.
Everything else is considered to be true. We say that all other objects are truthy.
What we mean by ‘considered to be true’ is that if that value is used as a conditional in an if
statement then the if code runs:
if 5
x = 1
else
x = 2
end
x #=> 1
In the above block of code, as 5
is truthy, the variable x
is set to 1
.
The bar is trialling a new initiative: Tuesdays is ladies night at the pub - no men allowed and all drinks are 2-4-1! They want you to update Bouncer 2.0 appropriately.
app.rb
to make it all work.Change your sinatra app into something more interesting: