You are on page 1of 11

The three Rs: Ruby, Rails and REST

Barry Cornelius, Oxford University Computing Services Date: 2008-06-05

1 1.1

Introduction The aim of this talk


The main aim of this talk is to demonstrate how Rails makes it easy to build web applications that are supported by a database. The talk will explain in detail how Rails can be used on Windows/Linux to build a simple web application. The handout for the talk looks at some of the issues involved with building more involved web applications.

1.2

Other aims

On the way, we will briey look at some aspects of the Ruby programming language. I will also briey mention the steps involved with deploying Rails using Apache. Finally, we will also look at REST, a technology for web services, and see how Rails automatically generates interfaces that are RESTful.

2 2.1

Ruby, RubyGems and Rails Using a web application framework


In my work, I often graft web applications from the code up. This can be very time-consuming and error-prone. Instead one can use a web application framework (WAF ). A web application framework is a software framework that is designed to support the development of dynamic websites, Web applications and Web services. The framework aims to alleviate the overhead associated with common activities used in Web development. For example, many frameworks provide libraries for database access, templating frameworks and session management, and often promote code reuse. (Wikipedia)

2.2

Which web application framework?

Another wikipedia page gives a list of 147 WAFs. The list of WAFs is divided into those using ASP, ASP.NET, ColdFusion, Java, JavaScript, Perl, PHP, Python and Ruby. I was keen to look at one based on a well-developed modern object-oriented programming language. For me, Java and Ruby are obvious programming languages to consider. And PHP and Perl are too primitive: they allow me easily to write bad code. I did quickly look at those WAFs using Java but there currently seems to be no frontrunner. Ruby on Rails (also known as Rails) is the WAF everyone keeps talking about.

2.3

Ruby

Ruby is an object-oriented programming language which is accompanied by a reasonably good library. I have one major criticism of Ruby. It ducks typing: typing of objects is dynamic. That does not appeal to me as in my opinion errors associated with the typing of objects should be caught at compile-time.

/rails/ictf08/handout.xml

Date: 2008-06-05 (revised Tue, 15 Jul 2008)

2.4

RubyGems

A RubyGem is a way of forming a package of Ruby code that does a substantial piece of work in some area. Examples of RubyGems include: rake, rails, gnuplot, mongrel, mysql, tidy, xml-simple, payment, BlueCloth, feedtools and htmltools.

2.5

Rails

Rails is a web application framework that uses Ruby. There are two buzz-phrases associated with Rails: Dont Repeat Yourself (DRY ): Heres an example. If some data is going to be stored both in objects of a program and in a table of a database, give the description of the data once; Convention over Conguration (CoC): Heres an example. If the objects of a class called Phone are being stored in a table of a database, the table will have the name phones. Rails even knows some strange pluralizations such as Person- people. For a class with a name like RecentChanges, the table will, by default, have the name recent_changes.

3 3.1

Installing Ruby and Rails Installing Ruby and Rails


Rails can be installed on Linux, Mac OS X and Windows. I have experience of installing it on Linux (Debian/Ubuntu) and Windows (XP).

3.2

Installing on Debian

I use a Debian package called ruby. This provides Ruby 1.8. I also use a Debian package for RubyGems (0.9.0/1.1.1). And then install the RubyGem for Rails (2.1.0). You can easily congure which database server software is to be used. Im using MySQL 5 (and so I install the Debian package mysql-server). There is more about installing on Debian in the document Rails HOW-TO: Installing Rails on Debian. This document is available from http://www.oucs.ox.ac.uk/rails/howtos

3.3

Installing on Windows

For Windows, you can install each bit separately (as was described for Debian). However, it is probably easier to use a software bundle such as Instant Rails. Ive used Instant Rails 2.0. This includes: Ruby 1.8.6 RubyGems 1.0.1 Rails 2.0.2 MySQL 5.0.27 Mongrel 1.1.2 Apache 1.3.33 phpMyAdmin 2.10.0.2 There is more about installing on Windows in the document Rails HOW-TO: Installing Rails on Windows. This document is available from http://www.oucs.ox.ac.uk/rails/howtos

