Transcript Document

1
24
Ruby on Rails
 2008 Pearson Education, Inc. All rights reserved.
2
Convention is the ruler of all.
— Pindar
Where the telescope ends, the microscope begins.
Which of the two has the grander view?
— Victor Hugo
…We grow more partial for the observer’s sake.
— Alexander Pope
 2008 Pearson Education, Inc. All rights reserved.
3
Those who cannot remember the past are
condemned to repeat it.
— George Santayana
Let’s look at the record.
— Alfred Emanuel Smith
All that matters is that the miraculous
become the norm.
— Henry Miller
 2008 Pearson Education, Inc. All rights reserved.
4
OBJECTIVES
In this chapter you will learn:
 Basic Ruby programming.
 How to use the Rails framework.
 The Model-View-Controller paradigm.
 How to use ActiveRecord to model a database.
 How to construct web applications that interact
with a database.
 How to create a web-based message forum.
 How to develop Ajax-enabled applications in Ruby
on Rails.
 How to use the built-in Script.aculo.us library to
add visual effects to your programs.
 2008 Pearson Education, Inc. All rights reserved.
5
24.1
Introduction
24.2
Ruby
24.3
Rails Framework
24.4
ActionController
24.5
A Database-Driven Web Application
24.6
Case Study: Message Forum
and ActionView
24.6.1
Logging In and Logging Out
24.6.2
Embellishing the Models
24.6.3
Generating Scaffold Code
24.6.4
Forum Controller and Forum Views
24.6.5
Message Controller and Message Views
24.6.6
Ajax-Enabled Rails Applications
24.7
Script.aculo.us
24.8
Wrap-Up
24.9
Web Resources
 2008 Pearson Education, Inc. All rights reserved.
6
24.1 Introduction
• Ruby on Rails (also known as RoR or just Rails) is a framework for
developing data-driven web applications.
• A web framework is a set of libraries and useful tool that can be used to build
dynamic web applications.
• Ruby on Rails is different from most other programming languages because it
takes advantage of many conventions to reduce development time. If you
follow these conventions, the Rails framework generates substantial
functionality and perform many tasks for you.
• Ruby on Rails has built-in libraries for performing common web
development tasks, such as interacting with a database, sending mass e-mails
to clients or generating web services.
• Rails has built-in libraries that provide Ajax functionality, improving the user
experience. Rails is quickly becoming a popular environment for web
development.
• Ruby on Rails was created by David Heinemeier Hansson of the company
37Signals.
 2008 Pearson Education, Inc. All rights reserved.
7
24.2 Ruby
• The Ruby scripting language was developed by Yukihiro “Matz” Matsumoto
in 1995 to be a flexible, object-oriented scripting language.
• Ruby’s syntax and conventions are intuitive—they attempt to mimic the way
a developer thinks. Ruby is an interpreted language.
• Instant Rails is a stand-alone Rails development and testing environment that
includes Ruby, Rails, MySQL, Apache, PHP and other components necessary
to create and run Rails applications.
• If you are using Mac OS X, there is an application similar to Instant Rails
called Locomotive.
• The method puts prints the text to the terminal, followed by a newline.
• A method can have parentheses surrounding its parameters, but this is not
typical in Ruby unless they are used to avoid ambiguity.
• A line of Ruby code does not have to end with a semicolon, although one can
be placed there.
• One way to run a Ruby script is to use the Ruby interpreter.
• IRB (Interactive Ruby) can be used to interpret Ruby code statement by
statement.
 2008 Pearson Education, Inc. All rights reserved.
8
Fig. 24.1 | Instant Rails application running.
 2008 Pearson Education, Inc. All rights reserved.
9
24.2 Ruby (Cont.)
• Ruby uses dynamic typing, which allows changes to a variable’s type at
execution time.
• Everything is an object in Ruby, so you can call methods on any piece of data.
• Hash Objects are mapped to other Objects in key/value pairs.
• The exclamation point after a method name is a Ruby convention indicating
that the object on which the method is called will be modified.
• Ruby has support for code blocks—groupings of Ruby statements that can be
passed to a method as an argument.
• The initialize method acts like a constructor in other object-oriented
languages—it is used to declare and initialize an object’s data.
• When each instance of a class maintains its own copy of a variable, the
variable is known as an instance variable and is declared in Ruby using the @
symbol.
• Classes can also have class variables, declared using the @@ symbol, that are
shared by all copies of a class.
• When an object is concatenated with a string, the object’s to_s method is
called to convert the object to its string representation.
 2008 Pearson Education, Inc. All rights reserved.
1
# Fig. 24.2: welcome.rb
2
# Simple Ruby program.
3
puts "Welcome to Ruby!"
Welcome to Ruby!
10
Outline
The puts command writes a
line of text to the console
welcome.rb
 2008 Pearson Education,
Inc. All rights reserved.
11
Fig. 24.3 | Launching the Ruby Interpreter in Instant Rails.
 2008 Pearson Education, Inc. All rights reserved.
12
Fig. 24.4 | Using the Ruby interpreter to run a simple Ruby script.
 2008 Pearson Education, Inc. All rights reserved.
13
Fig. 24.5 | Using Interactive Ruby to execute Ruby statements.
 2008 Pearson Education, Inc. All rights reserved.
