Archive for the ‘Grails’ Category

String similarity detection

I was looking for a simple string similarity detection algorithm and I did find the one on CatalySoft. Since I like it and I found it useful, I did create a groovy equivalent of it.

Here is the code:

public class LetterPairSimilarity {
 
  /** @return an array of adjacent letter pairs contained in the input string */
  private static def letterPairs(String str) {
    (0..str.size()-2).collect{str[it,it+1]} 
  }
 
  /** @return an ArrayList of 2-character Strings. */
  private static def wordLetterPairs(String str) {
    (str.split("\\s").collect{it} - [""]).collect{ letterPairs(it) }.flatten()
  }
 
  /** @return lexical similarity value in the range [0,1] */
  public static double compareStrings(String str1, String str2) {
    if (!str1 || !str2 || str1=="" || str2=="") {return 0.0}
    def p1=wordLetterPairs(str1.toUpperCase())
    def p2=wordLetterPairs(str2.toUpperCase())
 
    2*p1.intersect(p2).size() / (p1+p2).size
  }
}

Modalbox in Grails

There is a nice and handy javascript library for creating kind of a modal “window”, similar to the famous lightbox. Here are few lines of code to make it running in a Grails application

Installation

First of all, you have to download the library. The easiest way is to install a plugin modalbox

grails install-plugin modalbox

There was a slight problem in version 0.2. So, check your plugins/modalbox-0.2/grails-app/taglib/ModalboxTagLib.groovy. The version was not correct and the script tags were not correctly ended. Here is my tag library.

class ModalboxTagLib {
 
    static namespace = "modalbox"
 
    def createLink = { attrs,body ->
        // By default trigger onclick, but allow onmouseover etc
        def event = attrs.event ? attrs.event : 'onclick';
 
        // linkname only supported for backwards-compatibility. Default it to empty-string
        def linkname = attrs.linkname ? attrs.linkname : ""
 
        out << """
            <a href='${g.createLink(attrs)}' title='${attrs['title']}' ${event}='Modalbox.show(this.href, {title: this.title, width: ${attrs['width']}}); return false;'>${linkname}${body.call()}</a>
        """
    }
 
    def modalIncludes = {
        def jsFolder    = createLinkTo(dir:'plugins',file:'modalbox-0.2/js/modalbox')
        def cssFolder   = createLinkTo(dir:'plugins',file:'modalbox-0.2/css')
 
        out << """
            <script type='text/javascript' src='${jsFolder}/prototype.js' ></script>
    		<script type='text/javascript' src='${jsFolder}/scriptaculous.js?load=effects'></script>
    		<script type='text/javascript' src='${jsFolder}/modalbox.js' ></script>
    		<link rel='stylesheet' href='${cssFolder}/modalbox.css' />
        """
    }
}

“Parent” view

In the view that will call the Modalbox, use tag modalInclude like this one.

<modalbox:createLink controller="book" action="showDetails" params="[bookId:book.id]" title="Book details" width="500">book</modalbox:createLink>

Once clicked, it calls book/showDetails

“Modalbox” view

The view of book/showDetails is quite simple. You can create any static page and it will be displayed. If you want something more “spicy”, use AJAX.

Book details
 
<g:formRemote name="myForm" url="[controller:'book',action:'findSimilar']" update="[success:'similar']" onComplete="Modalbox.resizeToContent()">
	<input type="hidden" name="bookId" value="${book.id}" />
	<input id='search' name='search' />
	<input type="submit" value="Find similar" />
</g:formRemote >
 
<div id="similar">
</div>
 
<a href="#" title="Close window" onclick="Modalbox.hide(); return false;">Close</a>

Notice the resizeToContent() method. It assures, that the content that will come via AJAX will fit. Last, but not least; for comfortable close, there is the last line.

Enjoy it.

Grails: internationalization in the service

Today I spent some time by creation of localized messages in a service. Here is a small tutorial.

1. Create your service

grails create-service Local

2. Add a messageSource variable to your new service

class LocalService {
  def messageSource
}

3. Use it in a service method

// Initialize parameters
Object[] testArgs = {}
def msg = messageSource.resolveCode("message.code.to.translate", new java.util.Locale("EN")).format(testArgs)

4. Finally edit the grails-app/i18n/messages.properties

message.code.to.translate=It works!!!

Bootstrapping Grails integration tests

It is quite easy to prepare test environment the same as the development one. Just use Bootstrap.

class BootstrappedTests extends GroovyTestCase {
  void testBootstrap() {
    new BootStrap().init(null) 
    assert MyDomain.count() == 5   // Perform your tests here
    }
}

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.