ruby on rails

96
Ruby On Rails Gautam Rege Josh Software Pvt. Ltd.

Post on 11-Sep-2014

32 views

Category:

Documents


2 download

DESCRIPTION

Ruby On Rails basics

TRANSCRIPT

Page 1: Ruby On Rails

Ruby On Rails

Gautam Rege

Josh Software Pvt. Ltd.

Page 2: Ruby On Rails

04/07/23 Rails Training Programme 2

Speaker Introduction

9 years Software Experience BE – PICT Working in rails since 2006 Co-founded Josh Software – 2007 Previous Experience

Cybage, Zensar, Symantec

Page 3: Ruby On Rails

Part – 1 Ruby on Rails Introduction

Page 4: Ruby On Rails

04/07/23 Rails Training Programme 4

History of Ruby

Father of Ruby – Yukihiro Matsumoto, a.k.a. “Matz”, Japan, 1995

Ruby is an Object Oriented Scripting Language

Object Oriented helps in designing applications

Scripting makes it faster and quicker to develop and redeploy.

Page 5: Ruby On Rails

04/07/23 Rails Training Programme 5

Ruby Vs Python

Python was the first OO script but its not a pure OO. There is no real encapsulation.

Indentation !!def foo: print “This is the first line” print “This is second line” print “This is a syntax error”

Serious Ruby Competitor Lots of python plugins and auto-install features Very popular today Caveats:

Python – Why the name?

Page 6: Ruby On Rails

04/07/23 Rails Training Programme 6

Ruby Vs Perl

Perl is really a procedural language. OO Perl was introduced later. Syntax difficult to understand: $ \ @ % Excellent stream parser.. That was the

original purpose. Caveats:

Perl - Practical Extraction and Report Language

Page 7: Ruby On Rails

04/07/23 Rails Training Programme 7

Ruby Vs Perl contd..

foreach $item(@fields) {  if ($db{$item}) {  print "conflict on $item\n";  $err ++;  next;  }  $db{$item} = \@fields; }

