Previous Page
Next Page

Hack 60. Dynamically Generate a Selection List Using Database Data

Create a select element using database data in a Rails web application.

This hack generates a select element with options that have values and content derived from live database data. The cool twist is that the user initiates the creation of the element, and the select list appears loaded with database data without any page refreshes or rebuilds. This hack is a snap to build with Ruby on Rails, which automatically provides the developer with objects that are directly mapped to database tables.

This hack assumes that the user is interacting with a web server that uses RoR components. It uses the built-in WEBrick server to handle the HTTP requests and responses.

Tracking Energy Use

This hack is an energy-monitoring tool that allows the user to track the kilowatts usage of a system. It generates a web page that asks the user to choose a year, and then pulls monthly kilowatts-usage data from a database and displays the month options in a new select element. The select list appears on the page without any perceptible page rebuild in the browser.

When the user chooses a month, the page immediately displays the kilowatts used that month in a text field beneath the newly created select list. Figure 7-11 shows the web page before the user clicks the Show Months button.

Figure 7-11. Use Ajax to generate tags with database content

When the user clicks the Show Months button, the application sends a request to the RoR server, which responds with content for updating the web page. The content is a new select element containing MySQL database data and a text field, as Figure 7-12 shows.

Figure 7-12. Display monthly kilowatt usage from a database

When the user selects a month from the select list, the data for that month appears in the text field.

Let's see how the code is put together. Here is the view that RoR uses to output the page, located at <web-app-root>/app/views/kilowatt/dbselect.rhtml:

    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    <%= javascript_include_tag "prototype.js" %>
    <title>Ajax Rails &amp; DB Select list</title>
<%= form_remote_tag(:update => "db_div",:url => { :action => :db_element },
:position => "top",:success => "$('db_div').innerHTML=''" ) %>
<h3>Choose a year for energy usage totals:</h3>
<%= select_tag "year","<option>2005</option><option>2006</option>
<option>2007</option>" %>
<div id="db_div"></div>
<%= submit_tag "Show Months" %>
<%= end_form_tag %>

The page requires the Prototype JavaScript package to initiate its dynamic Ajax-driven update. See for an explanation of prototype.js. javascript_include_tag( ) is an RoR API method you can use in embedded scripts to make it easier to output script tags. form_remote_tag( ) creates a form element that uses XMLHttpRequest to update an HTML element on the page. The form submits its request to a server-side component (in Rails parlance, an action) called db_element. Let's take a look at db_element.

class KilowattController < ApplicationController
    scaffold :kilowatt
    def db_element
        @kwatts = Kilowatt.find_all
        render :partial => "options"

db_element is just a method defined in Ruby. In the Rails framework, controller objects, well, control the processing of requests. KilowattController is a class that handles requests involving <web-app-root>/kilowatt-type URLs. All the related actions are defined in this controller object. First, the method creates an instance variable, @kwatts, which contains the data for all the rows of a database table. The Kilowatt.find_all part is a model object that calls a find_all( ) method, which queries the database table kilowatts for its rows.

Ruby on Rails uses an object-relational mapping mechanism that allows application code written in Ruby to create, update, and delete database data. Ruby on Rails is already well known for automating much of this development process.

Next, db_element calls render( ), which renders the response (the select element and text field) using a chunk of a template called a partial. The partial's name is options, and it is located at <web-app-root>app/views/kilowatt/_options.rhtml (Ruby on Rails knows where to find it). The partial has access to the @kwatts variable mentioned above. Here it is:

<select id="dbselect" name="dbselect" onchange=
<% @kwatts.each do |kilowatt| %>
<option value="<%=kilowatt.kwatts%>">Kilowatts for :: <%=kilowatt.kdate%>
<% end %>
<input type="text" id="monthly_total" size="10" maxlength="10">

The template generates an option element for each database table row. The values for two of the table columns are used: kilowatt.kwatts is a number reflecting the kilowatts used, and kilowatt.kdate is a date string. Here's an example option in the output:

<option value="2200">Kilowatts for :: 11-07-2005</option>

The server sends the output of this partial as the HTTP response.

Good Form

The form element looks like this in the web page's underlying source code:

<form action="/kilowatt/db_element" method="post" 
onsubmit="new Ajax.Updater('db_div', '/kilowatt/db_element', 
{asynchronous:true, evalScripts:true, insertion:Insertion.Top, 
return false;">

Like "Periodically Make a Remote Call" [Hack #61], this code uses the Ajax.Updater object from the prototype.js package (see Chapter 6). While this object is interesting, the RoR developer deals only with the form_remote_tag( ) method. The framework does a lot of the work for you.

Previous Page
Next Page