Ruby On Rails 2.1 - Tutorial
Ruby On Rails 2.1 - Tutorial
Audience
This tutorial has been designed for beginners who would like to use the Ruby
framework for developing database-backed web applications.
Prerequisites
Before you start Ruby on Rails, please make sure you have a basic
understanding on the following subjects:
All the content and graphics published in this e-book are the property of
Tutorials Point (I) Pvt. Ltd. The user of this e-book is prohibited to reuse, retain,
copy, distribute or republish any contents or a part of contents of this e-book in
any manner without written consent of the publisher.
We strive to update the contents of our website and tutorials as timely and as
precisely as possible, however, the contents may contain inaccuracies or errors.
Tutorials Point (I) Pvt. Ltd. provides no guarantee regarding the accuracy,
timeliness or completeness of our website or its contents including this tutorial.
If you discover any errors on our website or in this tutorial, please notify us at
[email protected]
i
Ruby on Rails 2.1
Table of Contents
About the Tutorial ......................................................................................................................................
Audience .................................................................................................................................................... i
Prerequisites .............................................................................................................................................. i
1. INTRODUCTION..................................................................................................................... 1
2. INSTALLATION ....................................................................................................................... 6
ii
Ruby on Rails 2.1
3. FRAMEWORK ...................................................................................................................... 11
5. EXAMPLES ........................................................................................................................... 18
8. MIGRATIONS ....................................................................................................................... 26
iii
Ruby on Rails 2.1
9. CONTROLLERS ..................................................................................................................... 31
iv
Ruby on Rails 2.1
v
Ruby on Rails 2.1
Introduction ............................................................................................................................................ 95
vi
Ruby on Rails 2.1
vii
Ruby on Rails 2.1
1. Introduction
What is Ruby?
Before we ride on Rails, let us recapitulate a few points of Ruby, which is the
base of Rails.
Perl's pragmatism.
Ruby is
Why Ruby?
Ruby originated in Japan and now it is gaining popularity in US and Europe as
well. The following factors contribute towards its popularity:
Easy to learn
Rich libraries
Truly object-oriented
Helpful community
Although we have many reasons to use Ruby, there are a few drawbacks as well
that you may have to consider before implementing Ruby:
1
Ruby on Rails 2.1
Threading model – Ruby does not use native threads. Ruby threads are
simulated in the VM rather than running as native OS threads.
#!/usr/bin/ruby -w
Hello Ruby
Embedded Ruby
Ruby provides a program called ERb (Embedded Ruby), written by Seki
Masatoshi. ERb allows you to put Ruby code inside an HTML file. ERb reads
2
Ruby on Rails 2.1
along, word for word, and then at a certain point, when it encounters a Ruby
code, it starts executing the Ruby code.
If you want some Ruby code executed, enclose it between <% and %>.
If you want the result of the code execution to be printed out, as a part of
the output, enclose the code between <%= and %>.
Here's an example. Save the code in erbdemo.erb file. Note that a Ruby file will
have an extension .rb, while an Embeded Ruby file will have an extension .erb.
c:\ruby\>erb erbdemo.erb
<html>
<head>
<title>Demonstration of ERb</title>
</head>
<body>
<p>Dear programmer,</p>
<p>This is an example of how ERb fills out a template.</p>
</body>
</html>
3
Ruby on Rails 2.1
What is Rails?
An extremely productive web-application framework.
You could develop a web application at least ten times faster with Rails,
than you could with a typical Java framework.
Being a full-stack framework means all the layers are built to work
seamlessly with less code.
Rails Strengths
Rails is packed with features that make you more productive, with many of the
following features building on one other.
4
Ruby on Rails 2.1
one of the best languages for metaprogramming, and Rails uses this capability
well. Rails also uses code generation but relies much more on metaprogramming
for the heavy lifting.
Active Record: Rails introduces the Active Record framework, which saves
objects to the database. The Rails version of the Active Record discovers the
columns in a database schema and automatically attaches them to your domain
objects using metaprogramming.
Ajax at the core: Ajax is the technology that has become a standard to provide
interactivity to websites without becoming intrusive. Ruby on Rails has a great
support for Ajax technology and it is a part of the core libraries. So, when you
install RoR, Ajax support is also made available to you.
Built-in testing: Rails creates simple automated tests you can then extend.
Rails also provides supporting code called harnesses and fixtures that make test
cases easier to write and run. Ruby can then execute all your automated tests
with the rake utility.
This version is a further improvement on RoR 2.0, which was again really a
fantastic release, absolutely stuffed with great new features, loads of fixes, and
an incredible amount of polish over its previous versions RoR 1.2.x.
This tutorial takes you through all the important features available in the latest
RoR version 2.1.0.
After this tutorial, you should be able to build your website using one of the best
Web 2.0 technologies called Ruby on Rails v2.1.0.
5
Ruby on Rails 2.1
2. Installation
To develop a web application using Ruby on Rails Framework, you would need to
install the following software:
Ruby
A Web Server
A Database System
We assume that you already have installed a Web Server and Database System
on your computer. You can always use the WEBrick Web Server, which comes
with standard installation of Ruby. Most sites, however, use Apache or lightTPD
in production.
Rails works with many database systems, including MySQL, PostgreSQL, SQLite,
Oracle, DB2 and SQL Server. Please refer to a corresponding Database System
Setup manual to setup your database.
Let's look at the installation instructions for Rails' Framework on Windows, Mac
OS X, and Linux.
2. With RubyGems loaded, you can install all of Rails and its dependencies
through the command line:
The above command may take some time to install all dependencies. Make sure
you are connected to the internet while installing gems dependencies.
NOTE: In case you face any problem with the above installation, there are
chances that you may not have the latest versions of Ruby or other Gems. So
just issue the following command and you will have everything updated
automatically.
The above command may take some time to install all dependencies. Make sure
you are connected to the internet while installing gems dependencies.
NOTE: In case you face any problem with above installation, there are
chances that you may not have the latest versions of Ruby or other Gems.
So just issue the following command and you will have everything updated
automatically.tp> sudo gem update
7
Ruby on Rails 2.1
6. Now use RubyGems to install Rails. Still in the shell, issue the following
command.
The above command may take some time to install all dependencies. Make sure
you are connected to the internet while installing gems dependencies.
NOTE: In case you face any problem with above installation, there are
chances that you may not have the latest versions of Ruby or other Gems.
So, just issue the following command and you will have everything
updated automatically.tp> sudo gem update
8
Ruby on Rails 2.1
This will automatically update your Rails installation. The next time you restart
your application, it will pick up this latest version of Rails. While giving this
command, make sure you are connected to the internet.
Installation Verification
You can verify if everything is setup according to your requirements or not. Use
the following command to create a demo project in Rails environment.
This will create a demo rails' project using SQLite database. Note that Rails uses
SQLite as its default database.
We can create an application that will use MySQL database. Assuming you have
MySQL database setup on your machine, issue the following command to create
an application that will use MySQL database:
tp> cd demo
demo> ruby script/server
=> Rails application started on http://0.0.0.0:3000
=> Ctrl-C to shutdown server; call with --help for options
[2007-02-26 09:16:43] INFO WEBrick 1.3.1
[2007-02-26 09:16:43] INFO ruby 1.8.2 (2004-08-24)...
[2007-02-26 09:16:43] INFO WEBrick::HTTPServer-start:pid=2836...
....
Now open your browser and type the following address text box.
http://localhost:3000
9
Ruby on Rails 2.1
How to Upgrade?
If you are already running an old version of Rails, then here is the procedure to
upgrade it to the latest version 2.1:
1. If you want to move your application to Rails 2.0, you should first move it
to Rails 1.2.6.
10
Ruby on Rails 2.1
3. Framework
A framework is a program, set of programs, and/or code library that writes most
of the applications for you. When you use a framework, your job is to write the
parts of the application that make it do the specific things you want.
When you set out to write a Rails application, leaving aside the configuration and
other housekeeping chores, you have to perform three primary tasks:
Specify what can happen in this domain: The domain model is static.
You have to make it dynamic. Addresses can be added to an address
book. Musical scores can be purchased from music stores. Users can log in
to a dating service. Students can register for classes at a university. You
need to identify all the possible scenarios or actions that the elements of
your domain can participate in.
Model (ActiveRecord)
Maintains the relationship between Object and Database and handles validation,
association, transactions, and more.
11
Ruby on Rails 2.1
Ruby method names are automatically generated from the field names of
database tables.
View (ActionView)
It is a presentation of data in a particular format, triggered by a controller's
decision to present the data. They are script-based templating systems like JSP,
ASP, PHP and very easy to integrate with AJAX technology.
ActionView helps in separating the details of presentation from the core business
logic of your application.
Controller (ActionController)
The facility within the application that directs traffic, on the one hand querying
the models for specific data, and on the other hand, organizing that data
(searching, sorting, massaging it) into a form that fits the needs of a given view.
12
Ruby on Rails 2.1
tp> cd /usr/local/lib/ruby/gems/1.8/gems
tp> ls
You will see subdirectories including (but not limited to) the following:
actionpack-x.y.z
activerecord-x.y.z
rails-x.y.z
C:\>cd ruby\lib\ruby\gems\1.8\gems
C:\ruby\lib\ruby\gems\1.8\gems\>dir
You will see subdirectories including (but not limited to) the following:
actionpack-x.y.z
activerecord-x.y.z
rails-x.y.z
13
Ruby on Rails 2.1
14
Ruby on Rails 2.1
4. Dir Structure
When you use the helper script of Rails to create your application, it creates the
entire directory structure for your application. Rails knows where to find things it
needs within this structure, so you don't have to provide any input.
Here is a top-level view of the directory tree created by the helper script at the
time of an application creation. Except for minor changes between the releases,
every Rails project will have the same structure with the same naming
conventions. This consistency gives you a tremendous advantage; you can
quickly move between Rails projects without re-learning the project's
organization.
To understand this directory structure, let's use the demo application created in
the installation chapter. This can be created using a simple helper command as
follows:
C:\ruby\> cd demo
C:\ruby\demo> dir
demo/
..../app
......../controller
......../helpers
......../models
......../views
............../layouts
..../config
..../db
..../doc
..../lib
..../log
..../public
15
Ruby on Rails 2.1
..../script
..../test
..../tmp
..../vendor
README
Rakefile
app/models: The models subdirectory holds the classes that model and
wrap the data stored in our application's database. In most frameworks,
this part of the application can grow pretty messy, tedious, verbose, and
error-prone. Rails makes it dead simple!
db: Usually, your Rails application will have model objects that access
relational database tables. You can manage the relational database with
scripts you create and place in this directory.
16
Ruby on Rails 2.1
log: Error logs go here. Rails creates scripts that help you manage various
error logs. You'll find separate logs for the server (server.log) and each
Rails environment (development.log, test.log, and production.log).
public: Like the public directory for a web server, this directory has web
files that don't change, such as JavaScript files (public/javascripts),
graphics (public/images), stylesheets (public/stylesheets), and HTML files
(public). This should be set as the DOCUMENT_ROOT of your web server.
script: This directory holds scripts to launch and manage the various
tools that you'll use with Rails. For example, there are scripts to generate
code (generate) and launch the web server (server), etc.
test: The tests you write and those Rails creates for you, all goes here.
You'll see a subdirectory for mocks (mocks), unit tests (unit), fixtures
(fixtures), and functional tests (functional).
tmp: Rails uses this directory to hold temporary files for intermediate
processing.
Apart from these directories, there will be two files available in the demo
directory.
README: This file contains a basic detail about Rail Application and
description of the directory structure explained above.
17
Ruby on Rails 2.1
5. Examples
Subsequent chapters are based on the example taken in this chapter. In this
chapter, we will create a simple but operational online library system for holding
and managing the books.
This application has a basic architecture and will be built using two ActiveRecord
models to describe the types of data that is stored in your database:
Use the rails command to create the basic skeleton of the application.
Create Rails Active Records (Models), because they are the business
objects you'll be working with in your controllers.
18
Ruby on Rails 2.1
This will create a subdirectory for the library application containing a complete
directory tree of folders and files for an empty Rails application. Check a
complete directory structure of the application. Check Rails Directory
Structure for more detail.
Here, we are using -d mysql option to specify our interest to use MySQL
database. We can specify any other database name like oracle or postgress using
-d option. By default, Rails uses SQLite database.
Most of our development work will be creating and editing files in the
~/library/app subdirectories. Here's a quick rundown on how to use them:
The views subdirectory holds the display templates to fill in with data from
our application, convert to HTML, and return to the user's browser.
The models subdirectory holds the classes that model and wrap the data
stored in our application's database. In the most frameworks, this part of
the application can grow pretty messy, tedious, verbose, and error-prone.
Rails makes it dead simple.
The helpers subdirectory holds any helper classes used to assist the
model, view, and controller classes. This helps to keep the model, view,
and controller code small, focused, and uncluttered.
This server will be started from the application directory as follows. It runs on
port number 3000:
C:\> cd ruby\library
C:\ruby\library\> ruby script/server
It will start your WEBrick web server listening for Web Requests at port number
3000 at local machine.
19
Ruby on Rails 2.1
What is Next?
The next chapter explains how to create databases for your application and what
is the configuration required to access these created databases.
Further, we will see what is Rail Migration and how it is used to maintain
database tables.
20
Ruby on Rails 2.1
6. Database Setup
Before starting with this chapter, make sure your database server is setup and
running. Ruby on Rails recommends to create three databases: a database each
for development, testing, and production environment. According to convention,
their names should be as follows:
library_development
library_production
library_test
You should initialize all three of them and create a username and password for
them with full read and write privileges. We are using root user ID for our
application. In MySQL, a console session looks as follows:
You can do the same thing for the other two databases, library_production
and library_test.
Configuring database.yml
At this point, you need to let Rails know about the username and password for
the databases. You do this in the file database.yml, available in the
C:\ruby\library\config subdirectory of Rails Application you created. This file
has live configuration sections for MySQL databases. In each of the sections you
use, you need to change the username and password lines to reflect the
permissions on the databases you've created.
21
Ruby on Rails 2.1
development:
adapter: mysql
database: library_development
username: root
password: [password]
host: localhost
test:
adapter: mysql
database: library_test
username: root
password: [password]
host: localhost
production:
adapter: mysql
database: library_production
username: root
password: [password]
host: localhost
NOTE: You can use similar setting for other databases if you are using any other
database except MySQL.
What is Next?
The next two chapters explain how to model your database tables and how to
manage those using Rails Migrations.
22
Ruby on Rails 2.1
7. Active Records
Rails Active Record is the Object/Relational Mapping (ORM) layer supplied with
Rails. It closely follows the standard ORM model, which is as follows:
Rails Active Records provides an interface and binding between the tables in a
relational database and the Ruby program code that manipulates database
records. Ruby method names are automatically generated from the field names
of database tables.
Each Active Record object has CRUD (Create, Read, Update, and Delete)
methods for database access. This strategy allows simple designs and
straightforward mappings between database tables and application objects.
Each entity (such as book) gets a table in the database named after it,
but in the plural (books).
Each such entity-matching table has a field called id, which contains a
unique integer for each record inserted into the table.
Given entity x and entity y, if entity y belongs to entity x, then table y has
a field called x_id.
The bulk of the fields in any table, store the values for that entity's simple
properties (anything that's a number or a string).
23
Ruby on Rails 2.1
You're telling the generator to create models called Book and Subject to store
instances of books and subjects. Notice that you are capitalizing Book and
Subject and using the singular form. This is a Rails paradigm that you should
follow each time you create a model.
When you use the generate tool, Rails creates the actual model file that holds all
the methods unique to the model and the business rules you define, a unit test
file for performing test-driven development, a sample data file (called fixtures)
to use with the unit tests, and a Rails migration that makes creating database
tables and columns easy.
Apart from creating many other files and directories, this will create files named
book.rb and subject.rb containing a skeleton definition in app/models
directory.
24
Ruby on Rails 2.1
Now you need to tell Rails what relationships you want to establish within the
library data system. To do so, modify book.rb and subject.rb to look like this:
We have used a singular subject in the above example, because one Book can
belong to a single Subject.
We have used plural books in the above example, because one subject can have
multiple books.
Implementing Validations
The implementation of validations is done in a Rails model. The data you are
entering into the database is defined in the actual Rails model, so it only makes
sense to define what valid data entails in the same location.
Besides the validations mentioned above, there are some other common
validations. Check Rails Quick Guide.
What is Next?
In the next chapter, we will learn Rails Migration, which allows you to use Ruby
to define changes to your database schema, making it possible to use a version
control system to keep things synchronized with the actual code.
25
Ruby on Rails 2.1
8. Migrations
Rails Migration uses Ruby to define changes to your database schema, making it
possible to use a version control system to keep things synchronized with the
actual code.
Production servers - run "rake migrate" when you roll out a new release to
bring the database up to date as well.
drop_table(name)
rename_table(old_name, new_name)
remove_column(table_name, column_name)
remove_index(table_name, column_name)
Migrations support all the basic data types: string, text, integer, float, date-
time, timestamp, time, date, binary and Boolean:
date-time and timestamp - stores the date and time into a column.
26
Ruby on Rails 2.1
date and time - stores either the date only or time only.
NOTE: The activities done by Rails Migration can be done using any front-end
GUI or direct on SQL prompt, but Rails Migration makes all those activities very
easy.
We will create two migrations corresponding to our three tables - books and
subjects.
C:\ruby> cd library
C:\ruby\library> ruby script/generate migration books
C:\ruby\library> ruby script/generate migration subjects
Notice that you are using lowercase for book and subject and using the plural
form while creating migrations. This is a Rails paradigm that you should follow
each time you create a Migration.
27
Ruby on Rails 2.1
def self.down
drop_table :books
end
end
The method self.up is used when migrating to a new version, self.down is used
to roll back any changes if needed. At this moment, the above script will be used
to create the books table.
28
Ruby on Rails 2.1
def self.down
drop_table :subjects
end
end
The above script will be used to create subjects table; it will create five records
in the subjects table.
This will create a "schema_info" table if it doesn't exist, which tracks the current
version of the database. Each new migration will be a new version, and any new
migrations will be run, until your database is at the current version.
Rake is a Ruby build program similar to Unix make program that Rails takes
advantage of, to simplify the execution of complex tasks such as updating a
database's structure etc.
For example:
What is Next?
29
Ruby on Rails 2.1
Now we have our database and the required tables available. In the two
subsequent chapters, we will explore two important components called
Controller (ActionController) and View (ActionView).
30
Ruby on Rails 2.1
9. Controllers
The Rails controller is the logical center of your application. It coordinates the
interaction between the user, the views, and the model. The controller is also a
home to a number of important ancillary services.
The process for creating a controller is very easy, and it's similar to the process
we've already used for creating a model. We will create just one controller here:
Notice that you are capitalizing Book and using the singular form. This is a Rails
paradigm that you should follow each time you create a controller.
This command accomplishes several tasks, of which the following are relevant
here:
Controller classes inherit from ApplicationController, which is the other file in the
controllers folder: application.rb.
The ApplicationController contains code that can be run in all your controllers
and it inherits from Rails ActionController::Base class.
You don't need to worry with the ApplicationController as of yet, so let us just
define a few method stubs in book_controller.rb. Based on your requirement,
you could define any number of functions in this file.
31
Ruby on Rails 2.1
Modify the file to look like the following and save your changes. Note that it is up
to you what name you want to give to these methods, but better to give
relevant names.
def list
@books = Book.find(:all)
end
The @books = Book.find(:all) line in the list method tells Rails to search the
books table and store each row it finds in the @books instance object.
32
Ruby on Rails 2.1
def show
@book = Book.find(params[:id])
end
The show method's @books = Book.find(params[:id]) line tells Rails to find only
the book that has the id defined in params[:id].
The params object is a container that enables you to pass values between the
method calls. For example, when you're on the page called by the list method,
you can click a link for a specific book, and it passes the id of that book via the
params object so that show can find the specific book.
def new
@book = Book.new
@subjects = Subject.find(:all)
end
The above method will be called when you will display a page to the user to take
user input. Here the second line grabs all the subjects from the database and
puts them in an array called @subjects.
def create
@book = Book.new(params[:book])
if @book.save
redirect_to :action => 'list'
else
@subjects = Subject.find(:all)
render :action => 'new'
end
33
Ruby on Rails 2.1
end
The first line creates a new instance variable called @book that holds a Book
object built from the data the user submitted. The data was passed from the
new method to create using the params object.
The next line is a conditional statement that redirects the user to the list method
if the object saves correctly to the database. If it doesn't save, the user is sent
back to the new method. The redirect_to method is similar to performing a meta
refresh on a web page and it automatically forwards you to your destination
without any user interaction.
def edit
@book = Book.find(params[:id])
@subjects = Subject.find(:all)
end
This method will be called to display data on the screen to be modified by the
user. The second line grabs all the subjects from the database and puts them in
an array called @subjects.
def update
@book = Book.find(params[:id])
if @book.update_attributes(params[:book])
redirect_to :action => 'show', :id => @book
else
@subjects = Subject.find(:all)
render :action => 'edit'
34
Ruby on Rails 2.1
end
end
The update_attributes method is similar to the save method used by create, but
instead of creating a new row in the database, it overwrites the attributes of the
existing row.
Then @subjects = Subject.find(:all) line is required in case it does not save data
successfully, then it becomes similar to the edit option.
def delete
Book.find(params[:id]).destroy
redirect_to :action => 'list'
end
The first line finds the classified based on the parameter passed via the params
object and then deletes it using the destroy method. The second line redirects
the user to the list method using a redirect_to call.
def show_subjects
@subject = Subject.find(params[:id])
end
end
def new
@book = Book.new
@subjects = Subject.find(:all)
end
def create
@book = Book.new(params[:book])
if @book.save
redirect_to :action => 'list'
else
@subjects = Subject.find(:all)
render :action => 'new'
end
end
def edit
@book = Book.find(params[:id])
@subjects = Subject.find(:all)
end
def update
@book = Book.find(params[:id])
if @book.update_attributes(params[:book])
redirect_to :action => 'show', :id => @book
else
@subjects = Subject.find(:all)
render :action => 'edit'
end
end
def delete
Book.find(params[:id]).destroy
redirect_to :action => 'list'
end
def show_subjects
@subject = Subject.find(params[:id])
36
Ruby on Rails 2.1
end
end
Now, save your controller file and come out for the next assignment.
What is Next?
You have created almost all the methods, which will work on backend. Next, we
will create a code to generate screens to display data and to take input from the
user.
37
Ruby on Rails 2.1
10. Views
A Rails View is an ERb program that shares data with controllers through
mutually accessible variables.
If you look in the app/views directory of the library application, you will see one
subdirectory for each of the controllers we have created: book. Each of these
subdirectories was created automatically when the same-named controller was
created with the generate script.
Now, assuming your web server is up and running, provide the following input in
your browser's address box:
http://localhost:3000/book/list
You get the following error message because you have not defined any view file
for any method defined in the controller.
Rails lets you know that you need to create the view file for the new method.
Each method you define in the controller needs to have a corresponding RHTML
file, with the same name as the method, to display the data that the method is
collecting.
So let us create view files for all the methods we have defined in
book_controller.rb.
Now, to display the actual content, let us put the following code into list.rhtml.
38
Ruby on Rails 2.1
The code to be executed is to check whether the @books array has any objects
in it. The .blank? method returns true if the array is empty, and false if it
contains any objects. This @books object was created in controller inside the list
method.
The code between the <%= %> tags is a link_to method call. The first
parameter of link_to is the text to be displayed between the <a> tags. The
second parameter is what action is called, when the link is clicked. In this case,
it is the show method. The final parameter is the id of the book that is passed
via the params object.
Now, try refreshing your browser and you should get the following screen
because we don't have any book in our library.
39
Ruby on Rails 2.1
Create a file called new.rhtml using your favorite text editor and save it to
app/views/book. Add the following code to the new.rhtml file.
Here the start_form_tag() method interprets the Ruby code into a regular
HTML <form> tag using all the information supplied to it. This tag, for example,
outputs the following HTML:
The next method is text_field that outputs an <input> text field. The
parameters for text_field are object and field name. In this case, the object is
book and the name is title.
The Rails method called collection_select creates an HTML select menu built
from an array, such as the @books one. There are five parameters, which are as
follows:
:book - The object you are manipulating. In this case, it's a book object.
40
Ruby on Rails 2.1
:id - The value that is stored in the database. In terms of HTML, this is the
<option> tag's value parameter.
:name- The output that the user sees in the pull-down menu. This is the
value between the <option> tags.
The next used is submit_tag, which outputs an <input> button that submits
the form. Finally, there is the end_form_tag method that simply translates into
</form>.
Enter some data in this form and then click the Create button. This will result in
a call to create method, which does not need any view because this method is
using either the list or new methods to view the results. When you click the
Create button, the data should submit successfully and redirect you to the list
page, in which you now have a single item listed as follows:
41
Ruby on Rails 2.1
If you click the link, you should see another error “Template is missing” since
you haven't created the template file for the show method yet.
This is the first time you have taken full advantage of associations, which enable
you to easily pull data from related objects.
42
Ruby on Rails 2.1
>
<h1>Edit Book Detail</h1>
<%= start_form_tag :action => 'update', :id => @book %>
<p><label for="book_title">Title</label>:
<%= text_field 'book', 'title' %></p>
<p><label for="book_price">Price</label>:
<%= text_field 'book', 'price' %></p>
<p><label for="book_subject">Subject</label>:
<%= collection_select(:book, :subject_id,
@subjects, :id, :name) %></p>
<p><label for="book_description">Description</label><br/>
<%= text_area 'book', 'description' %></p>
<%= submit_tag "Save changes" %>
<%= end_form_tag %>
<%= link_to 'Back', {:action => 'list' } %>
43
Ruby on Rails 2.1
This code is very similar to the new method, except for the fact that action to be
updated instead of creating and defining an id.
At this point, we need some modification in the list method's view file. Go to
the <li></li> element and modify it so that it looks as follows:
<li>
<%= link_to c.title, {:action => "show", :id => c.id} -%>
<b> <%= link_to 'Edit', {:action => "edit",
:id => c.id} %></b>
</li>
Now, you edit this information and then click the Save Changes button. It will
result in a call to update method available in the controller file and it will update
all the changed attributes. Notice that the update method does not need any
view file because it's using either show or edit methods to show its results.
44
Ruby on Rails 2.1
<li>
<%= link_to c.title, {:action => 'show', :id => c.id} -%>
<b> <%= link_to 'Edit', {:action => 'edit', :id => c.id} %></b>
<b> <%= link_to "Delete", {:action => 'delete', :id => c.id},
:confirm => "Are you sure you want to delete this item?" %></b>
</li>
Now, using the Delete option, you can delete any listed record.
45
Ruby on Rails 2.1
Now, modify the Subject line of show.rhtml so that the subject listing shows a
link.
This will output a list of subject on the index page, so that users can access
them directly.
<ul id="subjects">
<% Subject.find(:all).each do |c| %>
<li><%= link_to c.name, :action => "show_subjects",
:id => c.id %></li>
<% end %>
</ul>
46
Ruby on Rails 2.1
What is Next?
We hope you are now comfortable with all the Rails Operations.
The next chapter explains how to use Layouts to put your data in a better way.
We will also show you how to use CSS in your Rails applications.
47
Ruby on Rails 2.1
11. Layouts
A layout defines the surroundings of an HTML page. It's the place to define the
common look and feel of your final output. Layout files reside in
app/views/layouts.
The process involves defining a layout template and then letting the controller
know that it exists and to use it. First, let's create the template.
Add a new file called standard.rhtml to app/views/layouts. You let the controllers
know what template to use by the name of the file, so following a same naming
scheme is advised.
Add the following code to the new standard.rhtml file and save your changes:
48
Ruby on Rails 2.1
</body>
</html>
Everything you just added are standard HTML elements except the two lines with
the stylesheet_link_tag helper method that outputs a stylesheet <link>. In
this instance, we are linking the style.css stylesheet. The yield command lets
Rails know that it should put the RHTML for the method called here.
Now open book_controller.rb and add the following line just below the first
line:
49
Ruby on Rails 2.1
body {
font-family: Helvetica, Geneva, Arial, sans-serif;
font-size: small;
font-color: #000;
background-color: #fff;
}
a:link, a:active, a:visited {
color: #CD0000;
}
input {
margin-bottom: 5px;
}
p {
line-height: 150%;
}
div#container {
width: 760px;
margin: 0 auto;
}
div#header {
text-align: center;
padding-bottom: 15px;
}
div#content {
float: left;
width: 450px;
padding: 10px;
}
div#content h3 {
50
Ruby on Rails 2.1
margin-top: 15px;
}
ul#books {
list-style-type: none;
}
ul#books li {
line-height: 140%;
}
div#sidebar {
width: 200px;
margin-left: 480px;
}
ul#subjects {
width: 700px;
text-align: center;
padding: 5px;
background-color: #ececec;
border: 1px solid #ccc;
margin-bottom: 20px;
}
ul#subjects li {
display: inline;
padding-left: 5px;
}
51
Ruby on Rails 2.1
What is Next?
The next chapter explains how to develop applications with Rails Scaffolding to
give user access to add, delete, and modify the records in any database.
52
Ruby on Rails 2.1
12. Scaffolding
While you're developing Rails applications, especially those which are mainly
providing you with a simple interface to data in a database, it can often be
useful to use the scaffold method.
Scaffolding provides more than cheap demo thrills. Here are some benefits:
You can quickly get code in front of your users for feedback.
Scaffolding Example
Ruby on Rails 2.0 changes the way Rails uses scaffolding. To understand
scaffolding, let’s create a database called cookbook and a table called recipes.
Here we are using -d mysql option to specify our interest to use MySQL
database. We can specify any other database name like oracle or postgress using
-d option. By default, Rails uses SQLite database.
development:
adapter: mysql
encoding: utf8
database: cookbook
username: root
password: password
host: localhost
test:
adapter: mysql
encoding: utf8
database: cookbook
username: root
password: password
host: localhost
production:
adapter: mysql
encoding: utf8
database: cookbook
username: root
password: password
host: localhost
NOTE: You can use similar settings for other database adapters in case you
want to use any other database except MySQL.
Rails lets you run in the development mode, test mode, or production mode,
using different databases. This application uses the same database for each.
54
Ruby on Rails 2.1
id INT(11)
title VARCHAR(40)
chef VARCHAR(40)
instructions VARCHAR(255)
Note a singular name Recipe to create a plural table name recipes. However, the
above command will generate the following messages:
exists app/models/
exists app/controllers/
exists app/helpers/
create app/views/recipes
exists app/views/layouts/
exists test/functional/
exists test/unit/
exists public/stylesheets/
create app/views/recipes/index.html.erb
create app/views/recipes/show.html.erb
create app/views/recipes/new.html.erb
create app/views/recipes/edit.html.erb
create app/views/layouts/recipes.html.erb
create public/stylesheets/scaffold.css
create app/controllers/recipes_controller.rb
create test/functional/recipes_controller_test.rb
55
Ruby on Rails 2.1
create app/helpers/recipes_helper.rb
route map.resources :recipes
dependency model
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/recipe.rb
create test/unit/recipe_test.rb
create test/fixtures/recipes.yml
create db/migrate
create db/migrate/20080614192220_create_recipes.rb
cookbook>
The Controller
Let's look at the code behind the controller. This code is generated by the
scaffold generator. If you open app/controllers/recipes_controller.rb, you will
find something as follows:
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @recipes }
end
end
# GET /recipes/1
# GET /recipes/1.xml
def show
56
Ruby on Rails 2.1
@recipe = Recipe.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @recipe }
end
end
# GET /recipes/new
# GET /recipes/new.xml
def new
@recipe = Recipe.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @recipe }
end
end
# GET /recipes/1/edit
def edit
@recipe = Recipe.find(params[:id])
end
# POST /recipes
# POST /recipes.xml
def create
@recipe = Recipe.new(params[:recipe])
respond_to do |format|
if @recipe.save
flash[:notice] = 'Recipe was successfully created.'
format.html { redirect_to(@recipe) }
57
Ruby on Rails 2.1
# PUT /recipes/1
# PUT /recipes/1.xml
def update
@recipe = Recipe.find(params[:id])
respond_to do |format|
if @recipe.update_attributes(params[:recipe])
flash[:notice] = 'Recipe was successfully updated.'
format.html { redirect_to(@recipe) }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @recipe.errors,
:status => :unprocessable_entity }
end
end
end
# DELETE /recipes/1
# DELETE /recipes/1.xml
def destroy
@recipe = Recipe.find(params[:id])
@recipe.destroy
58
Ruby on Rails 2.1
respond_to do |format|
format.html { redirect_to(recipes_url) }
format.xml { head :ok }
end
end
end
This file has all the methods implemented automatically. You can perform any
Create, Read, Delete, or Edit operation using these available methods.
When a user of a Rails application selects an action, e.g., "Show" - the controller
will execute any code in the appropriate section - "def show" - and then by
default will render a template of the same name - "show.html.erb". This default
behavior can be overwritten by overwriting the code in any template.
The controller uses ActiveRecord methods such as find, find_all, new, save,
update_attributes, and destroy to move data to and from the database tables.
Note that you do not have to write any SQL statements, Rails will take care of it
automatically.
The Views
All the views and corresponding controller methods are created by scaffold
command and they are available in app/views/recipes directory. You will have
the following files in this directory:
index.html.erb - This is the template file to show the default page and
will be executed when you type http://127.0.0.1:3000/recipes.
We suggest you to open these files one by one and try to understand their
source code.
The Migrations
You will find a migration file created in ~/cookbook/db/migrate subdirectory.
This file will have the following content:
59
Ruby on Rails 2.1
def self.down
drop_table :recipes
end
end
To create the required file in your database, make use of helper script as follows.
Ready to Test
All the above steps bring your database table to life. It provides a simple
interface to your data, and ways of:
When creating or editing an entry, scaffold will do all the hard work of form
generation and handling. It will even provide clever form generation, supporting
the following types of inputs:
60
Ruby on Rails 2.1
Date selectors
Date-time selectors
Now, go to cookbook directory and run the Web Server using the following
command:
Now, enter some values in the given text boxes, and press the Create button to
create a new recipe. Your record is added into the recipes table and it shows the
following result:
61
Ruby on Rails 2.1
You can use either the Edit option to edit the recipe or the Back button to go to
the previous page. Assuming you have pressed the Back button, it will display
all the recipes available in your database. As we have only one record in our
database, it will show you the following screen:
This screen gives you the option to see the complete details of the recipe table.
In addition, it provides options to edit or even delete the table.
62
Ruby on Rails 2.1
Here we are trying to provide a bigger title while editing the exiting record. It
produces the following error message, just because we have added the above
validations:
63
Ruby on Rails 2.1
13. Ajax on Rails
Ajax stands for Asynchronous JavaScript and XML. Ajax is not a single
technology; it is a suite of several technologies. Ajax incorporates the following:
Ajax enables you to retrieve data for a web page without having to refresh the
contents of the entire page. In the basic web architecture, the user clicks a link
or submits a form. The form is submitted to the server, which then sends back a
response. The response is then displayed for the user on a new page.
When you interact with an Ajax-powered web page, it loads an Ajax engine in
the background. The engine is written in JavaScript and its responsibility is to
both communicate with the web server and display the results to the user. When
you submit data using an Ajax-powered form, the server returns an HTML
fragment that contains the server's response and displays only the data that is
new or changed as opposed to refreshing the entire page.
For a complete detail on AJAX you can go through our AJAX Tutorial.
Some trigger fires: This trigger could be the user clicking on a button or
link, the user making changes to the data on a form or in a field, or just a
periodic trigger (based on a timer).
64
Ruby on Rails 2.1
These steps are the simplest way to use Ajax in a Rails application, but with a
little extra work, you can have the server return any kind of data in response to
an Ajax request, and you can create custom JavaScript in the browser to
perform more involved interactions.
AJAX Example
While discussing rest of the Rails concepts, we have taken an example of
Library. There we have a table called subject and we had added few subjects at
the time of Migration. Till now we have not provided any procedure to add and
delete subjects in this table.
In this example, we will provide, list, show and create operations on subject
table. If you don't have any understanding on Library Info System explained in
the previous chapters, then we would suggest you to complete the previous
chapters first and then continue with AJAX on Rails.
Creating Controller
Let’s create a controller for subject. It will be done as follows:
65
Ruby on Rails 2.1
end
Now, we will discuss the implementation part of all these functions in the same
way we had given in the previous chapters.
This is similar to the example explained earlier and will be used to list down all
the subjects available in our database.
This is also similar to the example explained earlier and will be used to display a
particular subject corresponding to the passed ID.
This part is a bit new. Here we are not redirecting the page to any other page;
we are just rendering the changed part instead of whole page.
It happens only when using partial. We don't write the complete view file,
instead, we will write a partial in the /app/view/subject directory. We will see it
in a moment. First, let's create view files for other methods.
66
Ruby on Rails 2.1
Creating Views
Now we will create view files for all the methods except for the create method
for which we will create a partial.
<h1>Listing Subjects</h1>
<ul id="subject_list">
<% @subjects.each do |c| %>
<li><%= link_to c.name, :action => 'show', :id => c.id %>
<%= "(#{c.books.count})" -%></li>
<% end %>
</ul>
Here, you are iterating through the @subjects array and outputting a <li>
element containing a link to the subject it is referencing for each item in the
array. Additionally, you are outputting the number of books in that specific
subject inside parentheses. Rails' associations make it easy to step through a
relationship and get information like this.
67
Ruby on Rails 2.1
Now, try clicking on any subject and you will find a listing of all the books
available under that subject.
This includes both the Prototype and script.aculo.us libraries in the template, so
their effects will be accessible from any of the views.
The second section is the creation of the add_subject <div>. Notice that you set
its visibility to be hidden by default using the CSS display property. The
preceding link_to_function is what will change this property and show the <div>
to the user to take input required to add a new subject.
Next, you are creating the Ajax form using the form_remote_tag. This Rails
helper is similar to the start_form_tag tag, but it is used here to let the Rails
framework know that it needs to trigger an Ajax action for this method. The
form_remote_tag takes the :action parameter just like start_form_tag.
The :update parameter tells Rails' Ajax engine which element to update
based on its id. In this case, it's the <ul> tag.
The :position parameter tells the engine where to place the newly added
object in the DOM. You can set it to be at the bottom of the unordered list
(:bottom) or at the top (:top).
Next, you create the standard form fields and submit buttons as before and then
wrap things up with an end_form_tag to close the <form> tag. Make sure that
things are semantically correct and valid XHTML.
69
Ruby on Rails 2.1
You are done now and can easily add several subjects without having to wait for
the page to refresh after each subject is added. Now, try browsing your Subject
list using http://localhost:3000/subject/list. It will show you the following
screen. Try to add some subject.
When you press the Add button, subject would be added at the bottom of all the
available subjects and you would not have a feel of page refresh.
70
Ruby on Rails 2.1
14. File Uploading
You may have a requirement in which you want your site visitors to upload a file
on your server. Rails makes it very easy to handle this requirement. Now, we
will proceed with a simple and small Rails project.
As usual, let's start off with a new Rails application called upload. Let's create a
basic structure of the application by using simple rails command.
Let's decide where you would like to save your uploaded files. Assume this is
data directory inside your public section. So, create this directory and check the
permissions.
C:\ruby> cd upload
C:\ruby> mkdir upload\public\data
Now, we will create a method called save in data_file.rb model file. This
method will be called by the application controller.
name = upload['datafile'].original_filename
directory = "public/data"
# create the file path
path = File.join(directory, name)
# write the file
File.open(path, "wb") { |f| f.write(upload['datafile'].read) }
end
end
The above function will take the CGI object upload and will extract the uploaded
file name using the helper function original_filename and finally, it will store
the uploaded file into the "public/data" directory. You can call the helper function
content_type to know the media type of the uploaded file.
Here File is a ruby object and join is a helper function that will concatenate the
directory name along with the file name and will return the full file path.
Next, to open a file in write mode, we are using the open helper function
provided by the File object. Further, we are reading data from the passed data
file and writing into output file.
Creating Controller
Now, let's create a controller for our upload project:
Now, we will create two controller functions. The first function index will call a
view file to take user input, and the second function uploadFile takes file
information from the user and passes it to the 'DataFile' model. We set the
upload directory to the 'uploads' directory we created earlier "directory = 'data'".
72
Ruby on Rails 2.1
Here, we are calling the function defined in the model file. The render function is
being used to redirect to view file as well as to display a message.
Creating View
Finally, we will create a view file uploadfile.rhtml, which we have mentioned in
the controller. Populate this file with the following code:
<h1>File Upload</h1>
<%= start_form_tag ({:action => 'uploadFile'},
:multipart => true) %>
<p><label for="upload_file">Select File</label> :
<%= file_field 'upload', 'datafile' %></p>
<%= submit_tag "Upload" %>
<%= end_form_tag %>
Here everything is same what we have explained in the earlier chapters. The
only new tag is file_field, which will create a button to select a file from user's
computer.
By setting the multipart parameter to true, you ensure that your action properly
passes along the binary data from the file.
73
Ruby on Rails 2.1
Now, you select a file and upload it. This file will be uploaded into
app/public/data directory with the actual file name and a message will be
displayed saying that "File has been uploaded successfully".
NOTE: If a file with the same name already exists in your output directory, then
it will be overwritten.
Instead of just:
My File.jpg
This is easily handled by File.basename, which strips out everything before the
filename.
def sanitize_filename(file_name)
# get only the filename, not the whole path (from IE)
just_filename = File.basename(file_name)
# replace all none alphanumeric, underscore or perioids
# with underscore
just_filename.sub(/[^\w\.\-]/,'_')
74
Ruby on Rails 2.1
end
def cleanup
File.delete("#{RAILS_ROOT}/dirname/#{@filename}")
if File.exist?("#{RAILS_ROOT}/dirname/#{@filename}")
end
For a complete detail on File object, you need to go through our Ruby
Reference Manual.
75
Ruby on Rails 2.1
15. Sending Emails
Let’s start with creating an emails project using the following command.
Here we are using -d mysql option to specify our interest to use MySQL
database. We can specify any other database name like oracle or postgress using
the -d option. By default, Rails uses SQLite database.
development:
adapter: mysql
encoding: utf8
database: emails
username: root
76
Ruby on Rails 2.1
password: password
host: localhost
test:
adapter: mysql
encoding: utf8
database: emails
username: root
password: password
host: localhost
production:
adapter: mysql
encoding: utf8
database: emails
username: root
password: password
host: localhost
ActionMailer – Configuration
Following are the steps you have to follow to complete your configuration before
proceeding with the actual work.
Go to the config folder of your emails project and open the environment.rb file
and add the following line at the bottom of this file.
ActionMailer::Base.delivery_method = :smtp
It informs the ActionMailer that you want to use the SMTP server. You can also
set it as :sendmail if you are using a Unix-based operating system such as Mac
OS X or Linux.
Add the following lines of code at the bottom of your environment.rb as well.
ActionMailer::Base.smtp_settings = {
:address => "smtp.tutorialspoint.com",
:port => 25,
:domain => "tutorialspoint.com",
:authentication => :login,
77
Ruby on Rails 2.1
Replace each hash value with proper settings for your Simple Mail Transfer
Protocol (SMTP) server. You can take this information from your Internet Service
Provider if you already don't know. You don't need to change port number 25
and authentication type if you are using standard SMTP server.
You may also change the default email message format. If you prefer to send
email in HTML instead of plain text format, add the following line to
config/environment.rb as well:
ActionMailer::Base.default_content_type = "text/html"
Generate a Mailer
Use the following command to generate a mailer as follows:
C:\ruby\> cd emails
C:\ruby\emails> ruby script/generate mailer Emailer
It will create a file emailer.rb in the app/models directory. Check the content of
this file as follows:
Now let's create one method inside the ActionMailer::Base class as follows:
78
Ruby on Rails 2.1
@body["email"] = '[email protected]'
@body["message"] = message
@headers = {}
end
end
The contact method has four parameters: a recipient, a subject, a message, and
a sent_at, which defines when the email is sent. The method also defines six
standard parameters that are a part of every ActionMailer method:
@body is a Ruby hash that contains values with which you can populate
the mail template. You created three key-value pairs: title, email, and
message
@sent_on takes the sent_at parameter and sets the timestamp of the e-
mail.
@headers is another hash that enables you to modify the e-mail headers.
For example, you can set the MIME type of the e-mail if you want to send
either plain text or HTML e-mail.
79
Ruby on Rails 2.1
To deliver e-mail using the mailer's contact method, you have to add deliver_ to
the beginning of the method name. You add a return if request.xhr?, so that you
can escape to Rails Java Script (RJS) if the browser does not support JavaScript
and then instruct the method to render a text message.
You are almost done except to prepare a screen from where you will get the user
information to send email. Let's define one screen method index in the controller
and then in the next section, we will define all the required views:
def index
render :file => 'app\views\emailer\index.html.erb'
end
Defining Views
Define a view in app\views\emails\index.html.erb. This will be called as the
default page for the application and will allow users to enter message and send
the required email:
<h1>Send Email</h1>
<% form_tag :action => 'sendmail' do %>
<p><label for="email_subject">Subject</label>:
<%= text_field 'email', 'subject' %></p>
<p><label for="email_recipient">Recipient</label>:
<%= text_field 'email', 'recipient' %></p>
<p><label for="email_message">Message</label><br/>
<%= text_area 'email', 'message' %></p>
<%= submit_tag "Send" %>
<% end %>
Apart from the above view, we need one more template, which will be used by
the Emailer's contact method while sending message. This is just text with
standard Rails <%= %> placeholders scattered throughout.
80
Ruby on Rails 2.1
Hi!
You are having one email message from <%= @email %> with a title
Thanks
81
Ruby on Rails 2.1
After sending a message, it will display the text message - "Message sent
successfully".
For a complete detail on ActionMailer, please look into the standard Ruby
documentation.
82
Ruby on Rails 2.1
16. RMagick
You can get RMagick by installing the rmagick gen on Unix or rmagick-win32
gem on Windows. Let's install it on a Unix machine as follows:
The RMagick module comes along with class Magick::Image, which lets you
resize images in four different methods:
resize(width, height)
scale(width, height)
sample(width, height)
thumbnail(width, height)
All these methods accept a pair integer values, corresponding to the width and
height in pixels of the thumbnail you want.
Example
Here's an example that uses resize() method to resize the image. It takes the file
tmp.jpg and makes a thumbnail of it 100 pixels wide by 100 pixels tall:
require 'rubygems'
require 'RMagick'
def createThubnail
width, height = 100, 100
img = Magick::Image.read('tmp.jpg').first
thumb = img.resize(width, height)
83
Ruby on Rails 2.1
# thumb.write("mythumbnail.jpg")
Next, we are calling method resize with the desired arguments, which is
creating a thumbnail.
Finally, we are directing this image to the browser. You can also use the
method thumb.write("mythumbnail.jpg") to store this image locally at
your machine.
Example
The following example converts a JPEG file into a GIF file:
require 'rubygems'
require 'RMagick'
def changeFormat
img = Magick::Image.read('tmp.jpg').first
84
Ruby on Rails 2.1
# img.write("mythumbnail.gif")
img = Magick::Image.read("tmp.png").first
img.write("tmp.jpg") # Converts into JPEG
img.write("tmp.gif") # Converts into GIF
img.write("JPG:tmp") # Converts into JPEG
img.write("GIF:tmp") # Converts into GIF
85
Ruby on Rails 2.1
17. HTTP Basic Authentication
To use this authentication, you will need to use SSL for traffic transportation. In
our tutorial, we are going to test it without an SSL.
Let us start with our library example that we have discussed throughout the
tutorial. We do not have much to do to implement authentication. We will add a
few lines in blue in our ~library/app/controllers/book_controller.rb:
def list
@books = Book.find(:all)
end
def show
@book = Book.find(params[:id])
end
def new
@book = Book.new
@subjects = Subject.find(:all)
end
def create
@book = Book.new(params[:book])
if @book.save
redirect_to :action => 'list'
86
Ruby on Rails 2.1
else
@subjects = Subject.find(:all)
render :action => 'new'
end
end
def edit
@book = Book.find(params[:id])
@subjects = Subject.find(:all)
end
def update
@book = Book.find(params[:id])
if @book.update_attributes(params[:book])
redirect_to :action => 'show', :id => @book
else
@subjects = Subject.find(:all)
render :action => 'edit'
end
end
def delete
Book.find(params[:id]).destroy
redirect_to :action => 'list'
end
def show_subjects
@subject = Subject.find(params[:id])
end
private
def authenticate
authenticate_or_request_with_http_basic do |id, password|
id == USER_ID && password == PASSWORD
end
end
87
Ruby on Rails 2.1
end
The first line is just to define the user ID and password to access various
pages.
In the second line, we have put before_filter, which is used to run the
configured method authenticate before any action in the controller. A filter
may be limited to specific actions by declaring the actions to include or
exclude. Both options accept single actions (:only => :index) or arrays of
actions (:except => [:foo, :bar]). So here we have put authentication for
edit and delete operations only.
Due to the second line, whenever you would try to edit or delete a book
record, it will execute private authenticate method.
Now, try to edit or delete any available record, to do so you would have to go
through the authentication process using the following dialogue box.
88
Ruby on Rails 2.1
18. Exception Handling
Execution and exception always go together. If you are opening a file that does
not exist, then you need to handle this situation properly, or your program is
considered to be of substandard quality.
The program stops if an exception occurs. Exceptions are used to handle various
type of errors, which may occur during a program execution and take
appropriate action instead of halting program completely.
Syntax
begin
# -
rescue OneTypeOfException
# -
rescue AnotherTypeOfException
# -
else
# Other exceptions
ensure
# Always will be executed
end
For each rescue clause in the begin block, Ruby compares the raised Exception
against each of the parameters in turn. The match will succeed if the exception
named in the rescue clause is same as the type of the currently thrown
exception, or is a superclass of that exception.
89
Ruby on Rails 2.1
The error reporting to the application is done to a structure called a flash. The
flash is a hash bucket to contain your message until the next request before
being deleted automatically. You can access it with the @flash variable. Given
below is the simplest form of using logger module to log error messages in an
internal file.
begin
.........
rescue Exception => exc
logger.error("Message for the log file #{exc.message}")
flash[:notice] = "Store error message"
redirect_to(:action => 'index')
end
To display all the messages from @flash in your view or layout (.html.erb), you
can add the following:
90
Ruby on Rails 2.1
19. Routes System
Rails parses the URL to determine the controller, action, and parameters for the
request. With Rails routing, parts of the URL can specify additional parameters,
and the entire routing process is under your control. Routing rules work the
same on any web server.
The config/routes.rb file is at the heart of the Rails routing system. This file
contains rules that try to match the URL path of a request and determine where
to direct that request. The rules are tested in the order they are defined in the
file. The first rule to match a request's URL path determines the fate of that
request.
It writes URLs for you for use as arguments to methods like link_to,
redirect_to, and form_tag.
Thus, the routing system knows how to turn a visitor's request URL into a
controller/action sequence. It also knows how to manufacture URL strings based
on your specifications.
Consider the following route installed by Rails when you generate your
application:
map.connect ':controller/:action/:id'
Thus the default routing (if you don't modify the routing rules) is:
http://<base-url>/<controller>/<action>/<id>
91
Ruby on Rails 2.1
The following code block will set up book as the default controller if no other is
specified. It means visiting '/' would invoke the book controller.
ActionController::Routing:Routes.draw do |map|
map.connect ':controller/:action/:id', :controller => 'book'
end
You can also define a default action if no action is specified in the given URL:
ActionController::Routing:Routes.draw do |map|
map.connect ':controller/:action/:id',
:action => 'edit', :controller => 'book'
end
Now, you can all edit methods inside the book controller to edit book with ID as
20 as follows:
http://localhost:3000/2
Route Priority
Routes have priority defined by the order of appearance of the routes in the
routes.rb file. The priority goes from top to bottom.
The last route in that file is at the lowest priority and will be applied last. If no
route matches, 404 is returned.
Now, to call action from the given controller, you would have to write your URL as
follows:
http://localhost:3000/action/controller/id
92
Ruby on Rails 2.1
It's not particularly logical to put action and controller in such sequence. The
original default (the default default) route is better and recommended.
map.connect ':controller/:action/:id.:format'
The .:format at the end matches a literal dot and a wildcard "format" value after
the id field. That means it will match, for example, a URL like this:
http://localhost:3000/book/show/3.xml
Here, inside the controller action, your params[:format] will be set to xml.
The first one will search for welcome action inside main controller even if
you type just http://localhost:3000.
Rails 2.0 introduces a mapper method named root, which becomes the proper
way to define the empty route for a Rails application, like this:
Defining the empty route gives people something to look at when they connect
to your site with nothing but the domain name.
93
Ruby on Rails 2.1
Named Routes
As you continue developing your application, you will probably have a few links
that you use throughout your application. For example, you will probably often
be putting a link back to the main listings page. Instead of having to add the
following line throughout your application, you can instead create a named route
that enables you to link to a shorthand version of that link:
You can define named routes as follows. Here instead of using connect, you are
using a unique name that you can define. In this case, the route is called home.
The rest of the route looks similar to the others you have created.
Here, instead of listing the :controller and :action to which you will be linking,
you are instead putting the name of the route followed by _url. Your user
shouldn't notice any difference. Named routing is merely a convenience for the
Rails developer to save some typing. The above case can be written without the
named route as follows:
Pretty URLs
Routes can generate pretty URLs. For example:
map.connect 'articles/:year/:month/:day',
:controller => 'articles',
:action => 'find_by_date',
:year => /\d{4}/,
:month => /\d{1,2}/,
:day => /\d{1,2}/
# Using the route above, the url below maps to:
# params = {:year => '2005', :month => '11', :day => '06'}
# http://localhost:3000/articles/2005/11/06
Introduction
Before proceeding, let's have a quick look at a few definitions:
The Tests - They are test applications that produce consistent result and
prove that a Rails application does what it is expected to do. Tests are
developed concurrently with the actual application.
The Assertion - This is a one line of code that evaluates an object (or
expression) for expected results. For example – Is this value = that
value? Is this object nil?
The Test Suite - This is a collection of test cases. When you run a test
suite, it will, in turn, execute each test that belongs to it.
Rails Testing
When you run the helper script script/generate to create controllers and models,
Rails generate a framework for unit and functional tests. You can get pretty good
test coverage by filling in the framework with tests for the functionality you
write. There are two important points to test in a Rails application:
This tutorial will cover both the testings in brief. So let's create one testapp to
understand the concept.
Database Setup
Till now, we have used only Rails application's development database, but now
you need to make sure that the testing database is also created and appropriate
sections of your config/database.yml file are set up correctly.
95
Ruby on Rails 2.1
Configuring database.yml:
Configure your config/database.yml as follows:
development:
adapter: mysql
encoding: utf8
database: testapp_development
username: root
password: password
host: localhost
test:
adapter: mysql
encoding: utf8
database: testapp_test
username: root
96
Ruby on Rails 2.1
password: password
host: localhost
production:
adapter: mysql
encoding: utf8
database: testapp_production
username: root
password: password
host: localhost
Generate Migration
Assume you have a table containing books, including their titles, price, and a
small description. The following migration sets up this table:
97
Ruby on Rails 2.1
Testing Models
When you generate a model with the generate script, Rails also generates a unit
test script for the model in the test directory. It also creates a fixture, a YAML file
containing test data to be loaded into the testapp_test database. This is the data
against which your unit tests will run:
As you write code in the model classes, you'll write corresponding tests in these
files. So let's create two test book records using YAML in test/fixtures/books.yml
as follows:
perl_cb:
id: 1
title: 'Ruby Tutorial'
price: 102.00
description : 'This is a nice Ruby tutorial'
java_cb:
id: 2
title: 'Java Programming'
price: 62.00
98
Ruby on Rails 2.1
Now let's replace the existing code in book unit test file test/unit/book_test.rb
with the following code:
def test_book
assert perl_book.save
perl_book_copy = Book.find(perl_book.id)
assert perl_book.save
assert perl_book.destroy
end
end
1. The BookTest method starts off by creating a new Book object using the
title and other fields from the first record in the text fixture/books.yml. The
resulting object is stored in the perl_book instance variable.
2. The first assertion tests that saving the Book object was successful.
3. Next, the book object is retrieved using the find method and stored in
another instance variable named perl_book_copy. The success of this
retrieval is tested in the next assertion, which compares the titles of both
book objects. At this point, we've tested the ability to create and read a
database record.
4. The solution tests updating by assigning a new title to the object stored in
perl_book and then asserts that saving the change is successful.
get
post
put
head
100
Ruby on Rails 2.1
delete
To write a functional test, you need to simulate any of the five HTTP request
types that your controller will process.
Request type "get" and "post" are the most commonly used in controller testing.
All these methods take four arguments:
In this tutorial, we will see how to use get method to test our controller. You can
test rest of the methods in similar way.
When you generate a controller with generate, Rails creates a functional test
script for the controller as follows:
As you write code in the controller classes, you'll write corresponding tests in
these files. Before that, let's define our controller functions list, show,
and search inside app/controllers/book_controller.rb as follows:
def show
@book = Book.find(params[:id])
end
101
Ruby on Rails 2.1
def search
@book = Book.find_by_title(params[:title])
if @book
redirect_to :action => 'show', :id => @book.id
else
flash[:error] = 'No such book available'
redirect_to :action => 'list'
end
end
end
NOTE: You would need two views templates for show and list method. You can
define those views and test them, but right now, we will proceed without
defining those views.
Now let's reuse our test fixture which is in the test/fixtures/books.yml file as
follows:
perl_cb:
id: 1
title: 'Ruby Tutorial'
price: 102.00
description : 'This is a nice Ruby tutorial'
java_cb:
id: 2
title: 'Java Programming'
price: 62.00
description : 'Java Programming for the beginners'
def rescue_action(e)
raise e
end
end
def test_search_book
get :search, :title => 'Ruby Tutorial'
assert_not_nil assigns(:book)
assert_equal books(:perl_cb).title, assigns(:book).title
assert_valid assigns(:book)
assert_redirected_to :action => 'show'
end
def test_search_not_found
get :search, :title => 'HTML Tutorial'
assert_redirected_to :action => 'list'
assert_equal 'No such book available', flash[:error]
end
end
103
Ruby on Rails 2.1
Started
..
Finished in 0.422 seconds.
The next two assertions verify that a Book object was saved in an instance
variable called @book and that the object passes any Active Record
validations that might exist.
The final assertion inside first method tests that the request was
redirected to the controller's show action.
The first assertions test that a redirect to the list action was issued.
$rake test - Test all unit tests and functional tests (and integration tests,
if they exist).
$rake test:recent - Run tests for models and controllers that have been
modified in the last 10 minutes:
104
Ruby on Rails 2.1
105
Ruby on Rails 2.1
21. Quick Reference Guide
Here we have listed all the important functions, scripts, validations, etc.
rake db:test:prepare - Prepare the test database and load the schema.
rake stats - Report code statistics (KLOCs, etc) from the application.
rake tmp:clear - Clear session, cache, and socket files from tmp/
rake tmp:create - Creat tmp directories for sessions, cache, and sockets
Script Description
108
Ruby on Rails 2.1
Script Example
Here is an example to call a script. The following script will start the
development server.
Plugin Description
109
Ruby on Rails 2.1
Generator Description
Given below is a list of options that can be used along with generators:
Model Creation
Model.new # creates a new empty model
Model.create( :field => 'value', :other_field => 42 )
# creates an object with the passed parameters and saves it
110
Ruby on Rails 2.1
Model.find_or_create_by_field( value )
# searches for a record where "field = value", creates
# a new record if not found
User.find_or_create_by_name_and_email( 'ramjoe', '[email protected]')
Model Relations
There are four ways of associating models: has_one, has_many, belongs_to,
and has_and_belongs_to_many. Assuming the following four entities:
111
Ruby on Rails 2.1
end
def Product < ActiveRecord::Base
has_and_belongs_to_many :categories
end
112
Ruby on Rails 2.1
has_many :authorships
has_many :books, :through => :authorships
end
class Authorship < ActiveRecord::Base
belongs_to :author
belongs_to :book
end
class Book < ActiveRecord::Base
has_one :authorship
end
@author = Author.find :first
# selects all books that the author's authorships belong to.
@author.authorships.collect { |a| a.book }
selects all books by using the Authorship join model
@author.books
/world/hello/1?foo=bar
id = params[:id] # 1
foo = params[:foo] # bar
def show
@person = Person.find( params[:id])
113
Ruby on Rails 2.1
end
def index
@posts = Post.find :all
respond_to do |type|
type.html # using defaults, which will render weblog/index.rhtml
type.xml { render :action => "index.rxml" }
type.js { render :action => "index.rjs" }
end
end
The process involves defining a layout template and then letting the controller
know that it exists and is available for use. First, let's create the template.
Add a new file called standard.rhtml to app/views/layouts. You let the controllers
know what template to use by the name of the file, so following a same naming
scheme is advised.
Add the following code to the new standard.rhtml file and save your changes:
114
Ruby on Rails 2.1
<div id="container">
<div id="header">
<h1>Library Info System</h1>
<h3>Library powered by Ruby on Rails</h3>
</div>
<div id="content">
<%= yield -%>
</div>
<div id="sidebar"></div>
</div>
</body>
</html>
Everything you just added are standard HTML elements except two lines. The
stylesheet_link_tag helper method outputs a stylesheet <link>. In this
instance, we are linking the style.css stylesheet. The yield command lets Rails
know that it should put the RHTML for the method called here.
Now open book_controller.rb and add the following line just below the first
line:
115
Ruby on Rails 2.1
Adding a Stylesheet
Till now, we have not created any stylesheet, so Rails is using the default
stylesheet. Now let's create a new file called style.css and save it in
/public/stylesheets. Add the following code to this file.
body {
font-family: Helvetica, Geneva, Arial, sans-serif;
font-size: small;
font-color: #000;
background-color: #fff;
}
a:link, a:active, a:visited {
color: #CD0000;
}
input {
margin-bottom: 5px;
}
p {
116
Ruby on Rails 2.1
line-height: 150%;
}
div#container {
width: 760px;
margin: 0 auto;
}
div#header {
text-align: center;
padding-bottom: 15px;
}
div#content {
float: left;
width: 450px;
padding: 10px;
}
div#content h3 {
margin-top: 15px;
}
ul#books {
list-style-type: none;
}
ul#books li {
line-height: 140%;
}
div#sidebar {
width: 200px;
margin-left: 480px;
}
ul#subjects {
width: 700px;
text-align: center;
padding: 5px;
background-color: #ececec;
117
Ruby on Rails 2.1
Action
# The default. Does not need to be specified
# in a controller method called "some_action"
render :action => 'some_action'
render :action => 'another_action', :layout => false
render :action => 'some_action', :layout => 'another_layout'
118
Ruby on Rails 2.1
Partial
Partials are stored in files called "_subformname" ( _error, _subform, _listitem).
Template
It is more like rendering an action, but it finds the template based on the
template root (app/views).
# renders app/views/weblog/show
render :template => 'weblog/show'
File
render :file => '/path/to/some/file.rhtml'
render :file => '/path/to/some/filenotfound.rhtml',
status => 404, :layout => true
Text
render :text => "Hello World"
render :text => "This is an error", :status => 500
render :text => "Let's use a layout", :layout => true
render :text => 'Specific layout', :layout => 'special'
Inline Template
Uses ERb to render the "miniature" template.
Nothing
render :nothing
render :nothing, :status => 403 # forbidden
RJS
def refresh
render :update do |page|
page.replace_html 'user_list', :partial => 'user',
:collection => @users
page.visual_effect :highlight, 'user_list'
end
end
Form
To create a form tag with the specified action and with POST request, use the
following syntax:
or
120
Ruby on Rails 2.1
Ruby Block
<% end %>
Use :multipart => true to define a MIME-multipart form (for file uploads).
File Upload
Define a multipart form in your view:
def upload
file_field = @params['form']['file'] rescue nil
# file_field is a StringIO object
file_field.content_type # 'text/csv'
file_field.full_original_filename
...
end
Text Fields
To create a text field, use the following syntax:
121
Ruby on Rails 2.1
Text Area
To create a text area, use the following syntax:
<%= text_area "post", "body", "cols" => 20, "rows" => 40%>
Radio Button
To create a Radio Button, use the following syntax:
122
Ruby on Rails 2.1
Checkbox Button
To create a Checkbox Button use the following syntax:
check_box("post", "validated")
Options
To create a dropdown list, use the following syntax:
select("post", "person_id",
Person.find(:all).collect {|p| [ p.name, p.id ] })
123
Ruby on Rails 2.1
This could generate the following code. It depends on what value is available in
your database.
<select name="post[person_id]">
<option value="1">David</option>
<option value="2">Sam</option>
<option value="3">Tobias</option>
</select>
Date Time
Following is the syntax to use data and time:
Builder::XmlMarkup
This class can be used to create XML markup easily. All methods sent to an
XmlMarkup object will be translated to the equivalent XML markup. Any method
with a block will be treated as an XML markup tag with nested markup in the
block.
124
Ruby on Rails 2.1
Example
xm.em("emphasized")
# => <em>emphasized</em>
xm.em { xmm.b("emp & bold") }
# => <em><b>emph & bold</b></em>
xm.a("A Link", "href"=>"http://onestepback.org")
# => <a href="http://onestepback.org">A Link</a>
xm.div { br }
# => <div><br/></div>
xm.target("name"=>"compile", "option"=>"fast")
# => <target option="fast" name="compile"\>
# NOTE: order of attributes is not specified.
xm.instruct!
# <?xml version="1.0" encoding="UTF-8"?>
xm.html { # <html>
xm.head { # <head>
xm.title("History")
# <title>History</title>
} # </head>
xm.body { # <body>
xm.comment! "HI" # <!-- HI -->
xm.h1("Header") # <h1>Header</h1>
xm.p("paragraph") # <p>paragraph</p>
} # </body>
} # </html>
Builder::XmlEvents
This class can be used to create a series of SAX-like XML events (e.g. start_tag,
end_tag) from the markup code.
125
Ruby on Rails 2.1
XmlEvent objects are used in a way similar to the XmlMarkup objects, except
that a series of events are generated and passed to a handler rather than
generating character-based markup.
Example
xe = Builder::XmlEvents.new(hander)
xe.title("HI")
# This sends start_tag/end_tag/text messages to the handler.
start_tag(tag, attrs): Announces that a new tag has been found. tag is
the name of the tag and attrs is a hash of attributes for the tag.
end_tag(tag): Announces that an end tag for tag has been found.
Example
<ul>
<% @products.each do |p| %>
<li><%= @p.name %></li>
<% end %>
</ul>
The output of anything in <%= %> tags is directly copied to the HTML output
stream. To secure against HTML injection, use the h() function to html_escape
the output.
126
Ruby on Rails 2.1
Example
127
Ruby on Rails 2.1
Sessions
To save data across multiple requests, you can use either the session or the
flash hashes. A flash stores a value (normally text) until the next request, while
a session stores data during the complete session.
session[:user] = @user
flash[:message] = "Data was saved successfully"
<%= link_to "login", :action => 'login' unless session[:user] %>
<% if flash[:message] %>
<div><%= h flash[:message] %></div>
<% end %>
Cookies
Following is the syntax for setting cookies:
cookies.delete :user_name
path - The path for which this cookie applies. Defaults to the root of the
application.
validates_presence_of
The following code checks that the last_name and the first_name contain data
and are not NULL.
validates_length_of
The following example shows various validations on a single file. These
validations can be performed separately.
validates_length_of :password,
:minimum => 8 # more than 8 characters
:maximum => 16 # shorter than 16 characters
:in => 8..16 # between 8 and 16 characters
:too_short => 'way too short'
:too_long => 'way to long'
validates_acceptance_of
The following code will accept only 'Y' value for an option field.
validates_acceptance_of :option
129
Ruby on Rails 2.1
validates_confirmation_of
The fields password and password_confirmation must match and will be used as
follows:
validates_confirmation_of :password
validates_uniqueness_of
The following code puts a condition for user_name to be unique.
validates_uniqueness_of :user_name
validates_format_of
The following code validates that a given email ID is in a valid format. It shows
how you can use a regular expression to validate a field.
validates_format_of :email
:with => /^(+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
validates_numericality_of
It validates that a given field is numeric.
validates_numericality_of :value
:only_integer => true
:allow_nil => true
validates_inclusion_of
The following code checks that the passed value is an enumeration and falls in
the given range.
validates_inclusion_of :gender,
:in => %w( m, f )
validates_exclusion_of
The following code checks that the given values do not fall in the given range.
130
Ruby on Rails 2.1
validates_exclusion_of :age
:in => 13..19
validates_inclusion_of
The following code checks that the given values fall in the given range. This is
the opposite of validates_exclusion_of.
validates_inclusion_of :age
:in => 13..19
validates_associated
It validates that the associated object is valid.
:message => 'my own errormessage' Use this to print a custom error
message in case of validation fails.
:on => :create or :update This will be used in such cases where you
want to perform validation only when record is being created or updated.
If you use :create, then this validation works only when there is a create
operation on database.
The following code will return the average age of all the employees.
Person.average :age
The following code will return the maximum age of the employees.
Person.maximum :age
The following code will return the minimum age of the employees.
Person.minimum :age
131
Ruby on Rails 2.1
The following code will return the sum of salaries of all the employees.
The following code will count the number of records having age more than 26.
Person.count
Author.find(50)
The following code will find authors with ID 20, 30 and 40.
Author.find([20,30, 40])
Author.find :all
The following code will find all the authors with first name alam.
Author.find :all
:condition => ["first_name =?", "alam" ]
The following code will find the first record of the authors with first name alam.
Author.find :first
:condition => ["first_name =?", "alam" ]
:order => 'name DESC' Use this option to sort the result in ascending or
descending order.
132
Ruby on Rails 2.1
:joins => LEFT JOIN ...' Additional LEFT JOIN (rarely used).
:include => [:account, :friends] This is LEFT OUTER JOIN with these
model.
If there is a field user_name, then you can use the following to find records by
username.
Person.find_by_user_name(user_name)
If there is a field last_name, then you can use the following to find records by
last name.
Person.find_all_by_last_name(last_name)
If there are fields user_name and password, then you can use the following to
find a record for a given username and password.
Person.find_by_user_name_and_password(user_name, password)
133
Ruby on Rails 2.1
end
134
Ruby on Rails 2.1
Employee.find(:all)
end
end
(-) save
(-) valid?
before_validation
before_validation_on_create
(-) validate
(-) validate_on_create
after_validation
after_validation_on_create
before_save
before_create
(-) create
after_create
after_save
Examples
135
Ruby on Rails 2.1
before_destroy{
|record|Person.destroy_all "firm_id= #{record.id}"
}
before_destroy{
|record|Client.destroy_all "client_of= #{record.id}"
}
end
136