fields.each { |item| puts “conflict on #{item}” if fields.include?(item) }

Page 8: Ruby On Rails

04/07/23 Rails Training Programme 8

Features of Ruby

Pure Object Oriented Script No indentation issues. Readable code. Blocks and Iterators Instance and Class variables Caveats:

What is the difference between, Proc, Lamda, a normal function

Page 9: Ruby On Rails

04/07/23 Rails Training Programme 9

What do I choose anyway??

Perl is for people who believe that ‘old is gold’ and are set in their ways.

Python is for ‘veterans’: people more comfortable on unix and vi than on Windows and Word!

Ruby is for ‘enthusiasts’. You treat Ruby like you ‘pet’. You code because you enjoy it, watch it grow AND groom it as you like.

Page 10: Ruby On Rails

04/07/23 Rails Training Programme 10

Overall Comparison

Features Perl Python Ruby

Data Types: Arrays, Hash

Loose Data Typing

Garbage Collection

Weak References (leaks)

Object Oriented Nature

Plug-ins / auto-installation

Web-frameworks cgi/perl Pylons Rails

Page 11: Ruby On Rails

04/07/23 Rails Training Programme 11

Web Technologies

Java – J2EE Python – Pylons, CGI PHP Perl – CGI Ruby – Rails .NET – ASP, C#

Page 12: Ruby On Rails

04/07/23 Rails Training Programme 12

J2EE, .NET Web Development J2EE. .NET are very evolved and very good for

robust and heavy applications. They support different levels of tier architecture –

EJB, databases Excellent Security – application and code Excellent Load Balancing and clustering support

Deployment is complicated Development is slow Very expensive for commercial deployment

Page 13: Ruby On Rails

04/07/23 Rails Training Programme 13

CGI / Perl & PHP

Simple architecture – so very fast WordPress is a PHP (XML-RPC) site Facebook

Very difficult to support multi-tier architecture Security is weak Poor clustering support SQL centric code Typically procedural in nature

Not suited for complicated web applications Very good for simple websites with small dynamic content

Page 14: Ruby On Rails

04/07/23 Rails Training Programme 14

Pylons

Pylons is the Python Web-framework Follows MVC pattern Relatively very new.

Based on Rails architecture

Page 15: Ruby On Rails

04/07/23 Rails Training Programme 15

Ruby on Rails

Pure MVC framework Model View Controller

Evolved over the past 4 years Authentication / Authorization very strong Being slowly adopted for heavy web applications

Page 16: Ruby On Rails

04/07/23 Rails Training Programme 16

Ruby On Rails contd..

Support simple multi-tier architecture Webserver Database Application Server

Good clustering support with Nginx + thin, Apache + passenger

Security at code level is weak i.e. no source code encryption support yet.

Page 17: Ruby On Rails

04/07/23 Rails Training Programme 17

Rails in the Real World

• Who uses Rails today?• Twitter, Facebook Applications• Vastly used as automated QA in large

companies• One of the pioneers of Agile Methodology• JRuby – Java Ruby interpreter

Page 18: Ruby On Rails

Part 2 – Rails Architecture

Page 19: Ruby On Rails

04/07/23 Rails Training Programme 19

Terminologies

MVC Model - View – Controller Design Pattern

REST Representational State Transfer

ORM Object Relational Mapping

Scaffold Building code skeletons.

Migrations Managing the database tables and columns

Page 20: Ruby On Rails

04/07/23 Rails Training Programme 20

Model – View – Controller

Page 21: Ruby On Rails

04/07/23 Rails Training Programme 21

Model - Overview

Maintains state of an object / application. Manages the actual data involved. Validates object information In Rails:

It is directly mapped to the database table via ORM It is independent of Database nuances. Models supports relationships Models have bulk of rails code ActiveRecord

Page 22: Ruby On Rails

04/07/23 Rails Training Programme 22

Controller – Overview

Control the logical flow of the request. Interact with model and render the views In Rails:

Controllers manage authorization, sessions. Controllers decide how the request is processed. Render view according to business logic. ActionController

Page 23: Ruby On Rails

04/07/23 Rails Training Programme 23

View – Overview

Views are HTML renderers Render dynamic pages based on templates.

XML Json HTML JS (Ajax)

In Rails Should contain very less or NO logic Erb (Embedded Ruby ) is supported. ActionView

Page 24: Ruby On Rails

04/07/23 Rails Training Programme 24

MVC in Rails

Page 25: Ruby On Rails

04/07/23 Rails Training Programme 25

Routing in Rails

http://host:port/:controller/:action/:id They determine

Which controller Which action Which object

Custom routes can also be setup.

Page 26: Ruby On Rails

04/07/23 Rails Training Programme 26

A word about RESTfull Rails

Routes: map.resources :teams

Page 27: Ruby On Rails

Session Break

Coffee ?

Page 28: Ruby On Rails

04/07/23 Rails Training Programme 28

Part 2.1 ActiveRecord

Database Connectors Mysql, pgsql, sqlite

ORM Validations Relationships

Page 29: Ruby On Rails

04/07/23 Rails Training Programme 29

Object Relational Mapping

Databasecreate table `customers` (`id` int(11) auto_increment, `name` varchar(64),`age`int,primary key `id`)

Modelclass Customer < ActiveRecord::Baseend

Object accesscust = Customer.createputs “#{cust.name}, #{cust.age}”

Page 30: Ruby On Rails

04/07/23 Rails Training Programme 30

Database “rules”

Rules would mean guidelines. They help in writing lesser code and allow easier access from Rails code

All table names should be plural: customers, products, categories, people

All tables should have `id` as primary key which is an auto_increment

All tables should have ‘_id` suffix as foreign keys. Example: `customer_id` in `products` table

Page 31: Ruby On Rails

04/07/23 Rails Training Programme 31

Database “rules” contd..

All datetime fields should have `_at` suffix. Example: `created_at`

Avoid composite keys use model validations instead They are new supported in Rails 2.1.2 onwards

Model name should be singular. Model Customer maps to `customers` table Model Category maps to `categories` table (!!) Model Person maps to `people` table (!!)

Page 32: Ruby On Rails

04/07/23 Rails Training Programme 32

Part 2.4 Migrations

Migrations are routines which help us manage the database.

Versions are maintained in the database itself in a table called schema_migrations

This controls relationships at model level and not database level.

rake db:migrate

Page 33: Ruby On Rails

04/07/23 Rails Training Programme 33

Example of Migration

class CreateAddresses < ActiveRecord::Migrationdef self.up create_table :addresses do |t|

t.string :street t.integer :zip, :default => 0

t.references :customert.timestamps

endend

def self.downdrop_table :addresses

endend

This creates customer_id field in database.

Relation between Customer and Address is determined by the models.

i.e. class Customer has_one :address

Page 34: Ruby On Rails

04/07/23 Rails Training Programme 34

Rake

Ruby build program similar to ‘make’ Rakefiles (rake‘s version of Makefiles) are

completely defined in standard Ruby syntax. No XML files to edit. No quirky Makefile syntax to worry about (tab or space

issues!) rake –T in rails environment show default tasks User can add new tasks in lib/tasks/filename.rake It loads the rails environment – development,

production or test or custom.

Page 35: Ruby On Rails

Part 3 – Hands-on work

Building a Rails Application

Page 36: Ruby On Rails

04/07/23 Rails Training Programme 36

Ruby on Rails Installation

Install ruby on Windows / Linux. Latest stable version: Ruby 1.8.6 , 1.8.7 Latest version: Ruby 1.9 http://rubyonrails.org/download

Install rubygems Link: http://rubyforge.org/frs/?group_id=126 Latest stable version: 1.3.3

gem install rails Latest stable version: 2.3.2 Recommended: 2.1.2

Install MySQL 5.x Link: http://dev.mysql.com/downloads/mysql/5.1.html#downloads

Page 37: Ruby On Rails

04/07/23 Rails Training Programme 37

Setup the Environment

Ensure installation is good and versions are correct. ruby –v >= 1.8.6 gem –v >= 1.3.2 rails –v >= 2.1.0 mysql –version >= 5.0.x

Editor: Scite Create the rails project

cmd> rails <name> -d mysql

Page 38: Ruby On Rails

04/07/23 Rails Training Programme 38

Rails Project Layout..../app ......../controller ......../helpers ......../models ......../views ............/layouts ..../config ..../components..../db ..../doc ..../lib ..../log ..../public ..../script ..../test ..../tmp ..../vendor......../plugins

Core Application code:Controllers, Helpers, Models, Views

Configuration for database, initializers,routes

Database migrations

Additional or custom libraries, rake tasks etc.

The HTDOC for this web project. This contains JS, CSS, images etc.

External plugins for this project.

Page 39: Ruby On Rails

Session Break

Coffee ?

Page 40: Ruby On Rails

04/07/23 Rails Training Programme 40

ActiveRecord Validations

validate Generic validation method that can be used for

custom validation validates_uniqueness_of :name validates_numericality_of :age validates_presence_of :address validates_format_of :email, :with => <regex>

Page 41: Ruby On Rails

04/07/23 Rails Training Programme 41

ActiveRecord Callbacks

before_create after_create before_save after_save before_update after_update before_destroy after_destroy before_validation after_validation

Page 42: Ruby On Rails

04/07/23 Rails Training Programme 42

ActiveRecord Relations

has_many 1 ↔ m relationship with child

belongs_to 1 ↔ 1 relationship with parent

has_one 1 ↔ 1 relationship with child

has_many :through => Earlier versions: has_and_belongs_to_many m ↔ m relationship with peer

Page 43: Ruby On Rails

04/07/23 Rails Training Programme 43

Database revisit

create table `customers` (`id` int(11) auto_increment, `name` varchar(64),`age`int,

primary key `id`)

create table `addresses` (`id` int(11) auto_increment, `street` varchar(64),`zip_code` varchar(64),`customer_id` int,foreign key customer_id references customer(id)

primary key `id`)

This line is actually not necessary in Rails as migrations handle this.

Page 44: Ruby On Rails

04/07/23 Rails Training Programme 44

has_one ↔ belongs_to

class Customer < ActiveRecord::Basehas_one :address

end

class Address < ActiveRecord::Basebelongs_to :customer

end

cust = Customer.new(:name => ‘Gautam Rege’)address = Address.new(:customer => cust, :street => ‘SB Road’, :zip => ‘411016’)

cust.address => #<Address object>address.customer => # <Customer object>Cust.address.zip => Zip code of address for this customer

Page 45: Ruby On Rails

04/07/23 Rails Training Programme 45

Database revisit

create table `bank_accounts` (`id` int(11) auto_increment,

`acc_number` varchar(64),

`branch` varchar(64),

`customer_id` int,

foreign key customer_id references customer(id)

primary key `id`)

Page 46: Ruby On Rails

04/07/23 Rails Training Programme 46

has_many ↔ belongs_to

class Customer < ActiveRecord::Basehas_many :bank_accounts

end

class BankAccount < ActiveRecord::Basebelongs_to :customer

end

cust = Customer.new(:name => ‘Gautam Rege’)bank = BankAccount.new(:customer => cust, :acc_number => ‘123456’, :branch => ‘XYZ’)

cust.bank_accounts =>[ #<BankAccount object> array ] bank.customer => # <Customer object>

Camelization !!

Page 47: Ruby On Rails

04/07/23 Rails Training Programme 47

Database Revist

create table `products` (`id` int(11) auto_increment, `cost` varchar(64),

primary key `id`)

create table `categories` (`id` int(11) auto_increment, `name` varchar(64),

primary key `id`)

create table `product_categories` (`id` int(11) auto_increment, `product_id` int,`category_id` int

primary key `id`)

Page 48: Ruby On Rails

04/07/23 Rails Training Programme 48

has_many :through =>

class Customer < ActiveRecord::Basehas_many :bank_account_customershas_many :bank_accounts :through => :bank_account_customers

end

class BankAccount < ActiveRecord::Basehas_many : bank_account_customershas_many :customers :through => : bank_account_customers

end

class BankAccountCustomer < ActiveRecord::Basebelongs_to :bank_accountbelongs_to :customer

end

customer.bank_accounts => [ #<BankAccount object> array ]acc.customers => [ #<Customer object> array ]

Page 49: Ruby On Rails

04/07/23 Rails Training Programme 49

Named Scopes

ActiveRecord::NamedScope::Scope A scope represents a narrowing of a

database query Returns a collection but its not an Array. It resembles the association object

constructed by a has_many declaration Unlike arrays, They are “composable” -

named_scopes can be chained!

Page 50: Ruby On Rails

04/07/23 Rails Training Programme 50

Named Scope exampleclass Customer < ActiveRecord::Base

has_many :bank_accounts

named_scope :hni, :conditions => [ ‘hni = ?’ true ]

named_scope :high_risk lambda do | list |{ :joins => ‘risk_customer_lists’, :conditions => [‘name in (?)’, list ] }

End

@customers = Customer.hni

@customers = Customer.hni @customers = @customers.high_risk(terrorists)

@customers = Customer.hni.high_risk(terrorists)

Page 51: Ruby On Rails

04/07/23 Rails Training Programme 51

Hands On!

Creating & updating migrations Adding relationships

Rails console Rails dbconsole

Page 52: Ruby On Rails

Session Break

Coffee ?

Page 53: Ruby On Rails

04/07/23 Rails Training Programme 53

Part 2.2 ActionController

Rails HTTP request processing Helpers Filters Accessing the models Rendering the views

Page 54: Ruby On Rails

04/07/23 Rails Training Programme 54

Processing a HTTP Rails request

http://host:port/:controller/:action/:id http://some.url:3000/customer/show/1

“_controller” suffix in app/controllers customers_controller.rb

All actions are mapped as functions in the controller. “def show”

params[:id] = 1 All views default to

app/views/<controller>/<action>.erb.html app/views/customers/show.html.erb

Page 55: Ruby On Rails

04/07/23 Rails Training Programme 55

Helpers

Helpers are not classes but modules. They mainly assist views with some helper

functions and global etc. Helper methods are accessible in controllers

and views.

Hmm.. Why are helpers not available

to the model?

Page 56: Ruby On Rails

04/07/23 Rails Training Programme 56

Filters

before_filter, after_filter are controller class methods Filters can be used to check authentication, caching, or auditing before

the intended action is performed. Filters have access to the request, response headers

class CustomerController < ApplicationControllerbefore_filter :login_required, :except => [:list, :show]

def login_required # check if user is logged in

end end

Page 57: Ruby On Rails

04/07/23 Rails Training Programme 57

ActionController example

app/controllers/customer_controller.rb:class CustomerController < ApplicationController

def index# default function when no action is called.:redirect_to :action => ‘list’

end

def list@customers = Customer.find(:all)

end

def show@customer = Customer.find(params[:id])

endend

GET and POST parameters are

accessed via params

Page 58: Ruby On Rails

04/07/23 Rails Training Programme 58

Part 2.3 ActionView

Embedded Ruby (erb) Rails Magic

Instance variables (@variables) are copied into and ActionView instance before view invocation

That is why all instance variables created in ActionController are available ‘as is’ to the views.

Page 59: Ruby On Rails

04/07/23 Rails Training Programme 59

Partials

Partials are views which can be rendered in other views.

They are always stored with a ‘_’ prefix _form.erb.html

:render :partial => ‘form’

Page 60: Ruby On Rails

04/07/23 Rails Training Programme 60

Layouts

The basic page layout for all pages. Default layout: application.erb.html Layout can be changed by specifying ‘layout

<name>’ in the controller.

Page 61: Ruby On Rails

04/07/23 Rails Training Programme 61

Rendering Views

Embedded Ruby code without rendering<% %>

Rendering dynamic data<%= %>

Example:<% @customers.each do |cust| %>

Name: <%= cust.name %>

<% end %>

Page 62: Ruby On Rails

04/07/23 Rails Training Programme 62

FormHelpers

<% form_for :customer @customer :url => {:action => :create} do |f| %>

<%= f.text_field :name %>

<%= f.date_select :birth_date %>

<%= submit_tag 'Create' %>

<% end %>

Page 63: Ruby On Rails

04/07/23 Rails Training Programme 63

Ajax on Rails

Link_to_remote Remote_form_for

Rails supports different rendering formats Html Xml Js json

Page 64: Ruby On Rails

Session Break

Coffee ?

Page 65: Ruby On Rails

04/07/23 Rails Training Programme 65

Building a Rails Application

Installing Ruby, rubygems and Rails Rails Project Layout Design the application Write Migrations Generate Scaffold Deploy & Run

Rails helps you build web applications really

fast but YOU STILL HAVE TO DESIGN IT !!

Page 66: Ruby On Rails

Application Idea??

Lets think of one now

Pre-decided

Page 67: Ruby On Rails

04/07/23 Rails Training Programme 67

Survey Application

A survey is a set of questions which a user answers Application should have multiple surveys and a user

should be able to choose any survey. User should be able to see all the questions in the

survey. User should be able to answer one or more

questions. User can choose to leave some questions un-answered.

All answers are free-text

Page 68: Ruby On Rails

04/07/23 Rails Training Programme 68

Survey Application

Result of the survey for a user should be shown.

User can edit his previous answer to some question in a survey

Anyone can see the results of the survey for any user. There is no need of any authentication.

Page 69: Ruby On Rails

04/07/23 Rails Training Programme 69

Is the above too easy ??

Questions can be free-text or multiple choice. User authorization

User should be able to change only his/her answers later Statistical survey data

How many users took which survey? Most popular survey User with maximum surveys

Page 70: Ruby On Rails

04/07/23 Rails Training Programme 70

Survey Application

survey

questions answers

users

Page 71: Ruby On Rails

04/07/23 Rails Training Programme 71

Relationships

A survey has_many questions A question has_many answers A user has_many answers A user has_many surveys A survey has_many users

Page 72: Ruby On Rails

04/07/23 Rails Training Programme 72

Migrations

Survey Migration t.string :name

User Migration T.string :name

User_surveys T.references :user T.references :survey

Page 73: Ruby On Rails

04/07/23 Rails Training Programme 73

Migrations contd..

Questions Migration T.string value T.references :survey

Answer migration T.string :value T.references :question T.references :user

Page 74: Ruby On Rails

04/07/23 Rails Training Programme 74

Scaffolding

Generate scaffolds ./script/generate scaffold Customer

This generates the model, controller, helper and migration for customer

app/models/customer.rb app/controllers/customers_controller.rb App/helpers/customer_helper.rb App/views/customers/*.erb.html Db/migrate/<version>_create_customers.rb

Page 75: Ruby On Rails

04/07/23 Rails Training Programme 75

Checklist

Migrations completed? Model relationships added? Config/database.yml correct? Database created?

rake db:create rake db:migrate

Server started?

Page 76: Ruby On Rails

04/07/23 Rails Training Programme 76

Actual Development (finally)

Add code to controller Add validation to models Modify the views Adding some CSS and JS

Page 77: Ruby On Rails

Session Break

Coffee ?

Page 78: Ruby On Rails

04/07/23 Rails Training Programme 78

Deploying the application

Starting rails server RAILS_ROOT/script/start

Stopping the application ^C

URL: http://localhost:3000 Production Deployment

./script/server -eproduction

Page 79: Ruby On Rails

04/07/23 Rails Training Programme 79

Configuring routes

Resource Maps map.resources :customer => Customer route

http://host:port/customers/new http://host:port/customers/show http://host:port/customers/list

Named Routes map.connect ‘home’, :controller =>

‘customers’, :action => ‘list’ Default routes

Map.connect ‘:controller/:action/:id’

Page 80: Ruby On Rails

04/07/23 Rails Training Programme 80

Enterprise Deployment

Nginx + mongrel Nginx + thin Apache + Passenger Apache + mongrel

Capistrano

Page 81: Ruby On Rails

04/07/23 Rails Training Programme 81

Capistrano – Rails Deployment Capify config/deploy.rb

cap –T deploy cap deploy

Page 82: Ruby On Rails

Session Break

Coffee ?

Page 83: Ruby On Rails

04/07/23 Rails Training Programme 83

Advanced Topics

Behavior Driven Development Test Driven Development Rspec Merb => Rails 3

Page 84: Ruby On Rails

04/07/23 Rails Training Programme 84

Behaviour Driven Development Standard SDLC process defines this. Testing is done after development.

Unit Testing Integration Testing

Iterative cycle for development and testing.

Testing is based on development and not requirements

Takes more time.

Page 85: Ruby On Rails

04/07/23 Rails Training Programme 85

Test Driven Development

Part of Agile Testing and Development go on in parallel

Actually Test Cases are developed before development !!

Tests are based on requirements and not on development

Development is focused on getting tests to pass !

Page 86: Ruby On Rails

04/07/23 Rails Training Programme 86

Rspec

Rspec for Models, Controllers and Views Books for Rspec are still being written ! A lot of specs are clear but clear guidance is

missing still

The Rspec Book – David Chleminsky

Page 87: Ruby On Rails

04/07/23 Rails Training Programme 87

Nuances of Rspec

Describe => the context or object It => test case

Before and after code Helper routines can be added. Pending examples (??)

Page 88: Ruby On Rails

04/07/23 Rails Training Programme 88

Rspec - Typical Example

describe "A new Account" doit "should have a balance of 0" do

account = Account.newaccount.balance.should ==

Money.new(0, :INR)end

End

# rspecA new Account

- should have a balance 0

Page 89: Ruby On Rails

04/07/23 Rails Training Programme 89

Rspec – Pending Examples

Describe “Customer” doIt “should have a address”

It “should have name”

It “should not be on terrorist list”

Done

Note that the it() does not have a code block

Page 90: Ruby On Rails

04/07/23 Rails Training Programme 90

Before & After Code

Before(:each) Before each it() executes

Before(:all) Before all its() only once

After (:each) After each (it) completes

After (:all) After all its are complete

Page 91: Ruby On Rails

04/07/23 Rails Training Programme 91

Before & after code example

Describe Account dobefore(:each)

@customer = Customer.create(‘Gautam’)@account = Account.create(@customer)

end

it “should have balance 0” [email protected] == Money(0, :INR)

end

end

Page 92: Ruby On Rails

04/07/23 Rails Training Programme 92

Helper Routines

Describe Customer, “when risky” dodef get_terror_list

@terror_list = [ ‘Osama’, ‘Laden’, ‘Mahsood’ ]

end

it “should have balance 0” [email protected]?(@terror_list).should be_empty

end

End

Page 93: Ruby On Rails

04/07/23 Rails Training Programme 93

Rspec – further reading

Shared Examples Nested Examples Spec::Mock objects Writing Views specs Writing Model specs Writing controller specs

Page 94: Ruby On Rails

04/07/23 Rails Training Programme 94

Hands On!

rails proj1 -d mysql cd proj1/ ./script/generate rspec ./script/generate rspec_model Stack ./script/generate rspec_controller Stack rake db:create:all RAILS_ENV=test rake db:migrate spec spec

Page 95: Ruby On Rails

04/07/23 Rails Training Programme 95

References

Books Rails Recipes – Chad Fowler

http://www.pragprog.com/titles/fr_rr/rails-recipes Agile Web Development with Rails:

http://www.pragprog.com/titles/rails2/agile-web-development-with-rails

Internet resources http://api.rubyonrails.org http://rubyonrails.org/ http://rubyonrails.org/documentation

Page 96: Ruby On Rails

Thank You!