Creating database aware application
In this example, we will create a sample application for task management. Basically the application will provide options for creating, deleting, editing and viewing task items. We will be taking the support of various utilities that comes as part of Rails distribution for creating this sample.
Download Example Source Code
Creating the project
Create a project called ‘task’ by executing the following command. The following command ensures that the basic set of artifacts necessary for a rails project is created.
1 | rails new task |
Also delete the default index.html file which is available in ‘/public/’ directory. Change the current directory to ‘task’ before proceeding with the rest of the section.
Configuring Database
The database that we will be using in this sample application will be mysql. Make sure that mysql database is installed in the local machine. Database related configurations for a rails application goes in database.yml file which is present in ‘/config/’directory. Rails framework provides database configuration options for development, testing and production environments. Edit the database.yml and make sure that the contents of the file matches the following,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | development: adapter: mysql database: javabeat_dev username: root password: #### pool: 5 timeout: 5000 test: adapter: mysql database: javabeat_test username: root password: #### pool: 5 timeout: 5000 production: adapter: mysql database: javabeat_prod username: root password: #### pool: 5 timeout: 5000 |
In the above file, we have configured different databases for different environments. Make sure to modify the username and the password for the database. Also there is one more place to instruct the Rails framework that we want mysql gem for interacting with the mysql database and this happens to be the file ‘Gemfile’ that is present in the project’s root directory.
1 | gem 'mysql', '2.8.1' |
Make sure to add the above line in the ‘Gemfile’ and remove any dependencies related to ‘sqlite’ which by default will be present.
The next step is to create the database that we have configured in the database.yml. One way is to connect to the MySql server through a MySql client and then issue ‘create database <DATABASE_NAME>’ for creating the database for the development and the testing environments. Other possible option is to execute to the following command which does the job of creating the database.
1 | rake db:create |
Scaffolding
In Rails terms, scaffolding refers to the process of the generation of artifacts such as controllers, models and view. In our case, we want to create controller, model and multiple views for the task item. Execute the following command,
1 | rails generate scaffold TaskItem tile:string summary:text start_date:date end_date:date status:string priority:string total_hours_of_work:integer |
We want scaffolding for ‘TaskItem’ where the model ‘Task’ is supposed to contain various properties like title, summary, start_date, end_date, status, priority and total_hours_of_work. Also note that syntax for specifying these list of properties in the command line which follows ‘<propertyName>:<propertyType>’. Property types with values ‘string’ will be displayed as a text field, those with values ‘text’ will be displayed as a text-box, for ‘date’ property types a date selector UI will be provided for selecting month, day and year. Executing the above command will generate a lot of files and folders for the project. In the subsequent sections, we will discuss the details about them.
Model
The model file ‘task_item.rb’ will be generated and placed in the directory ‘/app/models’. The name of the model class will be TaskItem (the one that is specified in the command prompt). The listing for this class is shown below.
1 2 | class TaskItem < ActiveRecord::Base end |
As you can see the TaskItem extends from the base class ‘ActiveRecord:Base’. This inheritance will make sure that the ‘TaskItem’ is a data-aware model class and the capabilities for a data-aware object such as Create/Update/Delete/Read will be applicable to objects created from TaskItem.
Controller
The Controller class provides the actions for creating, editing displaying, deleting and viewing. The following provides code snippet for TaskItemsController.
1 2 3 4 5 | class TaskItemsController < ApplicationController … end |
The controller class must extend the base ‘ApplicationController’ in a data-aware environment. We will see the list of supported actions provided by the controller in the following section.
New Task
Given below is the code snippet for creating a new task action. One can see that a new task is created through ‘TaskItem.new’ and the result is stored in task_item variable. When it comes to the rendering part, in case of html rendering, when the url is accessed through ‘http://localhost:3000/task_items/new’, the view is taken from the file ‘new.html.erb’ which is present in ‘/app/views/task_items’ directory. For xml rendering, when the url is accessed as ‘http://localhost:3000/task_items/new.xml’, the xml format of the new task-item is shown, although one would rarely use this feature.
1 2 3 4 5 6 7 8 | def new
@task_item = TaskItem.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @task_item }
end
end |
One can see that this above action creates a empty task and redirects the user to a different page where the user can provide information for creating a task. The next section discusses about creating the new task.
Create Task
This action will be triggered once the user presses the ‘Create’ button after giving all the information .
1 2 3 4 5 6 7 8 9 10 11 12 13 | def create
@task_item = TaskItem.new(params[:task_item])
respond_to do |format|
if @task_item.save
format.html { redirect_to(@task_item, :notice => 'Task item was successfully created.') }
format.xml { render :xml => @task_item, :status => :created, :location => @task_item }
else
format.html { render :action => "new" }
format.xml { render :xml => @task_item.errors, :status => :unprocessable_entity }
end
end
end |
Note that the information collected from the user will be stored in the ‘params’ variable and the list of values present in the variable will be used for creating a new task. Upon successful creation of the task, appropriate message is displayed to the user.
Edit Task
In the case of editing a task, the task item to be edited is fetched from the database by calling the method TaskItem.find() that takes the id of the task as a parameter. Note that the request parameters will always be available in the in-built ‘params’ variable.
1 2 3 4 5 6 7 8 9 10 11 12 13 | def update
@task_item = TaskItem.find(params[:id])
respond_to do |format|
if @task_item.update_attributes(params[:task_item])
format.html { redirect_to(@task_item, :notice => 'Task item was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @task_item.errors, :status => :unprocessable_entity }
end
end
end |
We take the id of the task item to be edited and then call the method update_attributes() for updating the task object.
Show Task
The show action resembles the same functionality as that of update functionality. The task item to be shown in the UI is fetched with the help of task item. The fetched task item is then rendered in the browser either in html or in XML depending on the request URL.
1 2 3 4 5 6 7 8 | def show
@task_item = TaskItem.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @task_item }
end
end |
Delete Task
For deleting a task also, we follow similar logic as ‘edit’, where the id of the task is taken into consideration for fetching the task to be deleted. The method destroy() can be used for actually deleting the task object.
1 2 3 4 5 6 7 8 9 | def destroy
@task_item = TaskItem.find(params[:id])
@task_item.destroy
respond_to do |format|
format.html { redirect_to(task_items_url) }
format.xml { head :ok }
end
end |
View all Tasks
The code snippet for viewing all the tasks is given below.
1 2 3 4 5 6 7 8 | def index
@task_items = TaskItem.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @task_items }
end
end |
The call ‘TaskItem.all’ will retrieve all the task items from the database and the results are stored in the variable task_items. In this action also, html rendering (‘http://localhost:3000/task_items’)as well as xml rendering (‘http://localhost:3000/taskitems.xml’)is supported.
Views
In this section we will look into the various views that the above action definitions are having references.
Index View
The complete listing for the Index view is given below. This view will be displayed by default when the user accesses the URL ‘http://localhost:3000/task_items’.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <h1>Listing all the task items</h1>
<table border = '1'>
<tr>
<th>Tile</th>
<th>Summary</th>
<th>Start date</th>
<th>End date</th>
<th>Status</th>
<th>Priority</th>
<th>Total hours of work</th>
<th></th>
<th></th>
<th></th>
</tr>
<% @task_items.each do |task_item| %>
<tr>
<td><%= task_item.tile %></td>
<td><%= task_item.summary %></td>
<td><%= task_item.start_date %></td>
<td><%= task_item.end_date %></td>
<td><%= task_item.status %></td>
<td><%= task_item.priority %></td>
<td><%= task_item.total_hours_of_work %></td>
<td><%= link_to 'Show', task_item %></td>
<td><%= link_to 'Edit', edit_task_item_path(task_item) %></td>
<td><%= link_to 'Destroy', task_item, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New Task item', new_task_item_path %> |
Note that the above file uses a mixture of html and ruby scriptlets. The very first time the view is accessed it will be empty. Upon creating of sample tasks, the view may look something similar to the following
Listing all the tasks
New Task View
The screen-shot for creating a new task view is shown below.
For creating a new task
The code listing for ‘new.html.erb’ is given as follows.
1 2 3 4 5 | <h1>Create new task page</h1> <%= render 'form' %> <%= link_to 'Back', task_items_path %> |
Here we are using the concept of Partials in Ruby. Paritals are templates for a view that can be reused in multiple places. Here we have defined a partial in the name ‘form’ and hence the convention is that the view file ‘_form.html.erb’ will be placed in the directory ‘/app/views/task_items’ directory. The source code for ‘_form.html.erb’ will be presented later in the section. Given such a template file, it is possible to use the same template for new task as well as for edit task action because the UI controls for ‘new task’ and ‘edit task’ are one and the same.
Edit Task View
The edit task view is not different from ‘new task view’ and it also uses the partial ‘form’, the complete source code of which is given below.
1 2 3 4 5 6 | <h1>Edit the selected task</h1> <%= render 'form' %> <%= link_to 'Show', @task_item %> | <%= link_to 'Back', task_items_path %> |
The sample screen-shot of ‘edit task’ is give below.
For editing existing task
Show Task View
When the user clicks the Show link from the ‘View all tasks’ page, information about the task will be displayed. Please refer the following screenshot for one such task information.
For viewing a task information
Given below is the source code listing for ‘show task view’. Note that there is view ensures that all the properties of a task are taken into consideration for display.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | <h2> View information about the selected task </h2> <p id="notice"><%= notice %></p> <p> <b>Tile:</b> <%= @task_item.tile %> </p> <p> <b>Summary:</b> <%= @task_item.summary %> </p> <p> <b>Start date:</b> <%= @task_item.start_date %> </p> <p> <b>End date:</b> <%= @task_item.end_date %> </p> <p> <b>Status:</b> <%= @task_item.status %> </p> <p> <b>Priority:</b> <%= @task_item.priority %> </p> <p> <b>Total hours of work:</b> <%= @task_item.total_hours_of_work %> </p> <%= link_to 'Edit', edit_task_item_path(@task_item) %> | <%= link_to 'Back', task_items_path %> |
Conclusion
This article explored the power of Ruby with respect to database integration, especially with Active Record features. The first section of the article discussed on writing basic CRUD operations along with the mapping between Ruby classes and database tables. Establishing relationships are explained with simple example. The later section of the article guided in writing a web application that makes use of Active Record features for creating/editing/listing tasks.










December 6, 2010
Ruby