Date: 2008-06-05 (revised Tue, 15 Jul 2008)

/rails/ictf08/handout.xml

4 4.1

A simple web app A phone book


We now look at how to use Rails to provide a simple web application. It is for a web app allowing a phone book to be maintained. Lets keep things simple: ... each entry in the phone book is just going to have a name and a number.

4.2

Creating a Rails application

Ill create a directory for my Rails applications. mkdir /var/apps cd /var/apps

You use the rails command to create a new Rails application. By default, it creates an application that uses SQLite3. Use the -d option to use some other database server. The following command creates a directory called contacts and creates a lot of subdirectories/les in that directory. rails -d mysql contacts cd /var/apps/contacts ls

One le is called README: it includes an explanation of the purpose of the subdirectories.

4.3

Conguring Railss access to MySQL

One subdirectory is called config. That directory contains a le called database.yml. This is the conguration for this applications access to the chosen database server. By default, it assumes you want three databases: one for development, one for testing and one for production. It also assumes your web application is going to contact the database server on the standard port (3306 for MySQL) using a username of root with an empty password. Because I want some different values, Im going to provide a different le.

4.4

Conguring Railss access to MySQL


cd /var/apps/contacts/config cat database.yml cat >database.yml <<% development: adapter: mysql port: 8116 encoding: utf8 database: contacts_development username: ruby password: PW4ruby # Warning: The database defined as test will be erased and # re-generated from your development database when you run rake. # Do not set this db to the same as development or production. test:

/rails/ictf08/handout.xml

Date: 2008-06-05 (revised Tue, 15 Jul 2008)

adapter: mysql port: 8116 encoding: utf8 database: contacts_test username: ruby password: PW4ruby production: adapter: mysql port: 8116 encoding: utf8 database: contacts_production username: ruby password: PW4ruby %

4.5

Conguring permissions in MySQL

Having chosen to use a particular username and password, we also need to inform MySQL that these three databases are to be accessed in this way. mysql -P 8116 -u root -p mysql <<% grant all privileges on contacts_development.* \ to ruby@localhost identified by PW4ruby; grant all privileges on contacts_production.* \ to ruby@localhost identified by PW4ruby; grant all privileges on contacts_test.* \ to ruby@localhost identified by PW4ruby; flush privileges; \q % PW4root

4.6

Getting rails to create the databases

The Rails software has a command called rake that behaves like Unixs make command or Windowss nmake. The following rake command gets MySQL to create the three databases. cd /var/apps/contacts rake db:create:all

Note: if I hadnt wanted to use a different port, username and password, we could have jumped from creating the Rails application to this stage.

4.7

Creating the scaffold

Ruby comes with scripts that do useful things. One of these can be used to create a scaffold. A scaffold is an initial stab at all the les you need for a web application that manipulates data stored in some table of the database. We need to give the script the name of the class and the names and types of attributes of the class. This will also be used to create a table in the database. cd /var/apps/contacts ruby script/generate scaffold Phone \ name:string \ number:string

Date: 2008-06-05 (revised Tue, 15 Jul 2008)

/rails/ictf08/handout.xml

I have chosen the type string for both attributes. Other possibilities for types are binary, boolean, date, datetime, decimal, float, integer, text, time, and timestamp.

4.8

Migrating the database

Currently, we have an empty database. With Rails, you can change a database by performing a migration. One of the les the above command creates is a le with a name like 001_create_phones.rb (when using a version of Rails before Rails 2.1) or 20080615150932_create_phones.rb (when using Rails 2.1). Its in the directory db/migrate. cd /var/apps/contacts/db/migrate cat *_create_phones.rb

It can be used to add/remove the table to/from the database. Here is this migration le.

4.9

