• No results found

Building the code for the SQL generator

In document Code Generation in action (Page 161-165)

Generating documentation

6.3 A CASE STUDY : AUGMENTED SQL CODE

6.3.4 Building the code for the SQL generator

The case study generator is written in Ruby and uses the Tokenizer toolkit from chapter 3 (“Code generation tools”) to read and parse the SQL file. The code then stores the table definitions and comments in memory and uses this material to generate the HTML pages. The generator creates the HTML pages with the help of templates from ERb. Listing 6.2 shows the code for the documentation generator.

require "SQLTokenizer"

require "SQLLanguageScanner"

require "JavaDoc"

require "erb/erb"

def run_template( template_name, bind ) erb = ERb.new( File.new( "templates/#{template_name}" ).read ) erb.result( bind )

attr_reader :tableDescription # The table description string

attr_reader :fieldDescriptions # The hash of descriptions for each field attr_reader :relatesTo # The array of tables this table relates to def add_to_tag( key, text )

Brings in the ERb template system

e

A CASESTUDY: AUGMENTED SQL CODE 133

fh = File.open( file_name in_text = fh.read() fh.close()

tokenizer = SQLTokenizer.new( ) tokenizer.parse( in_text )

languagescanner = SQLLanguageScanner.new()

languagescanner.parse( tokenizer.tokens ) tables = languagescanner.tables

tables.each { |table|

print "Building #{table.name}.html\n"

jd = ExtendedJavaDoc.new() jd.parse( convert_comment( table.comment ) )

table.fields.each { |field|

field.comment = jd.fieldDescriptions[ field.name.to_s.downcase.strip ] }

table_comment = jd.tableDescription relates_to = jd.relatesTo fh = File.new ("output/#{table.name}.html", "w" ) fh.print run_template( "table_page.html.template", binding ) fh.close()

q

This code imports the Tokenizer and parser that reads the SQL. These are from the language parsing toolkit described in chapter 3.

w

The JavaDoc class is also from the language parsing toolkit. It reads JavaDoc comments and creates a hash of key value pairs that stores the data in the comment.

Later in this chapter you’ll create an ExtendedJavaDoc class that derives from the JavaDoc class to handle your requirements.

e

ERb is the text-template handler.

r

run_template is a wrapper for the ERb template mechanism that takes the file-name of a template and the binding object that contains the local variables for template.

t

The ExtendedJavaDoc class derives from the JavaDoc class and handles the @field and @relates_to keys. The @field descriptions are stored in the fieldDescriptions hash table; the @relates_to table names are stored in an array called relatesTo.

y

This code iterates over every table. Within this loop the code reads the JavaDoc com-ments attached to the table, then uses a template to create the HTML page for the table.

u

This code creates our ExtendedJavaDoc object for this table and passes along to it the comments that are attributed to the table.

i

This code attaches a comment to every field by using the comment for the field in the ExtendedJavaDoc object.

o

These two local variables—table_comment and relates_to—are passed to the ERb template by using the binding method call on run_template.

a

This code runs the ERb template that generates the HTML page, which in turn describes the table.

Next you need a template that uses basic ERb substitution to build the header at the top of the page. This header describes the fundamentals of the table, including the name, and the comment. The template then iterates over each field to create the HTML table that describes the fields of the database table. The ERb template for the generator is shown in Listing 6.3.

<html><head>

<title><%= table.name %></title>

</head>

<body>

<table width=100%>

<tr>

<td width=10% nowrap valign=top><b>Table Name:</td><td><%= table.name %></

Listing 6.3 table_page.html.template

Uses the table name as the title

A CASESTUDY: AUGMENTED SQL CODE 135

<td width=10% nowrap valign=top><b>Description:</td><td><%= table_comment

%></td></tr>

<td width=10% nowrap valign=top><b>Fields:</td><td>

<table cellspacing=1 cellpadding=0 bgcolor=#bbbbbb width=100%>

constraints.push( "Non-null" ) if ( field.not_null ) constraints.push( "Unique" ) if ( field.unique )

constraints.push( "Primary key" ) if ( field.primary_key )

%><tr>

<td bgcolor=white valign=top><%= field.name %></td>

<td bgcolor=white valign=top><%= field.type %></td>

<td bgcolor=white valign=top><%= constraints.join( ", " ) %></td>

<td bgcolor=white valign=top><%= field.comment %></td>

</tr><% } %>

</table>

</td></tr>

<% if ( relates_to.length > 0 )

rel_text = relates_to.map { |table| "<a href=\"#{table}.html\">#{table}"

}.join( ", " )

%><td width=10% nowrap valign=top><b>Relates To:</td>

<td valign=top><%= rel_text %></td>

</tr><% end %></table>

</body>

</

html>

q

This code loops through each field and outputs the cells that contain the names, the types, the constraints, and the comments.

w

This code prints a list of related tables. The map creates the <a> tags and the join adds the comments between the completed <a> tags.

The tables.html file displays the left-hand menu in a framed layout (shown in figure 6.2).

The menu contains the names of all the tables. When the user clicks on one of the table names, the right-hand frame shows the page specific to that table. The template for the tables.html file is shown here:

<html>

<body>

<% tables.each { |table| %>

<a href="<%= table.name %>.html" target="main"><%= table.name %></a><br>

<% } %>

Next you must write the template for the index.html file. No substitution is required in this template. The resulting HTML is a frameset that places the menu on the left-hand side and the table information in the right-hand panel. Here’s the code:

<frameset cols="20%,*">

<frame src="tables.html">

<frame name="main" src="tables.html">

</frameset>

Figure 6.2 shows the output of the generator for the Book table. The HTML shows the name of the table, your description of it and all its fields, and the tables to which it relates.

In document Code Generation in action (Page 161-165)