Tutorial 3
Sessions
We will start this tutorial by first telling the system to store the session information in the database. To do so, first type the following command:
rake db:sessions:create
which will create a new migration for storing sessions in the database. You can check the new migration under db/migrate. The session_id attribute corresponds to the id that is stored in the browser cookie. Data is the data that you store in the session serialized in a text field. The updated_at attribute will allow you to check the last time and day the user accessed the application.
Now, run the migration to add this table to the database.
rake db:migrate
We have not yet told the application to use the database to store the session data in the table we have just created. To do so, edit the file config/environment.rb and uncomment the line
config.action_controller.session_store = :active_record_store
Now, stop and restart the server for these changes to take effect. As you are storing all the session information in the database, this is a good time to think about what is best to store in a session. Generally, we would like to store only simple information that does not change over time. For example, storing user's name may not be the best idea if you expect that the user may edit their name. Their user id is a better choice, using the id you can read their name from the database (we will do so in a minute). Of course, you can choose to store the name in the session but you must update it in the session anytime you change it elsewhere.
CRUD (create, read, update, delete)
We have seen that the scaffolding application allows you to create, read, update and delete objects from a class that is stored in a database. We will examine this function in more detail in this section. First, let us expand the scaffold by running the following command:
ruby script/generate scaffold book admin
It will ask you whether you would like to overwrite some of the files in your project. Answer yes to all these questions. Now, the system should work the same but a number of files are generated. First, you will see files generated for each of the actions performed by the scaffold under views/admin. Let's take a look at these quickly.
Edit/New actions call the corresponding rhtml files under views. However, both basically do the same thing. Display a form with the fields for the book table, read the fields and store them in the database. So, they can simply use the same form, but the action fields will be different. This form is stored under _form.rhtml. Any file name under views that store with an underscore is a partial file that is called from within the another view file with the command, render. You can see this form is called with:
<%= render :partial => 'form' %>
The submit_tag create a button when pressed sends a post request to the application. For many reasons, it is highly recommended that any action that changes data in the database should be invoked by a post request. You can see this also in the controller we just created:
verify :method => :post, :only => [ :destroy, :create, :update ],
:redirect_to => { :action => :list }
which tells that only way to execute actions destroy, create and update methods in the controller is by a post request. All the other requests will be forwarded to the list action.
Let us now look at the list.rhtml file. Recall that the class that stores all the books is called Book. The objects in this class are tuples in the database. You can simply access these tuples by the find method. (The list action uses pagination which handles this differently, but we will disregard that for the time being.) The set of all the selected tuples from the books table can now be accessed as a collection of objects of type Book. For example:
@books = Book.find(:all, conditions => ["title = :title", {:title = "Database Systems"}])
is equivalent to executing the query
select * from books where title = 'Database Systems'
Incidentally, rails generates an accessor method for all named columns. So, we could write the same query using:
@books = Book.find_by_title("Database Systems")
The result is the same, the variable @books contains a set objects. We can now iterate through these objects using a command like:
<% for book in @books %>
<%= book.title %>
<% end %>
which will display the title of all the books. There are many other methods defined for database backed classes, all handled by the
ActiveRecord class. To read more about
ActiveRecord , see
http://api.rubyonrails.org/classes/ActiveRecord/Base.html .
Another thing to note is how we access individual tuples. For example, the line:
<%= link_to 'Show', :action => 'show', :id => book %>
triggers the action show and sends the identifier of the chosen book object to the action with the option :id. The show action in the controller now has to first retrieve that book with the given id from the database:
@book = Book.find(params[:id])
and display in the show.rhtml file.
Go through the actions in this controller and their corresponding views to familiarize yourself with the rails classes.
Adding data
Now, when we start the application, we would like to have a number of books objects so that we can test our code. To do so, let us create a new migration:
ruby script/generate migration add_books
Now, edit the corresponding migration file:
class AddBooks < ActiveRecord::Migration
def self.up
self.down
Book.create(:name => 'Fundemantals of Database Systems',
:author => 'Ramez Elmasri, Shamkant B. Navathe ',
:description => 'Combines clear explanations of theory and design,
broad coverage of models and real systems. Excellent examples with up
to date introductions to modern database technologies are included.',
:isbn => '0-3213695-7-2',
:price => 88.24)
Book.create(:name => 'Database Management Systems',
:author => 'Raghu Ramakrishnan, Johannes Gehrke',
:description => 'Database Management Systems provides comprehensive
and up-to-date coverage of the fundamentals of database systems.
Coherent explanations and practical examples have made this one of
the leading texts in the field.',
:isbn => '0-0712305-7-2',
:price => 82.66)
Book.create(:name => 'Database Systems: An Application Oriented Approach, Compete Version',
:author => 'Michael Kifer, Arthur Bernstein, Philip M. Lewis ',
:description => 'Database Systems: An Application Oriented Approach,
Complete Version, Second Edition presents the principles underlying the
design and implementation of databases and database applications,
covering Object Databases, Security, XML and Data Mining and Web
Services topics.',
:isbn => '0-3212684-5-8',
:price => 105.12)
end
def self.down
Book.delete_all
end
end
Notice that we are running the Book.create method to create and save new tuples in the Book class corresponding to the books table. Now, run this migration as usual and check the contents of the books table in your application.
--
SibelAdali - 22 Sep 2008