The migration le
class CreatePhones < ActiveRecord::Migration def self.up create_table :phones do |t| t.string :name t.string :number t.timestamps end end def self.down drop_table :phones end end

4.10

Migrating the database

Here is the command to do a migration. cd /var/apps/contacts rake db:migrate

This command looks in the db/migrate directory to see if there are any les that have not been executed. It will execute the up methods of each of these in turn. In our example, it just nds 001_create_phones.rb or 20080615150932_create_phones.rb and it executes this les up method. If you were now to do the command rake db:migrate:down VERSION=20080615150932 it would execute the down method of this le to get the database back to the previous state.

4.11

Starting a web server

Ruby comes with some web server software called WEBrick. It knows how to run Ruby applications. It needs to be started.

/rails/ictf08/handout.xml

Date: 2008-06-05 (revised Tue, 15 Jul 2008)

cd /var/apps/contacts ruby script/server -p 8119 & # I got: # => Booting WEBrick... # => Rails application started on http://0.0.0.0:8119 # => Ctrl-C to shutdown server; call with --help for options # [2008-05-31 12:16:11] INFO WEBrick 1.3.1 # [2008-05-31 12:16:11] INFO ruby 1.8.5 (2006-08-25) [i486-1] # [2008-05-31 12:16:11] INFO WEBrick::HTTPServer#start: pid=28586 port=8119

4.12

Accessing the web pages

Now we can go to the web pages provided by the scaffold. There is a web page to list the items of the table. http://www.abcd.ox.ac.uk:8119/phones

There is a web page to add a new item. http://www.abcd.ox.ac.uk:8119/phones/new

There is a web page to edit an existing item. http://www.abcd.ox.ac.uk:8119/phones/1/edit

4.13

Summary of the ve steps

Suppose you just want a web application fronting one table of a database. Above, we saw that there are just ve steps: 1. Create the basic les of the application rails -d mysql contacts 2. Tell it to create the database for the app rake db:create:all 3. Tell it about the data you want to represent and it then builds a scaffold ruby script/generate scaffold Phone name:string number:string 4. Migrate the database (to include the new table) rake db:migrate 5. Start up the web server (WEBrick) and access the pages of the scaffold. We did all this without writing any code. Wow!

5 5.1

Model View Controller Rails uses Model View Controller


Rails exploits a programming technique called Model View Controller (or MVC). Here the Model is concerned with the data you want to represent. So it could be a person, or a persons name, or a CD, or a bank account, or a grid reference, ... . With Rails, by default a class in the program (e.g., Phone) is mapped to the schema for a table of a database (e.g., phones). Each instance of the class (i.e., each object) will be stored in a different row of the table. The Controller has the code that causes the data of the Model to change. And the View is the code that shows the results of an action. Typically, these les have all the code that generates HTML (or XML or ...).

Date: 2008-06-05 (revised Tue, 15 Jul 2008)

/rails/ictf08/handout.xml

5.2

The les associated with MVC

At the top level of a Rails app, there is a directory called app. In this directory, there are subdirectories called models, controllers and views. With simple examples, there is little code in the models directory as the Model is described by the table of the database. The crucial le of the controllers directory has a name like phones_controller.rb This has one method for each action. Here is an example.

5.3

A method of the controller


class PhonesController < ApplicationController def index @phones = Phone.find(:all) respond_to do |format| format.html # index.html.erb format.xml { render :xml => @phones } end end ... end

The nal part of the code of each method indicates what view to use (to show the result of the action). The request (for the action) will indicate the format of the response. It will often be HTML or XML.

5.4

Establishing the views

The views has a subdirectory with a name like phones and in that directory there is one le for each view. For example, there is a le called index.html.erb that contains the code of the web page that just lists the items of the table.

5.5

