Ur/Web Tutorial

Ur/Web Tutorial

Step 3

Previous | Next

In the last step we succeeded in querying the database and displaying it. If you didn't go to the trouble of adding some test data to your entry table, you'll want to do this now, because in this step we are going to add a little bit of style.

Adding some data is pretty simple. Ur/Web does some automatic table name generation. Looking inside the urblog database, there is one table: uw_Urblog_entry. Tables are named according to the modules they belong to (and module names are in turn defined by file names -- our entry table is defined inside a file called urblog.ur, which leads to an implied module Urblog). This separation is used by Ur/Web to achieve useful encapsulation of tables, such that one module cannot (inadvertantly or intentionally) interfere with tables that are owned by some other module. I added some test data like this:

insert into uw_Urblog_entry (uw_id, uw_title, uw_created, uw_author, uw_body) 
	values (0, "This is a test entry", now(), "Gian", "This is a test entry.  I hope you like it");
insert into uw_Urblog_entry (uw_id, uw_title, uw_created, uw_author, uw_body) 
	values (1, "This is also a test entry", now(), "Gian", "This is yet another test entry.  I hope you like it");

Stylesheets

Like most of the other commonly-manipulated artifacts of web development, CSS styles are first-class values in Ur/Web, and therefore the compiler can statically ensure that you do not reference undeclared styles. Styles are introduced by the style keyword.

style entry

In urblog.ur, we're going to include a stylesheet, and define a class for our entry div.

urblog.ur

[...]
style blogEntry

fun list () =
    rows <- queryX (SELECT * FROM entry)
            (fn row => 
            <xml>
               <div class={blogEntry}>
                  <h1>{[row.Entry.Title]}</h1>
                     <h2>By {[row.Entry.Author]} at {[row.Entry.Created]}</h2>
                  <p>{[row.Entry.Body]}</p>
               </div>
            </xml>
            );
    return 
       <xml>
        <head>
            <title>All Entries</title>
            <link rel="stylesheet" type="text/css" href="http://expdev.net/urtutorial/step3/style.css"/>
        </head>
        <body>
         <h1>All Entries</h1>
        {rows}
        </body>
       </xml>
[...]

We use a full URL for the style sheet. You are free to replace this with your own stylesheet. Ur/Web enforces certain security constraints on externally-referenced media, so we need to tell Ur/Web that this URL is OK to include, and we specify this in our .urp file.

urweb.urp

allow url http://expdev.net/urtutorial/step4/style.css
rewrite style Urblog/blogEntry blogEntry
database dbname=urblog
sql urblog.sql

urblog

Like all other entities within Ur/Web, styles are named according to their modules. When we defined a style blogEntry in our main source file, that was implicitly tied to the Urblog module, and therefore our generated code would look for a style called Urblog_blogEntry in the style.css file. This rewrite style syntax allows us to tell Ur/Web what we have really called this style in the CSS file.

We can build and run this exactly as we built the last step:

# urweb -dbms mysql -db "password=******* dbname=urblog" urblog
# ./urblog.exe

And now you can access the application exactly as you did previously: http://localhost:8080/Urblog/list.

Previous | Next