1
2
3
# Fig. 24.6: types.rb
# Method calls on numeric and string data
myvar = 5.7 # binds the value 5.7 to myvar
4
5
6
7
8
9
10
puts "The value of myvar is #{myvar}"
11
12
13
14
15
16
myvar = myvar.round # return a rounded value Fixnum
puts "The rounded value of myvar is #{myvar}"
myvar = 5.4 # bind the value 5.4 to myvar
puts "The value of myvar is #{myvar}"
myvar = myvar.round # return a rounded value Fixnum
puts "The rounded value of myvar is #{myvar}"
Ruby uses = as the
Outline
assignment operator
Enclosing a variable in
curly braces ({})preceded
types.rb
by a pound sign (#) causes it
to be interpolated
(1 of 2)
14
You can call the round method on
any variable of type Fixnum
myvar = "mystring" # bind the value 'mystring' to myvar
puts "The value of myvar is '#{myvar}'"
Ruby variables are dynamically
typed, so variables have no
explicit type, but can hold any
type of data at any time
 2008 Pearson Education,
Inc. All rights reserved.
17
15
18 myvar = myvar.capitalize # capitalize the value of myvar
19 puts "The capitalized form of myvar is '#{myvar}'"
The
20
21 myvar = "my string" # bind the value 'my string' to
capitalize
method capitalizes the
myvar
first letter of a string
22 puts "The value of myvar is '#{myvar}'"
23
24 myvar = myvar.capitalize # capitalize the value of myvar
25 puts "The capitalized form of myvar is '#{myvar}'"
The
The
The
The
The
The
The
The
Outline
types.rb
(2 of 2)
value of myvar is 5.7
rounded value of myvar is 6
value of myvar is 5.4
rounded value of myvar is 5
value of myvar is 'mystring'
capitalized form of myvar is 'Mystring'
value of myvar is 'my string'
capitalized form of myvar is 'My string'
 2008 Pearson Education,
Inc. All rights reserved.
1
# Fig. 24.7: arraysAndHashes.rb
2
# Arrays and hashes in Ruby.
3
fruits = [ "mango", "orange",
4
puts "The length of the fruits array is #{fruits.length}" # output
5
puts "The first fruit is #{fruits[0]}" # output first element
6
puts "The last fruit is #{fruits[-1]}\n\n" # output last element
16
"apple", "pear" ] # create an array
Arrays can be created
lengthusing comma-separated
lists in square brackets
7
8
fruits.reverse! # reverse the order of the elements in the fruits array
9
puts "The length of the fruits array is #{fruits.length}" # output length
10 puts "The first fruit is #{fruits[0]}" # output first element
11 puts "The last fruit is #{fruits[-1]}\n\n" # output last element
12
13 # a simple hash
14 food = { "mango" => "fruit", "banana" => "fruit", "onion" => "vegetable"
15 puts "The length of the food hash is #{food.length}" # output length
16 puts "A mango is a #{food["mango"]}" # output value of key mango
17 puts "An onion is a #{food["onion"]}" # output value of key onion
The length of the fruits array is 4
The first fruit is mango
the last fruit is pear
The length of the fruits array is 4
The first fruit is pear
the last fruit is mango
The length of the food hash is 3
A mango is a fruit
An onion is a vegetable
Outline
arraysAndHashes
.rb
The length of an array
is stored in its length
Elements are accessed
property
using square bracket
notation; You can also
access items starting
}
from the end of the
array using negative
indices
You can create a hash, which
stores key-value pairs, by
separating keys from values
with the => operator and
enclosing the list in curly
braces
 2008 Pearson Education,
Inc. All rights reserved.
1
# Fig. 24.8: controlStatements.rb
2
# Conditionals, loops, and codeblocks.
3
def letter_grade( x ) # define method letterGrade
4
5
if x >= 90 # if x is greater than or equal to 90
"A" # grade is A
6
elsif x >= 80 # if x is greater than or equal to 80
7
8
9
10
11
12
"B" # grade is B
elsif x >= 70 # if x is greater than or equal to 70
"C" # grade is C
elsif x >= 60 # if x is greater than or equal to 60
"D" # grade is D
else # grade is less than 60
13
"F" # grade is F
14
end # if
15 end # method letterGrade
16
17
Outline
Control
Statements.rb
Methods are defined using
the def keyword, and
method definitions end
with the end keyword
17 students = { "John" => 100, "Sue" => 92, "Tom" => 56, "Jill" => 80 }
18
19 students.each() { |key, value| # display the letter grade for each student
20
puts "#{key} received a #{letter_grade(value)}"
21 } # end codeblock
Jill received a B
Sue received a A
John received a A
Tom received a F
The each method can be used
on arrays to iterate through
their elements.
The parameters of a code
block are placed between
pipe characters (||)at the
beginning of the block
 2008 Pearson Education,
Inc. All rights reserved.
1
# Fig. 24.9: Classes.rb
2
3
# A Ruby class.
class Point
4
@@num_points = 0 # initialize numPoints
5
6
7
8
# create a new Point object
def initialize(x, y)
@x = x # initialize x-coordinate
9
@y = y # initialize y-coordinate
18
Classes are defined
beginning with the class
keyword and ending with the
end keyword
Outline
Classes.rb
Class variables are preceded
(1 of 2)
by @@
Create a constructor by
10
11
12
@@num_points +=1 # increment numPoints counter
end # method initialize
13
14
15
# return a string containing the x-y values
def to_s
Every
return "x: #{@x}; y: #{@y}"
16
end # method to_s
defining an initialize
Instance
variables are
method
preceded by @
class has a to_s
method that returns a string
representation of the object.
This class overrides its to_s
method
 2008 Pearson Education,
Inc. All rights reserved.
17
19
18
# return how many Points have been instantiated
19
def num_points
20
21
return @@num_points
end # method numPoints
22 end # class Point
23
24 p = Point.new( 8, 9 ) # instantiate a Point
25 q = Point.new( 1, 1 ) # instantiate another Point
26 puts "the value of p is '#{p}'"
27 puts "the value of q is '#{q}'"
28 puts "the number of points created is #{p.num_points}"
the value of p is 'x: 8; y: 9'
the value of q is 'x: 1; y: 1'
the number of points created is 2
Outline
Classes.rb
(2 of 2)
Create an instance using the
class name and new,
supplying any arguments
required by the constructor
 2008 Pearson Education,
Inc. All rights reserved.
20
24.3 Rails Framework
• While users have benefitted from the rise of database-driven web
applications, web developers have had to implement rich functionality
with technology that was not designed for this purpose.
• The Rails framework combines the simplicity of development that has
become associated with Ruby with the ability to rapidly develop
database-driven web applications.
• Ruby on Rails is built on the philosophy of convention over
configuration—if you follow certain programming idioms, your
applications will require little or no configuration and Rails will
generate substantial portions of the applications for you.
• The Model-View-Controller (MVC) architectural pattern separates
application data (contained in the model) from graphical presentation
components (the view) and input-processing logic (the controller).
• ActiveRecord is used to map a database table to an object.
• ActionView is a set of helper methods to modify user interfaces.
• ActionController is a set of helper methods to create controllers.
 2008 Pearson Education, Inc. All rights reserved.
21
Fig. 24.10 | Model-View-Controller architecture.
 2008 Pearson Education, Inc. All rights reserved.
22
Fig. 24.11 | Rails directory structure for a new Rails application.
 2008 Pearson Education, Inc. All rights reserved.
23
24.4 ActionController and ActionView
• Ruby on Rails has two classes, ActionController and ActionView, that work
together to process a client request and render a view.
• To generate a controller in Rails, you can use the built-in Controller generator
by typing ruby script/generate controller name.
• A Ruby on Rails application must be run from a web server
• Instant Rails comes with a built-in web server named Mongrel, which is easy to use to
test Rails applications on the local machine.
• When generating output, a controller usually renders a template—an XHTML
document with embedded Ruby that has the .rhtml filename extension.
• The request object contains the environment variables and other information for a
web page.
• Erb (embedded Ruby) that is located between the <%= %> tags in rhtml files is parsed
as Ruby code and formatted as text.
• A set of Ruby tags without an equals sign—<% %>—represents statements to execute
as Ruby code but not formatted as text.
• Rails allows you to add headers and footers with a layout—a master view that is
displayed by every method in a controller.
• A layout can generate a template for a specific method using yield.
 2008 Pearson Education, Inc. All rights reserved.
1
# Fig. 24.12: app/controllers/welcome_controller.rb
2
# Simple controller that renders a message on a web page.
3
class WelcomeController < ApplicationController
4
# render text in page
5
def index
6
7
8
render :text => "Welcome to Ruby on Rails!"
end # method index
end # class WelcomeController
24
Outline
app/controllers/
Call the render method,
welcome_
specifying its parameter controller.rb
using the text symbol
 2008 Pearson Education,
Inc. All rights reserved.
25
Fig. 24.13 | Starting the Mongrel web server.
 2008 Pearson Education, Inc. All rights reserved.
1
# Fig. 24.14: app/controllers/welcome_controller.rb
2
# Simple controller that passes a parameter to the view.
3
class WelcomeController < ApplicationController
4
# set server_name to server information
5
def hello
6
7
8
@server_name = request.server_software # retrieve software of server
end # method hello
end # class WelcomeController
26
Outline
app/controllers/
welcome_
controller.rb
Define a class variable in the
controller that contains
information about the server
 2008 Pearson Education,
Inc. All rights reserved.
1
<?xml version = "1.0" encoding = "utf-8"?>
2
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
3
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
27
Outline
4
5
<!-- Fig. 24.15: app/views/welcome/hello.rhtml -->
6
<!-- View that displays the server name. -->
7
<html xmlns = "http://www.w3.org/1999/xhtml">
8
<head>
9
app/views/welcome
/hello.rhtml
<title>hello</title>
10 </head>
11 <body style = "background-color: lightyellow">
12
<strong>Hello from the view!</strong><br />
13
The server you are coming from is
14
<em><%= @server_name %></em>
15 </body>
16 </html>
The view has access to the
controller’s class variables
 2008 Pearson Education,
Inc. All rights reserved.
1
<?xml version = "1.0" encoding = "utf-8"?>
2
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
3
28
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
Outline
4
5
<!-- Fig. 24.16: app/views/layouts/welcome.rhtml -->
6
<!-- Layout that displays a greeting. -->
7
<html xmlns = "http://www.w3.org/1999/xhtml">
8
<head>
9
app/views/layouts
/welcome.rhtml
<title><%= controller.action_name %></title>
10 </head>
11 <body style = "background-color: lightyellow">
12
Hello from the Layout!<br />
13
<hr />
14
<%= yield %> <!-- render template -->
15 </body>
16 </html>
A controller’s action_name
method displays the action
that is currently being called
The layout yields to the view
associated with the current action
 2008 Pearson Education,
Inc. All rights reserved.
29
Fig. 24.17 | Creating a model in the Ruby Console.
 2008 Pearson Education, Inc. All rights reserved.
30
24.5 A Database-Driven Web Application
• Rails makes extensive use of Object-Relational Mapping (ORM) that
maps a database to application objects.
• The objects that Rails uses to encapsulate a database inherit from
ActiveRecord.
• One ActiveRecord convention is that every model that extends
ActiveRecord::Base in an application represents a table in a
database.
• By convention, the table that the model represents has a name which
is the lowercase, pluralized form of the model’s name.
• Rails uses a generator to create the Employee model. You use a
generator by typing ruby script/generate model employee
in the Ruby Console, after navigating to your application directory.
 2008 Pearson Education, Inc. All rights reserved.
31
24.5 A Database-Driven Web Application
(Cont.)
• The ActiveRecord object has a special feature called Migration,
which allows you to perform database operations within Rails.
• ActiveRecord has built-in functionality for many create, retrieve,
update and destroy methods known in Rails as CRUD.
• We can execute the migration using Ruby’s rake command by typing
rake db:migrate, which will call the self.up method of all the
migrations located in your db/migrate directory.
• If you ever want to roll back the migrations, you can type rake
db:migrate VERSION=0, which calls each migration’s
self.down method.
• The scaffold method is a powerful tool that automatically creates
CRUD functionality. It creates methods such as new, edit and list
so you don’t have to create them yourself.
 2008 Pearson Education, Inc. All rights reserved.
1
2
# Fig. 24.18: db/migrate/001_create_employees.rb
# Database migration script modified to add data to the table
3
4
class CreateEmployees < ActiveRecord::Migration
# create the table with three columns and insert some rows.
5
6
7
8
9
10
11
12
13
14
15
16
def self.up
create_table :employees do |t|
t.column :first_name, :string
t.column :last_name, :string
t.column :job_title, :string
Outline
The up method in a migration
does the work on the database
db/migrate/001_
create_employees
We create a table .rb
in the
database with three columns
containing strings
end # do block
Employee.create :first_name => "Sue", :last_name => "Green",
:job_title => "Programmer"
Employee.create :first_name => "Meg", :last_name => "Gold",
:job_title => "Programmer"
Employee.create :first_name => "John", :last_name => "Gray",
17
18
:job_title => "Programmer"
end # method self.up
19
20
21
# reverse the migration, delete the table that was created
def self.down
22
32
drop_table :employees
23
end # method self.down
24 end # class CreateEmployees
Create three entries in
the table, specifying
values for each field
The down method undoes
what the up method did so
that you can roll changes
forward
and we
back
To undo the
changes,
simply drop the table
 2008 Pearson Education,
Inc. All rights reserved.
33
Common Programming Error 24.1
If the code that comes after the creation of the table in the
self.up is erroneous, the migration will fail, and will not
be able to execute again because the table will already exist.
Also, Rails will not have marked the migration as
successfully completed, so the version will still be 0 and the
migration cannot be rolled back. One way to prevent this
problem is to force the table to be dropped every time
before creating it. Another solution is splitting up the
migration into smaller discrete migrations, one to create
the table and another to insert data in the table.
 2008 Pearson Education, Inc. All rights reserved.
1
# Fig. 24.19: employee.rb
2
# Generated code for an Employee Model.
3
class Employee < ActiveRecord::Base
4
end # class Employee
34
Outline
employee.rb
 2008 Pearson Education,
Inc. All rights reserved.
1
# Fig. 24.20: app/controllers/employees_controller.rb
2
# Provides all of the functionality for the application.
3
4
class EmployeesController < ApplicationController
scaffold :employee # create scaffold code for controller
35
Outline
The scaffold method dynamically
generates any CRUD methods that
are not already defined
in the
app/controllers/
controller
employees_contro
5
6
# override scaffold list method
7
8
def list
@employees = Employee.find( :all ) # return an array of Employees
9
end # method list
10 end # class EmployeeController
ller.rb
Our list method (called when the
list action is invoked) creates an
array of all employees so that the
view can display them
 2008 Pearson Education,
Inc. All rights reserved.
36
Fig. 24.21 | View of the new action when generated by the scaffold.
 2008 Pearson Education, Inc. All rights reserved.
1
<?xml version = "1.0" encoding = "utf-8"?>
2
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
3
37
Outline
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
4
5
<!-- Fig. 24.22 app/views/employees/list.rhtml -->
6
<!-- A view that displays a list of Employees. -->
7
<html xmlns = "http://www.w3.org/1999/xhtml">
8
<head>
9
app/views/
employees/list
.rhtml
<title>List of Employees</title>
10 </head>
11 <body style="background-color: lightyellow">
12
<h1>List of Employees</h1>
13
<ol>
14
<% for employee in @employees %>
15
<!-- create a list item for every employee with his full name -->
16
Loop through each employee in
the database
<li><%= employee.first_name %> <%= employee.last_name %></li>
17
<% end %>
18
</ol>
19 </body>
20 </html>
Access each employee’s first and
last name as properties of the
current employee object
 2008 Pearson Education,
Inc. All rights reserved.
38
24.6 Case Study: Message Form
• Validators that will be called when the database is modified, can be applied to an object
that inherits from ActiveRecord.
• The method validates_presence_of ensures that all the fields specified by its
parameters are not empty.
• The method validates_format_of matches all the fields specified by its
parameters with a regular expression.
• The link_to method is used to link to an action in the controller and pass arguments
to it.
• A partial is a block of HTML and embedded Ruby code stored in another file and
inserted directly into the document.
• Rails includes a JavaScript library called Prototype that contains easy-to-use crossbrowser Ajax functions.
• The javascript_include_tag helper method is used to link in JavaScript
libraries.
• The link_to_remote method allows us to link to JavaScript that we included in the
layout file.
• Specifying the url and update parameters inside the link_to_remote method
tells Rails to convert these tags into prototype Ajax.Updater objects that will update
the page asynchronously.
 2008 Pearson Education, Inc. All rights reserved.
1
# Fig. 24.23: db/migrate/001_create_users.rb
2
# Database migration script modified to add data to the table.
3
class CreateUsers < ActiveRecord::Migration
4
# create and configure users table
5
def self.up
6
create_table :users do |t|
7
t.column :name, :string, :limit => 11
8
t.column :password, :string
9
39
Outline
Create a database
table to store users
db/migrate/001_
create_users.rb
end # do block
10
11
12
User.create :name => "user1", :password => "54321"
Create a test user
end # method self.up
13
14
# remove users table
15
def self.down
16
drop_table :users
17
end # method self.down
18 end # class CreateUsers
 2008 Pearson Education,
Inc. All rights reserved.
40
Common Programming Error 24.2
Creating a column without explicitly
specifying a limit on length will cause
Rails to truncate the data entered into
the database with database-defined limits.
 2008 Pearson Education, Inc. All rights reserved.
1
# Fig. 24.24: app/models/user.rb
2
# Generated code for the User model.
3
class User < ActiveRecord::Base
4
end # method User
41
Outline
app/models/user
.rb
 2008 Pearson Education,
Inc. All rights reserved.
1
# Fig. 24.25: app/controllers/users_controller.rb
2
# UsersController provides validation functionality for the table.
3
class UsersController < ApplicationController
4
# create a new User object
5
def admin
6
42
The admin action
creates a new User
@user = User.new # create a new User object
7
8
end # method admin
9
10
# validate that user exists
def validate
11
12
13
14
# find a user with the correct name and password
@user = User.find_by_name_and_password( params[ :user ][ :name ],
params[ :user ][ :password ] )
15
16
17
18
19
20
if ( @user == nil ) # if the user dosn’t exist
redirect_to :action => "admin" # redirect to admin action
else # user does exist
session[ :user ] = @user # store the user in a session variable
redirect_to :controller => "forums", :action => "index"
end # if
21
22
23
end # method validate
24
def logout
Outline
app/controllers/
users_controller
.rb
The validate
action implements a
login attempt
If the login is successful,
store the User object in a
session variable
# log user out
25
reset_session # delete all session variables
26
redirect_to :controller => "forums", :action => "index" # redirect
27
end # method logout
28 end # class UserController
 2008 Pearson Education,
Inc. All rights reserved.
43
Performance Tip 24.1
Storing full objects in the session is
inefficient. The user object is one of the
rare exceptions, because it doesn’t
change very often and is frequently
needed in web applications that manage
the state information for unique clients.
 2008 Pearson Education, Inc. All rights reserved.
1
<!-- Fig. 24.26: app/views/users/admin.rhtml -->
2
<!-- Login form used to send data to the user controller. -->
3
<h1>Please Log In</h1>
4
<% form_tag :action => 'validate' do %> <!-- create form tag -->
5
<p><label for="user_name">Name</label><br/>
6
<%= text_field 'user', 'name'
44
%></p> <!-- create input tag -->
Outline
The login form submits to the
validate action, where the
login information
is processed
app/views/users/
admin.rhtml
7
8
<p><label for="user_password">Password</label><br/>
9
<%= password_field 'user', 'password'
10
<%= submit_tag "Sign In" %> <!-- create submit tag -->
11 <% end %> <!-- create an end form tag -->
%></p> <!-- create input tag -->
Both fields specify a
model and a column to
which they correspond
 2008 Pearson Education,
Inc. All rights reserved.
1
<?xml version = "1.0" encoding = "utf-8"?>
2
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
3
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
45
Outline
4
5
<!-- Fig. 24.27: app/views/layouts/users.rhtml-->
6
<!-- Display the name of the current action in the title bar -->
7
<html xmlns = "http://www.w3.org/1999/xhtml">
8
<head>
9
app/views/
layouts/users
.rhtml
<title>Users: <%= controller.action_name %></title>
10 </head>
11 <body>
12
<%= yield %>
13 </body>
14 </html>
 2008 Pearson Education,
Inc. All rights reserved.
1
# Fig. 24.28: db/migrate/002_create_messages.rb
2
# Database migration script modified to add data to the table.
3
class CreateMessages < ActiveRecord::Migration
4
# create and configure messages table
5
6
def self.up
create_table :messages, do |t|
7
8
t.column :title, :string, :limit => 64
t.column :author, :string, :limit => 20
9
t.column :created_on, :timestamp
10
11
t.column :email, :string, :limit => 40
t.column :message, :text
12
13
t.column :forum_id, :integer
end # do block
14
15
16
Message.create :title => "Welcome to the Fourth Edition",
:author => "Bob Green",
17
18
46
Outline
db/migrate/002_
create_messages
.rb
:email => "[email protected]",
:message => "We hope you enjoy the book.",
19
20
21
:forum_id => 2
end # method self.up
22
23
# remove messages table
def self.down
24
drop_table :messages
25
end # method self.down
26 end # class CreateForums
 2008 Pearson Education,
Inc. All rights reserved.
1
# Fig. 24.29: app/models/message.rb
2
# Message Model containing validation and initialization functionality.
3
class Message < ActiveRecord::Base
4
belongs_to :forum # adds a forum method to Message
5
47
Specify that each Message
belongs to a Forum
6
# validators (validates automatically before ActiveRecord.save)
7
validates_presence_of :title, :author, :email, :message
8
validates_format_of :email,
9
Outline
app/models/
message.rb
:with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
10 end # class Message
Validators make sure that a
Message is not created
unless the title, author,
email, and message are
defined, and the email is
properly formatted
 2008 Pearson Education,
Inc. All rights reserved.
1
# Fig. 24.30 db/migrate/003_create_forums.rb
2
# Database migration script modified to add data to the table.
3
4
class CreateForums < ActiveRecord::Migration
# Create and configure forums table
5
6
7
8
def self.up
create_table :forums do |t|
t.column :name, :string, :limit => 64
t.column :administrator, :string, :limit => 20
9
10
11
t.column :created_on, :timestamp
end # do block
12
13
Forum.create :name => "Ruby On Rails",
:administrator => "user1"
14
15
Forum.create :name => "Internet and World Wide Web: 4th Edition",
:administrator => "user1"
16
17
48
Outline
db/migrate/003_
create_forums.rb
end # method self.up
18
# remove forums table
19
def self.down
20
drop_table :forums
21
end # method self.down
22 end # class CreateForums
 2008 Pearson Education,
Inc. All rights reserved.
1
# Fig. 24.31: app/models/forum.rb
2
# Forum model that includes validation and initialization functionality.
3
class Forum < ActiveRecord::Base
49
4
has_many :messages, :dependent => :destroy
5
validates_presence_of :name
6
Outline
app/models/forum
.rb
end # class Forum
A forum model is a container
for multiple message objects
When a forum is destroyed,
all of its messages are
destroyed with it
 2008 Pearson Education,
Inc. All rights reserved.
1
# Fig. 24.32: app/controllers/forums_controller.rb
2
# ForumsController implements CRUD functionality.
3
class ForumsController < ApplicationController
4
5
50
Outline
verify :method => :post, :only => [ :destroy, :create ],
:redirect_to => { :action => :list }
6
7
8
9
10
# shortcut to the list method
def index
list
render :action => 'list'
11
12
13
14
end # method index
15
16
17
18
19
20
@forums = Forum.find( :all )
end # method list
21
22
23
app/controllers/
forums_
controller.rb
Ensure that anything modifying
the database is sent to the server
(1 of 2)
as a POST request
# set up the list web page that lists all forums
def list
Go back to the list page once
a change has been submitted
# set up the new web page that adds a new forum
def new
if ( session[ :user ] == nil ) # if user is not logged in
Use flash to display an
error at the top of the page if
the user is not logged in
flash[ :error ] = 'you must be logged in to complete this action'
redirect_to :action => "index" and return
end # if
24
25
26
27
28
@forum = Forum.new
end # method new
# attempt to create a new forum with the parameters passed in
 2008 Pearson Education,
Inc. All rights reserved.
29
30
31
32
33
def create
@forum = Forum.new( params[ :forum ] )
51
Outline
@forum.administrator = session[ :user ].name
if @forum.save # if save method was successful
34
35
36
37
38
39
40
flash[ :notice ] = 'Forum was successfully created.'
redirect_to :action => 'list'
else # save was unsuccessful
render :action => 'new' # go to new
Notify the user that their
end # if...else
action was successful
end # method create
41
42
43
44
45
# set up the delete web page
def delete
if ( session[ :user ] == nil ) # if user is not logged in
flash[ :error ] = 'you must be logged in to complete this action'
redirect_to :action => "index" and return
46
47
48
49
50
51
52
53
54
else
@forums = Forum.find( :all,
:conditions => "administrator = '#{ session[:user].name }'" )
end # if else
end # method delete
# delete a forum with a specified parameter
def destroy
# find the forum and delete it
app/controllers/
forums_
controller.rb
(2 of 2)
Only allow the user to
see a list of forums to
delete if the user is an
administrator
Delete a forum and redirect to
the list page
55
Forum.destroy( params[ :forum ][ :id ] ) # delete the forum
56
redirect_to :action => 'list' # redirect to list
57
end # method destroy
58 end # class ForumsController
 2008 Pearson Education,
Inc. All rights reserved.
1
2
<!-- Fig. 24.33: app/views/forums/list.rhtml -->
<!-- Template for the list action that displays a list of forums. -->
3
4
<h1>Deitel Message Forums</h1>
<h2>Available Forums</h2>
5
6
7
8
9
<ul>
<% for forum in @forums %>
<!-- create a list item for every forum -->
<li>
<!-- link to list action in messages -->
10
11
12
13
52
Outline
Use the @forums array
(defined in the controller) to
app/views/forums
create a list of all
<%= link_to ( forum.name, {:controller => 'messages',
:action => 'list', :forum_id => forum.id},
{ :class => (forum.created_on < 5.minutes.ago ?
/list.rhtml
(1 of 2)
'recent': nil ) } ) %>
14
</li>
15
<% end %> <!-- end for -->
16 </ul>
17 <% if ( session[ :user ] ) then %>
18
<!-- a user is logged in -->
19
20
21
22
<h2>Forum Management</h2>
<ul>
<li><%= link_to 'Add a Forum', :action => 'new' %></li>
<li><%= link_to 'Delete a Forum', :action => 'delete' %></li>
23
</ul>
24 <% end %> <!-- end if -->
 2008 Pearson Education,
Inc. All rights reserved.
53
Outline
app/views/forums
/list.rhtml
(2 of 2)
 2008 Pearson Education,
Inc. All rights reserved.
1
<!-- Fig. 24.34 app/views/forums/new.rhtml -->
2
<!-- Template for a new action that adds a forum to the forums table. -->
3
<h1>New forum</h1>
4
<% form_tag :action => 'create' do %>
5
<%= render :partial => 'form' %>
6
<%= submit_tag "Create" %>
7
<% end %>
54
Outline
app/views/forums
/new.rhtml
8
9
<%= link_to 'Back', :action => 'list' %>
The render :partial method
inserts the contents of a partial file
(in this case _form.rhtml) into
a document
 2008 Pearson Education,
Inc. All rights reserved.
1
<!-- Fig. 24.35: app/views/forums/_form.rhtml -->
2
<!-- Partial that contains a form used to add a new forum. -->
3
<%= error_messages_for 'forum' %>
4
<p><label for="forum_name">Name</label><br/>
5
<%= text_field 'forum', 'name'
55
Outline
%></p>
app/views/forums
/_form.rhtml
 2008 Pearson Education,
Inc. All rights reserved.
1
<!-- Fig. 24.36: app/views/forums/delete.rhtml -->
2
<!-- Template for delete action used to delete a Forum. -->
3
<h1>Delete a Forum</h1><br />
56
Outline
4
5
<% form_tag
:action => :destroy do %> <!-- create from tag -->
6
<p><label for="forum_id">Forum Name</label><br />
7
<%= collection_select "forum", "id", @forums, "id", "name" %></p>
8
<%= submit_tag "Delete" %> <!-- create submit tag -->
9
<% end %> <!-- create end form tag -->
10
11 <%= link_to 'Back', :action => 'list' %> <!-- link back to list
app/views/forums
/delete.rhtml
Use the collection_select
method to generate a dropdown
method
--> menu from the @forms
array.
 2008 Pearson Education,
Inc. All rights reserved.
1
<?xml version = "1.0" encoding = "utf-8"?>
2
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
3
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
57
Outline
4
5
<!-- Fig. 24.37: app/views/layouts/forums.rhtml -->
6
<!-- Layout that displays the logged-in user for every Forums action. -->
7
<html xmlns = "http://www.w3.org/1999/xhtml">
8
<head>
9
<title>Forums: <%= controller.action_name %></title>
10
<%= stylesheet_link_tag 'scaffold' %> <!-- link to a stylesheet -->
app/views/layouts
/forums.rhtml
(1 to 2)
11 </head>
12 <body>
13
14
15
<div style = "text-align: right">
<% if ( session[ :user ] ) then %> <!-- if user is logged on -->
<!-- code to display if user is logged on -->
 2008 Pearson Education,
Inc. All rights reserved.
16
<%= "Logged In As #{ session[ :user ].name }: " %>
17
<%= link_to 'Log Out',
:controller => 'users', :action => 'logout' %>
18
19
Outline
<% else %> <!-- user is not logged on -->
20
<!-- code to display if user is not logged on -->
21
<%= "Not Currently Logged In:" %>
22
<%= link_to 'Log In',
app/views/layouts
/forums.rhtml
:controller => 'users', :action => 'admin' %>
23
24
58
<% end %> <!-- end if -->
25
</div>
26
<p style="color: green"><%= flash[ :notice ] %></p>
27
<p style="color: red"><%= flash[ :error ] %></p>
(2 to 2)
Link to the admin action to
allow the user to login
28
29
<%= yield %> <!-- displays template -->
30 </body>
31 </html>
 2008 Pearson Education,
Inc. All rights reserved.
1
2
# Fig. 24.38: app/controllers/messages_controller.rb
# MessagesController that implements CRUD functionality.
3
4
class MessagesController < ApplicationController
verify :method => :post, :only => [ :destroy, :create ],
5
6
7
8
59
Outline
:redirect_to => { :action => :list }
app/controllers/
messages_
controller.rb
# sets up the list web page that lists all messages
def list
9
10
11
if ( params[ :forum_id ] ) # if parameter forum_id is provided
session[ :forum_id ] = params[ :forum_id ]
end # if
12
13
if ( session[ :forum_id ] == nil ) # if no forum_id is provided
14
15
16
flash[ :notice ] = 'there has been an error.'
redirect_to :controller => "forums", :action => "list" and return
end # if
17
18
@messages = Message.find( :all, :order => "created_on desc",
19
20
:conditions => "forum_id = #{ session[:forum_id ] }" )
@forum = Forum.find( :first,
21
22
23
:conditions => "id = #{ session[ :forum_id ] }" )
end # method list
(1 to 2)
Get an array of messages
belonging to the forum with
the forum_id stored in the
session object for the list
action
 2008 Pearson Education,
Inc. All rights reserved.
24
# sets up the new web page that creates a message
25
def new
26
@message = Message.new
27
28
end # method new
29
30
31
# attempts to create a new message with the parameters passed in
def create
@message = Message.new( params[ :message ] )
32
33
34
35
36
37
38
39
40
@message.forum_id = session[ :forum_id ]
if @message.save
# if save method was successful
60
Outline
app/controllers/
messages_
controller.rb
(2 to 2)
flash[ :notice ] = 'Message was successfully created.'
redirect_to :action => 'list'
else # save was unsuccessful
render :action => 'new'
end # if
end # method create
41 end # class MessagesController
 2008 Pearson Education,
Inc. All rights reserved.
1
<!-- Fig. 24.39: app/views/messages/list.rhtml -->
2
<!-- Template for the list action that displays a list of Forums. -->
3
4
<div style = "text-align: center">
<table style = "width: 600px; margin: 0 auto 0 auto">
5
<tr class="msgHeader">
6
7
8
<td><%= @forum.name %></td>
</tr>
<% for message in @messages %>
9
<!-- create two table rows for every message -->
10
11
12
<tr class="msgTitle">
<td>
<strong><%= message[ 'title' ] %></strong><br />
13
14
15
16
17
18
61
Outline
app/views/
messages/list
.rhtml
(1 to 2)
by <em><%= message[ 'author' ] %></em> at
<%= message[ 'created_on' ].strftime("%m/%d/%Y at %I:%M%p") %>
</td>
</tr>
Format the creation time using
<tr class="msgPost">
the strftime method of the
<!-- message content -->
19
20
21
22
<td><%= message[ 'message' ] %></td>
</tr>
<% end %>
</table>
23
24
<%= link_to 'New message', :action => 'new' %> |
Time object stored in
message[‘created_on’]
25
<%= link_to 'list forums',
26
:controller => 'forums', :action => 'index' %>
27 </div>
 2008 Pearson Education,
Inc. All rights reserved.
62
Outline
app/views/
messages/list
.rhtml
(2 to 2)
 2008 Pearson Education,
Inc. All rights reserved.
1
<!-- Fig. 24.40: app/views/messages/_form.rhtml -->
2
<!-- A form that allows the user to enter a new message. -->
3
4
<%= error_messages_for 'message' %>
5
6
<table>
<tr class = "alignRight">
7
8
<td>Title</td>
<td><%= text_field 'message', 'title'
%></td>
9
10
11
</tr>
<tr class = "alignRight">
<td>Author</td>
12
13
<td><%= text_field 'message', 'author' %></td>
</tr>
14
15
<tr class = "alignRight">
<td>Email</td>
16
17
<td><%= text_field 'message', 'email'
</tr>
63
Outline
app/views/
messages/_form
.rhtml
(1 to 2)
%></td>
18
<tr><td colspan = "2">Message</td></tr>
19
<tr><td colspan = "2">
20
<%= text_area 'message', 'message', :cols => "30", :rows => "4"%>
21
</td></tr>
22 </table>
The text_area method
generates a textarea
XHTML element
 2008 Pearson Education,
Inc. All rights reserved.
64
Outline
app/views/
messages/_form
.rhtml
(2 to 2)
 2008 Pearson Education,
Inc. All rights reserved.
1
<?xml version = "1.0" encoding = "utf-8"?>
2
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
3
65
Outline
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
4
5
<!-- Fig. 24.41: app/views/layouts/messages.rhtml -->
6
<!-- Message layout that links a style sheet and displays a message. -->
7
<html xmlns = "http://www.w3.org/1999/xhtml">
8
<head>
9
<title>Messages: <%= controller.action_name %></title>
10
<%= stylesheet_link_tag 'scaffold' %>
11 </head>
12 <body>
13
14
<% if ( flash[ :notice ] ) then %>
<p style="color: green"><%= flash[ :notice ] %></p>
15
<% end %>
16
<%= yield %>
app/views/
layouts/messages
.rhtml
The stylesheet_link_tag
generates a link element to an
external style sheet—in this
case, scaffold.css—in
public/stylesheets/
17 </body>
18 </html>
 2008 Pearson Education,
Inc. All rights reserved.
1
<?xml version = "1.0" encoding = "utf-8"?>
2
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
3
66
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
Outline
4
5
<!-- Fig. 24.42: app/views/layouts/forums.rhtml -->
6
<!-- Forums layout that uses the default JavaScript libraries. -->
7
<html xmlns = "http://www.w3.org/1999/xhtml">
8
<head>
9
<title>Forums: <%= controller.action_name %></title>
10
<%= stylesheet_link_tag 'scaffold' %> <!-- link to a stylesheet -->
11
<%= javascript_include_tag :defaults %>
12 </head>
13 <body>
14
15
<div style = "text-align: right">
app/views/
layouts/forums
.rhtml
(1 to 2)
Include the default JavaScript
libraries, including Script.aculo.us
and Prototype
<% if ( session[ :user ] ) then %> <!-- if user is logged on -->
 2008 Pearson Education,
Inc. All rights reserved.
16
<!-- code to display if user is logged on -->
17
<%= "Logged In As #{ session[ :user ].name }: " %>
18
<%= link_to 'Log Out',
<% else %> <!-- user is not logged on -->
21
<!-- code to display if user is not logged on -->
22
<%= "Not Currently Logged In:" %>
23
<%= link_to 'Log In',
app/views/
layouts/forums
.rhtml
:controller => 'users', :action => 'admin' %>
24
25
Outline
:controller => 'users', :action => 'logout' %>
19
20
67
<% end %> <!-- end if -->
26
</div>
27
<p style="color: green"><%= flash[ :notice ] %></p>
28
<p style="color: red"><%= flash[ :error ] %></p>
(2 to 2)
29
30
<%= yield %> <!-- displays template -->
31 </body>
32 </html>
 2008 Pearson Education,
Inc. All rights reserved.
1
<!-- Fig. 24.43: app/views/forums/list.rhtml -->
2
<!-- Displaying a list of messages without reloading the page. -->
3
4
<h1>Deitel Message Forums</h1>
<div class = "forumList">
5
<h2>Available Forums</h2>
6
7
8
<ul>
<% for forum in @forums %>
<li>
10
11
12
{ :url => { :controller => 'messages',
:action => 'list', :forum_id => forum.id },
:update => 'currentForum' },
13
{ :class => ( forum.created_on < 5.minutes.ago ?
14
15
16
17
18
'recent': nil ) } ) %>
23
24
Outline
app/views/forums
/list.rhtml
<%= link_to_remote ( forum.name,
9
19
20
21
22
68
(1 to 2)
The link to each forum makes
an Ajax call, displaying the
selected forum’s messages in
the currentForum div
using a partial page update
</li>
<% end %>
</ul>
<% if ( session[ :user ] ) then %>
<h2>Forum Management</h2>
<ul>
<li><%= link_to 'Add a Forum', :action => 'new' %></li>
<li><%= link_to 'Delete a Forum', :action => 'delete' %></li>
</ul>
<% end %>
25 </div>
26 <div id = 'currentForum' class = "ajaxComponent">
27 </div>
Messages are displayed
in this div
 2008 Pearson Education,
Inc. All rights reserved.
69
Outline
app/views/forums
/list.rhtml
(2 to 2)
 2008 Pearson Education,
Inc. All rights reserved.
1
<!-- Fig. 24.44: app/views/messages/list.rhtml -->
2
<!-- Forum that allows the user to add a message on the same page. -->
3 <div class = "messageList">
4 <table style = "width: 400">
5
<tr class="msgHeader">
6
<td><%= @forum.name %></td>
7
</tr>
8
<% for message in @messages %>
9
<tr class="msgTitle">
10
<td>
11
<strong><%= message.title %></strong><br/>
12
by <em><%= message.author %></em> at
13
14
15
16
17
70
Outline
app/views/
messages/list
.rhtml
(1 to 2)
<%= message.created_on.strftime( "%m/%d/%Y at %I:%M%p" ) %>
</td>
</tr>
<tr class="msgPost">
<td><%= message.message %></td>
18
</tr>
19
<% end %>
20 </table>
21
22 <%= link_to_remote 'New message',
23
:url => { :action => 'new' },
24
:update => 'currentForum'%>
25 </div>
The New Message link puts
the form in on the same page
using a partial page update
 2008 Pearson Education,
Inc. All rights reserved.
71
Outline
app/views/
messages/list
.rhtml
(2 to 2)
 2008 Pearson Education,
Inc. All rights reserved.
1
<!-- Fig. 24.45: app/views/messages/new.rhtml -->
2
<!-- Allows the user to add a new message without reloading the page. -->
3
<%= form_remote_tag :url=> { :action => 'create' },
4
:update => 'currentForum' %>
5
<%= render :partial => 'form' %>
6
<%= submit_tag "Create" %>
7
<%= end_form_tag %>
8
<%= link_to_remote 'Cancel', :url=> { :action => 'list' },
9
72
Outline
Forum creation is also done
without reloading the
entire
app/views/
page
messages/new
.rhtml
:update => 'currentForum' %>
Canceling forum
(1 tocreation
2)
replaces the form with the list
of forums
 2008 Pearson Education,
Inc. All rights reserved.
73
Outline
app/views/
messages/new
.rhtml
(2 to 2)
 2008 Pearson Education,
Inc. All rights reserved.
74
24.7 Script.aculo.us
• Script.aculo.us allows you to easily create visual effects
similar to those in Adobe Flash and Microsoft Silverlight.
• The library provides many pre-defined effects, as well as
the ability to create your own effects from the pre-defined
ones.
• The Script.aculo.us library also provides drag-and-drop
capability through the draggable_element and
drop_receiving_element methods.
• The sortable_element method allows you to
describe a list that allows the user to drag and drop list
items to reorder them.
• Script.aculo.us also provides the
text_field_with_auto_complete method, which
enables server-side autocompletion of a text field.
 2008 Pearson Education, Inc. All rights reserved.
75
Fig. 24.46 | Script.aculo.us’s Fade effect.
 2008 Pearson Education, Inc. All rights reserved.
1
<!-- Fig. 24.47: app/views/scriptaculous_demo/index.rhtml -->
2
<!-- Default view for Script.aculo.us demo. -->
3
<div id = "link">
4
:effect_index => 0}, :update => "link",
6
:before => visual_effect(
:Shrink, 'image', :duration => 1.0, :queue => 'end') %>
7
</div>
9
10 <div id = "image" style = "width: 244px; height: 320px;">
11
Outline
<%= link_to_remote 'Shrink', :url => {:action => 'playEffect',
5
8
76
<%= image_tag "jhtp7medium.jpg" %>
12 </div>
app/views/
scriptaculous_
demo/index.rhtml
Play a Shrink effect on the
image div before
proceeding to the playEffect
action
 2008 Pearson Education,
Inc. All rights reserved.
1
# Fig. 24.48: app/controllers/scriptaculous_demo_controller.rb
2
# Script.aculo.us Demo controller
3
class ScriptaculousDemoController < ApplicationController
4
Outline
def index
@currentEffect = 0
5
6
end
7
def playEffect
8
@currentEffect = params[ :effect_index ]
9
render :partial => "link"
10
77
app/controllers/
scriptaculous_
demo_controller
.rb
end # method playEffect
11 end # class ScriptaculousDemoController
 2008 Pearson Education,
Inc. All rights reserved.
1
<?xml version = "1.0" encoding = "utf-8"?>
2
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
3
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
78
Outline
4
5
<!-- Fig. 24.49: app/views/layouts/application.rhtml -->
6
<!-- Default layout of Script.aculo.us demo. -->
7
<html xmlns = "http://www.w3.org/1999/xhtml">
8
<head>
9
<title>Script.aculo.us Effects Demo</title>
10
<%= javascript_include_tag :defaults %>
11
</head>
12
<body>
13
14
app/views/layouts
/application
.rhtml
<%= yield %>
</body>
15 </html>
 2008 Pearson Education,
Inc. All rights reserved.
1
<!-- Fig. 24.50: app/views/scriptaculous_demo/_link.rhtml -->
2
<!-- link partial view for Script.aculo.us demo -->
3
<!-- Grow effect -->
4
5
<% if @currentEffect == '0' %>
<%= link_to_remote 'Grow', :url => { :action => 'playEffect',
6
:effect_index => 1 }, :update => "link",
7
:before => ( visual_effect(
8
:Grow, 'image', :duration => 1.0, :queue => 'end' ) ) %>
9
10 <!-- Fade effect -->
11 <% elsif @currentEffect == '1' %>
12
<%= link_to_remote 'Fade', :url => { :action => 'playEffect',
13
14
15
79
Outline
app/views/
scriptaculous_
demo/_link.rhtml
(1 to 5)
:effect_index => 2 }, :update => "link",
:before => ( visual_effect(
:Fade, 'image', :duration => 1.0, :queue => 'end' ) ) %>
16
17 <!-- Appear effect -->
18 <% elsif @currentEffect == '2' %>
19
<%= link_to_remote 'Appear', :url => {:action => 'playEffect',
20
:effect_index => 3 }, :update => "link",
21
:before => ( visual_effect(
22
:Appear, 'image', :duration => 1.0, :queue => 'end' ) ) %>
23
24 <!-- BlindUp effect -->
25 <% elsif @currentEffect == '3' %>
26
<%= link_to_remote 'BlindUp', :url => { :action => 'playEffect',
27
:effect_index => 4 }, :update => "link",
28
:before => ( visual_effect(
29
:BlindUp, 'image', :duration => 1.0, :queue => 'end' ) ) %>
30
 2008 Pearson Education,
Inc. All rights reserved.
31 <!-- BlindDown effect -->
32 <% elsif @currentEffect == '4' %>
33
34
35
<%= link_to_remote 'BlindDown', :url => { :action => 'playEffect',
:effect_index => 5 }, :update => "link",
41
42
43
44
Outline
:before => ( visual_effect(
36
:BlindDown, 'image', :duration => 1.0, :queue => 'end' ) ) %>
37
38 <!-- Puff effect -->
39 <% elsif @currentEffect == '5' %>
40
80
<%= link_to_remote 'Puff', :url => { :action => 'playEffect',
:effect_index => 6 }, :update => "link",
:before => ( visual_effect(
app/views/
scriptaculous_
demo/_link.rhtml
(2 to 5)
:Puff, 'image', :duration => 1.0, :queue => 'end' ) ) %>
45 <!-- SwitchOff effect -->
46 <% elsif @currentEffect == '6' %>
47
<%= link_to_remote 'SwitchOff', :url => { :action => 'playEffect',
48
49
50
:effect_index => 7 }, :update => "link",
:before => ( visual_effect(
:SwitchOff, 'image', :duration => 1.0, :queue => 'end' ) ) %>
51
52 <!-- SlideUp effect -->
53 <% elsif @currentEffect == '7' %>
54
55
56
57
<%= link_to_remote 'SlideUp', :url => { :action => 'playEffect',
:effect_index => 8 }, :update => "link",
:before => ( visual_effect(
:SlideUp, 'image', :duration => 1.0, :queue => 'end' ) ) %>
58
 2008 Pearson Education,
Inc. All rights reserved.
59 <!-- SlideDown effect -->
60 <% elsif @currentEffect == '8' %>
61
62
63
<%= link_to_remote 'SlideDown', :url => { :action => 'playEffect',
:effect_index => 9 }, :update => "link",
69
70
71
72
Outline
:before => ( visual_effect(
64
:SlideDown, 'image', :duration => 1.0, :queue => 'end' ) ) %>
65
66 <!-- Shake effect -->
67 <% elsif @currentEffect == '9' %>
68
81
<%= link_to_remote 'Shake', :url => { :action => 'playEffect',
:effect_index => 10 }, :update => "link",
:before => ( visual_effect(
app/views/
scriptaculous_
demo/_link.rhtml
(3 to 5)
:Shake, 'image', :duration => 1.0, :queue => 'end' ) ) %>
73 <!-- Pulsate effect -->
74 <% elsif @currentEffect == '10' %>
75
<%= link_to_remote 'Pulsate', :url => { :action => 'playEffect',
76
77
78
:effect_index => 11 }, :update => "link",
:before => ( visual_effect(
:Pulsate, 'image', :duration => 1.0, :queue => 'end' ) ) %>
79
80 <!-- Squish effect -->
81 <% elsif @currentEffect == '11' %>
82
83
84
85
<%= link_to_remote 'Squish', :url => { :action => 'playEffect',
:effect_index => 12 }, :update => "link",
:before => ( visual_effect(
:Squish, 'image', :duration => 1.0, :queue => 'end' ) ) %>
86
 2008 Pearson Education,
Inc. All rights reserved.
87 <!-- Grow effect -->
88 <% elsif @currentEffect == '12' %>
89
90
91
<%= link_to_remote 'Grow', :url => { :action => 'playEffect',
:effect_index => 13 }, :update => "link",
97
98
99
100
Outline
:before => ( visual_effect(
92
:Grow, 'image', :duration => 1.0, :queue => 'end' ) ) %>
93
94 <!-- Fold effect -->
95 <% elsif @currentEffect == '13' %>
96
82
<%= link_to_remote 'Fold', :url => { :action => 'playEffect',
:effect_index => 14 }, :update => "link",
:before => ( visual_effect(
app/views/
scriptaculous_
demo/_link.rhtml
(4 to 5)
:Fold, 'image', :duration => 1.0, :queue => 'end' ) ) %>
101 <!-- Grow effect -->
102 <% elsif @currentEffect == '14' %>
103
<%= link_to_remote 'Grow', :url => { :action => 'playEffect',
104
105
106
:effect_index => 15 }, :update => "link",
:before => ( visual_effect(
:Grow, 'image', :duration => 1.0, :queue => 'end' ) ) %>
107
108 <!-- DropOut effect -->
109 <% elsif @currentEffect == '15' %>
110
111
112
113
<%= link_to_remote 'DropOut', :url => { :action => 'playEffect',
:effect_index => 16 }, :update => "link",
:before => ( visual_effect(
:DropOut, 'image', :duration => 1.0, :queue => 'end' ) ) %>
114
 2008 Pearson Education,
Inc. All rights reserved.
115 <!-- Grow effect -->
116 <% elsif @currentEffect == '16' %>
117
<%= link_to_remote 'Grow', :url => { :action => 'playEffect',
118
:effect_index => 17 }, :update => "link",
119
:before => ( visual_effect(
120
:Grow, 'image', :duration => 1.0, :queue => 'end' ) ) %>
121
122 <!-- Shrink effect -->
83
Outline
app/views/
scriptaculous_
demo/_link.rhtml
123 <% elsif @currentEffect == '17' %>
124
<%= link_to_remote 'Shrink', :url => { :action => 'playEffect',
125
:effect_index => 0 }, :update => "link",
126
:before => ( visual_effect(
127
(5 to 5)
:Shrink, 'image', :duration => 1.0, :queue => 'end' ) ) %>
128 <% end %>
 2008 Pearson Education,
Inc. All rights reserved.
84
Fig. 24.51 | Flickr Photo Viewer showing search results for bugs.
 2008 Pearson Education, Inc. All rights reserved.
1
2
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3
4
5
<!-- Fig. 24.52: app/view/flickr/index.rhtml -->
6
<!-- Main view for Flickr Photo Viewer. -->
7
8
<html xmlns = "http://www.w3.org/1999/xhtml">
<head>
9
10
11
12
13
<title>Flickr Photo Viewer</title>
<%= javascript_include_tag :defaults %>
<%= stylesheet_link_tag 'flickrPhotoViewer' %>
85
Outline
app/view/
flickr/index
.rhtml
(1 to 2)
</head>
<body>
14
<!-- Form to search for tags -->
15
16
<%= form_remote_tag :url => { :action => 'search' },
:update => 'thumbs',
17
18
:complete => visual_effect( :BlindDown, 'thumbs' ),
:before => { visual_effect( :BlindUp, 'thumbs' ),
19
20
%( Element.show( 'loading' ) ) },
:failure => %( Element.hide( 'loading' ) ),
21
:success => %( Element.hide( 'loading' ) ) %>
A form that searches for
tags, using blind effects
and a loading indicator
 2008 Pearson Education,
Inc. All rights reserved.
<div id = "search">
22
23
Tags:
24
<%= text_field_tag "tags" %>
25
#:
26
<%= text_field_tag "numImages", "8", :size => "3" %>
27
<%= submit_tag "Search" %>
28
<div id = "loading"
style = "display: none">Loading...</div>
29
Outline
app/view/
flickr/index
.rhtml
</div>
30
31
<%= end_form_tag %>
32
<div id = "thumbs"></div>
33
<div id = "fullsizeImage"></div>
34
86
(2 to 2)
</body>
35 </html>
 2008 Pearson Education,
Inc. All rights reserved.
1
# Fig. 24.53: app/controllers/flickr_controller.rb
2
# Controller for Flickr Photo Viewer.
3
class FlickrController < ApplicationController
4
# handle the search request
5
def search
6
flickr = Flickr.new
7
render :partial => "thumbs",
8
:collection => flickr.photos( :tags => params[ :tags ],
9
:per_page => params[ :numImages ] )
10
end # method search
11
12
# handle the thumbnail click, sets the currentURL variable
13
def fullsizeImage
14
15
87
Outline
app/controllers/
flickr_
controller.rb
Search for tags and display
paginated results
@currentURL = params[ :imageURL ]
end # method fullsizeImage
16 end # class FlickrController
 2008 Pearson Education,
Inc. All rights reserved.
1
<!-- Fig. 24.54: app/views/flickr/_thumbs.rhtml -->
2
<!-- thumbs view of Flickr Photo Viewer. -->
3
<%= link_to_remote image_tag( thumbs.sizes[ 0 ][ 'source' ],
4
5
6
Outline
:class => "image" ),
:url => { :action => 'fullsizeImage',
:imageURL => thumbs.sizes[ 3 ][ 'source' ] },
7
:update => "fullsizeImage",
8
:success => visual_effect( :grow, 'fullsizeImage',
9
88
app/views/flickr
/_thumbs.rhtml
:queue => 'last' ) %>
Display a thumbnail that links
to the full sized image
 2008 Pearson Education,
Inc. All rights reserved.
1
<!-- Fig. 24.55: app/views/flickr/fullsizeImage.rhtml -->
2
<!-- fullsizeImage view of Flickr Photo Viewer. -->
3
<%= image_tag( @currentURL, :class => "image" ) %>
Display the full size
version of an image
89
Outline
app/views/flickr
/fullsizeImage
.rhtml
 2008 Pearson Education,
Inc. All rights reserved.