A typical view
<h1>Listing phones</h1> <table> <tr> <th>Name</th> <th>Number</th> </tr> <% for phone in @phones %> <tr> <td><%=h phone.name %></td> <td><%=h phone.number %></td> <td><%= link_to Show, phone %></td> <td><%= link_to Edit, edit_phone_path(phone) %></td> <td><%= link_to Destroy, phone, :confirm => Are you sure?, :method => :delete %></td> </tr> <% end %> </table> <br /> <%= link_to New phone, new_phone_path %>

/rails/ictf08/handout.xml

Date: 2008-06-05 (revised Tue, 15 Jul 2008)

6 6.1

More involved applications Building more involved applications


Suppose we want a web app that records the training runs undertaken by a group of runners. It has to model the people, the courses that can be run, the events (i.e., the actual training runs recording which course and when) and the runners (i.e., the people that took part in these training runs). Thats four tables. So steps 3 and 4 of the ve steps have to be done 4 times. So thats 11 steps in all. However, its not quite that easy. There are two other kinds of changes that have to be made.

6.2

Change 1: Establishing a relationship

We need to deal with the relationships between the tables. The tables involve three one-to-many relationships: an event refers to a course; a runner refers to an event; a runner refers to a person.

6.3

Change 1: Establishing a relationship


we add a MySQL command to the migration le to get the MySQL server to establish a foreign key; we alter the models for Course and Event to record more details of the relationship.

We establish a relationship by doing two things:

6.4

Change 1: Establishing a relationship


cd /var/apps/jabs/db/migrate cat *_create_events.rb cat >*_create_events.rb <<% class CreateEvents < ActiveRecord::Migration def self.up create_table :events do |t| t.date :date t.integer :minutes t.integer :seconds t.boolean :forwards t.integer :course_id, :null => false t.timestamps end execute "alter table events add constraint fk_event_courses foreign key (course_id) references courses(id)" end def self.down drop_table :events end end %

6.5

Change 1: Establishing a relationship


cd /var/apps/jabs cat app/models/course.rb cat >app/models/course.rb <<% class Course < ActiveRecord::Base has_many :events

Date: 2008-06-05 (revised Tue, 15 Jul 2008)

/rails/ictf08/handout.xml

end % cat app/models/event.rb cat >app/models/event.rb <<% class Event < ActiveRecord::Base belongs_to :course end %

6.6

Change 2: Simplifying the user interface

The other change involves changing some of the views. We alter the web form where you choose an item of another table. Instead of typing an integer identifying which row of the other table ... ... you choose from a drop-down list.

6.7

Change 2: Simplifying the user interface


ed app/controllers/events_controller.rb <<% /def new/a @courses = Course.find(:all, :order => "length desc, route_summary").map do |c| [c.length.to_s + " " + c.route_summary, c.id] end . w q % ed app/views/events/new.html.erb <<% g/f.text_field :course_id/s//f.select(:course_id, @courses)/gp w q %

http://www.abcd.ox.ac.uk:8119/events

6.8

More information

There is more about building this web app in the document Rails HOW-TO: A more involved Rails apps: jabs. This document is available from http://www.oucs.ox.ac.uk/rails/howtos

7 7.1

Deploying Rails Using Apache to deploy Rails apps


WEBrick only handles one request at a time. An often-used deployment of Rails is to replace WEBrick by the following combination: several Apache web server processes; an Apache module called mod_proxy_balancer; several Mongrel web server processes. In April 2008, an open source product called Passenger was released that can be run as an Apache module. This can be use used instead of mod_proxy_balancer and the pack of Mongrels. Passenger spawns Rails application server processes, proxies to them, and largely eliminates the conguration and glue that other Rails deployment options leave up to you (railsforphp.com)

/rails/ictf08/handout.xml

Date: 2008-06-05 (revised Tue, 15 Jul 2008)

7.2

Using Basic Authentication

It is easy to get a Rails app to ask for a username and a password. For security reasons, the Apache server should be congured to handle https connections. You then use the following code.

7.3

Code for Basic Authentication


