Archive for 2008

Custom iterative tag in Grails with named variable

I will show you how to create an iterative Grails tag that can contain another tag. The inner tag will use variable of the iterative tag. So, we are going to implement a tag that creates n links ’/show/1’, ’/show/2’, etc. with description ‘Article number 1’, ‘Article number 2’ etc.:

First of all, there is a nice and handy example for a simple iterative tag on the Grails site.

Definition:

def repeat = { attrs, body ->
  def i = Integer.valueOf( attrs["times"] )
  def current = 0
  i.times {
    // pass the current iteration as the groovy default arg "it"
    // then pass the result to "out" to send it to the view
    out << body( ++current )
  }
}

Usage:

<g:repeat times="3">
  <p>Repeat this 3 times! Current repeat = ${it}</p>
</g:repeat>

Slight modification of the tag does not lead to the requested functionality:

<g:repeat times="3"> 
  <g:link action="show" id="${it}">Hello number  ${it}</g:link> 
</g:repeat>

It just generates the “Article number” string three times, because the it variable is not known here.
Thus it is necessary to change the tag definition. Lets add another parameter vars as a symbolic name of the current member of the collection.

def repeat = { attrs, body -> 
  def pars = [:]
 
  attrs.times?.toInteger().times { n -> 
    pars[attrs.var] = n
    out << body(pars) 
  } 
}

And now it is possible to use g:link inside the custom tag:

<g:repeat times="3" var="num"> 
  <g:link action="show" id="${num}">Hello number  ${num}</g:link> 
</g:repeat>

I am not sure if it is supported, but it is definitely working.

From Mysql to Oracle: Grails application migration

Today I have finished migration of our Grails prototype. Originally we did develop it for MySQL, but the final system have to work with Oracle. This post summarize troubles and differences I was facing.

User creation

Since I am not Oracle administrator, it took me some time to put together script that creates user and appropriate rights for the Grails application. Use the script for development only.

CREATE user grails IDENTIFIED BY grassword;
GRANT connect  TO habilion;
GRANT CREATE TABLE TO habilion;
GRANT CREATE sequence TO habilion;
GRANT unlimited tablespace TO habilion;

Identifier length limitation

I usually do not use identifiers that are 30 characters long. But, there is a trick.

Imagine two classes: Author and Content. Author having multiple Contents.

Now, imagine there is several types of Content – Book, Newspaper, ElectronicNewspaper, ScientificArticle…
So, we can model the situation using following classes:

Class Content{
  static belongsTo = [ contentAuthor:Author ]
}
 
Class Book extends Content {}
Class Newspaper extends Content {}
Class ElectronicNewspaper extends Content {}
Class ScientificArticle extends Content {}
 
Class Author{
  static hasMany = [ contents: Content ]
}

And now comes the trick. The ‘content’ table in the database contains long columns:

content_author_id
newspaper_content_author_id
electronic_newspaper_content_author_id
book_content_authot_id
scientific_article_author_id

As you can see, it is easy to hit the 30 characters limit. If you look deeper, you will see the solution. The column names are composed of class name of the Content descendants and variable name pointing to the master entity.
So, I renamed the contentAuthor to ca, created getter and setter for contentAuthor and checked all “new Book…” snippets. God bless MVC!

Column size

The second major issue was a String column. I had a string column of 10000 characters.

Class Content {
  String abstract
  static constraints = { abstract(maxSize:10000) }
}

It was translated to Long data type. Unfortunately there is a bug in Oracle JDBC driver that causes nasty stack traces when processing Long data type. There is a workaround on the Internet, but it is working only for some versions of Oracle. Moreover, there is just one Long column allowed per table. So, changed the size to 4000 characters and the column was created as VARCHAR2.

And thats it!

Update: Empty strings

One thing to mention is a fact that Oracle does not distinguish between null and an empty string. So, if you try to store an empty string to Oracle DB, it actually stores it as a null value.

The problem arises, if you have not null column and you try to store empty string ‘’. For Grails it is a not null value, so it does not apply defaults. For Oracle it is null and thus constraint violation…

MagicDraw documentation

I like MagicDraw as a versatile CASE open to customizations. But recently, I’ve found this in the official MagicDraw javadoc:
Official javadoc for MagicDraw OpenAPI
Well, you can’t say the OpenAPI is missing open (ended) documentation, can you?

Update: For a start, I’ve created an index of MagicDraw 14.0 OpenAPI examples. You may find it useful – place it in
<MagicDraw_installation_directory>/openapi/examples/.

Google is the best search engine

I was checking my rail stat data and I did find this.
Google vs. Yahoo

It seems that Google is really the best search engine. Even people from Yahoo are using it. :o)

Block level helpers in Ruby on Rails

Web developer often comes to a situation where he needs to “decorate” a block of a page. There is a simple solution and simple and elegant solution.
Helpers concept in Ruby on Rails is very powerful and will be used to do the trick.

Imagine, you want to create a rounded box helper similar to Nifty Corners (http://www.html.it/articoli/nifty/index.html), but you do not want to use javascript. So, a handy helper needs to be created.
The principle of the Nifty Corners trick is adding few b tags before content, few b tags after it and few lines to CSS.

<div id="container">
<b class="rtop">
  <b class="r1"></b> <b class="r2"></b> <b class="r3"></b> <b class="r4"></b>
</b>
<!--content goes here -->
<b class="rbottom">
  <b class="r4"></b> <b class="r3"></b> <b class="r2"></b> <b class="r1"></b>
</b>
</div>

and modification of CSS

.rtop, .rbottom{display:block}
.rtop *, .rbottom *{display: block; height: 1px; overflow: hidden}
.r1{margin: 0 5px;}
.r2{margin: 0 3px;}
.r3{margin: 0 2px;}
.r4{margin: 0 1px; height: 2px;}
.r1, .r2, .r3, .r4 {background-color:red;}
.cont{background-color:red;}

Easy solution

The easy solution uses two helpers. One to put before the content and one to put it after. So, the view could look like:

...
<%= round_box_start %>
content
<%= round_box_end %>
...

Well, it does not look good. So, what about the other solution?

Easy and elegant solution

We will create a block level helper. The view will look much better.

...
<% round_box do %>
content
<% end %>
...

Now, let’s create the helper:

def round_box(&block)
  b = '<div id="container"><b class="rtop"><b class="r1"></b><b class="r2"></b><b class="r3"></b><b class="r4"></b></b><div class="cont">'
  e = '</div><b class="rbottom"><b class="r4"></b> <b class="r3"></b> <b class="r2"></b> <b class="r1"></b></b></div>'
 
  # Get the data from the block 
  data = capture(&block)
 
  res = b + data + e
 
  # Use concat method to pass text back to the view 
  concat(res, block.binding)
end

Good, but works only for red boxes. How to pass another color? Simply:

...
<% round_box(color) do %>
content
<% end %>
...

and in helper

def round_box(color, &block)
  b = '<div id="container"><b class="rtop"><b class="r1"></b><b class="r2"></b><b class="r3"></b><b class="r4"></b></b><div class="cont">'
  e = '</div><b class="rbottom"><b class="r4"></b> <b class="r3"></b> <b class="r2"></b> <b class="r1"></b></b></div>'
 
  # Get the data from the block 
  data = capture(&block)
 
  res = b + data + e
 
  # Use concat method to pass text back to the view 
  concat(res, block.binding)
end

Final implementation of the colored box is left as a homework :o)