cd /var/apps/contacts ed app/controllers/phones_controller.rb <<% /class PhonesCon/a before_filter :authenticate, :except => [ :index ] . /^end/i private def authenticate authenticate_or_request_with_http_basic do |user, pass| user=="UN4login" && pass=="PW4login" end end . w q % /etc/init.d/apache2 stop /etc/init.d/apache2 start

https://www.abcd.ox.ac.uk:8113/apps/contacts/phones https://www.abcd.ox.ac.uk:8113/apps/contacts/phones/new

7.4

More information

There is more about using Apache and passenger to deploy Rails apps and the use of Basic Authentication in the document Rails HOW-TO: Apache and Basic Authentication. There is information about how to get a Rails apps to work with WebAuth (the authentication system used at the University of Oxford) in the document Rails HOW-TO: Authenticating with WebAuth. Both these documents are available from http://www.oucs.ox.ac.uk/rails/howtos

8 8.1

Using REST What is REST?


In a Ph.D. thesis in the early 2000s, Roy Fielding introduced REST (REpresentational State Transfer). It can be used with the HTTP protocol when programs wish to communicate with web servers. There are two key aspects of using REST with HTTP: 1 You use the URL to indicate the resource you wish to manipulate 2 The HTTP method (GET, PUT, POST, DELETE) is used to indicate what you want to do with that resource. For many people, REST comes as a welcome simplication of web services.

8.2

How RESTful is Rails?

The URLs and HTTP methods that we have been using to communicate with a Rails application are essentially RESTful. For example, if we click on the submit button of a form for a new entry of the phone book, it communicates the data using POST to the URL: https://www.abcd.oucs.ox.ac.uk:8113/apps/contacts/phones Ive been using a program called curl at a Unix command line to test this out. So Ive used curl to list items, to add an item, to delete an item, to update an item, ... . Date: 2008-06-05 (revised Tue, 15 Jul 2008) 10 /rails/ictf08/handout.xml

8.3

Testing Railss RESTfulness


curl \ -k \ https://www.abcd.ox.ac.uk:8113/apps/contacts/phones.xml

curl \ -k \ -u UN4login:PW4login \ https://www.abcd.ox.ac.uk:8113/apps/contacts/phones/2.xml

curl \ -k \ -d _method=delete \ -u UN4login:PW4login \ https://www.abcd.ox.ac.uk:8113/apps/contacts/phones/2.xml curl \ -k \ https://www.abcd.ox.ac.uk:8113/apps/contacts/phones.xml

8.4

More information

There is more about using REST in the document Rails HOW-TO: Using REST. This document is available from http://www.oucs.ox.ac.uk/rails/howtos

9 9.1

And nally Important omissions


how easy it is to ensure that the data to be stored in the database is validated; how Rails comes with a complete environment for testing Rails applications. Obviously, here are some opportunities for future HOW-TOs! Time prevents me from describing:

9.2

Conclusions

With Rails, it is easy to build web applications that are supported by a database. The handout for the talk looks at some of the issues involved with building more involved web applications. Although all the code in the handout is given for Linux, similar commands can be used in Mac OS X or Windows. The handout looks at the steps involved with deploying Rails using Apache. We looked at REST, and saw how Rails automatically generates interfaces that are RESTful.

9.3

Questions, comments and resources

Over to you: its time for your questions and comments. ... ... ... The slides for this talk are available at http://www.oucs.ox.ac.uk/rails/ictf08 I found out about Ruby by immersing myself in a book. I recommend Programming Ruby by Dave Thomas (0-9745140-5-5). For Rails, the book I enjoyed reading was Agile Web Development with Rails: Second Edition by Dave Thomas and David Heinemeier Hansson (0-9776166-3-0). Unfortunately, this covers Rails 1.2: the third edition due out in October covers Rails 2.x.

/rails/ictf08/handout.xml

11

Date: 2008-06-05 (revised Tue, 15 Jul 2008)

You might also like