tag:blogger.com,1999:blog-91748328408907966162024-03-16T00:09:11.331-07:00Learning Technical StuffThis blog is a record of me learning stuff.I hope that in the process of recording and expressing technical stuff I will learn it better. What is technical stuff? Mostly development and computer programming, networking and other geeky tips. Enjoy!Anonymoushttp://www.blogger.com/profile/15141304569652949781noreply@blogger.comBlogger102125tag:blogger.com,1999:blog-9174832840890796616.post-6714126194272494532016-03-10T00:57:00.001-08:002016-03-10T00:57:04.356-08:00Setting up Ruby on Mac OSXMac OSX ships with a version of Ruby, but it is almost out of date. You can see the current installed version by opening a console and typing<br />
<br />
<code>$ ruby --version</code><br />
<br />
Regardless of whether the version you see reported is current, old or if Ruby is somehow not available, you'll want to take control of your Ruby version for serious development. You are interested in controlling:<br />
<br />
<ul>
<li>which Rubies are installed on your system,</li>
<li>which Ruby you happen to be using at any one time</li>
<li>which Ruby you expect your users to have to run any Ruby code you develop.</li>
</ul>
<div>
To this end you'll want to take some specific steps to get this kind of control. On OSX this is pretty easy. </div>
<div>
<br /></div>
<div>
Apart from this sort of control, you'll also want to make sure you can install gems with native extensions. Gems with native extensions need to be compiled on (or for) the target system. Ruby's gem infrastructure needs access to specific system tools and native libraries to do this. </div>
<div>
<br /></div>
<div>
Google picked <a href="https://launchschool.com/blog/how-to-install-ruby-on-rails-development-environment-for-mac-os-x">this guide</a> when I googled the question about how to install Ruby on Mac OSX. Bear in mind there is more than one way, but it happens this guide mostly mirrors how I have set my local environment up:</div>
<div>
<br /></div>
<div>
<ol>
<li>Install <a href="https://developer.apple.com/library/ios/technotes/tn2339/_index.html">X-code command line tools</a> (to support native compilation)</li>
<li>Install <a href="http://brew.sh/">Homebrew</a> (a package manager for Mac)</li>
<li>Install <a href="https://rvm.io/">RVM</a> or <a href="https://github.com/rbenv/rbenv">RBENV</a> (ruby version managers)</li>
<li>Install your Ruby or Rubies of choice using RVM or RBENV</li>
</ol>
<div>
The guide linked above uses RBENV to manage ruby versions and it has a specific instructions for the entire process. My experience is only with RVM. So if I get a chance I'll investigate further the difference and possible advantages and disadvantages.</div>
<div>
<br /></div>
<div>
<br /></div>
</div>
Anonymoushttp://www.blogger.com/profile/15141304569652949781noreply@blogger.com19tag:blogger.com,1999:blog-9174832840890796616.post-23795586337945646632016-03-08T02:28:00.001-08:002016-03-08T02:28:54.894-08:00Tooling on Mac OS for Ruby DevelopmentI mentioned in my <a href="http://www.learningtechnicalstuff.com/2016/03/life-new-casual-project.html">previous post</a> I was starting a new project, and interestingly enough, my newish 2015 iMac doesn't have much in the way of tooling for Ruby Development installed.<br />
<br />
I quickly fixed this by installing<br />
<br />
<ul>
<li><a href="https://www.iterm2.com/">iTerm2</a> - a console replacement</li>
<li><a href="https://www.sublimetext.com/">Sublime Text 3</a> - a coder's text editor</li>
</ul>
<div>
If I come across any other generic tool I end up using I might add it to this list.</div>
<div>
<br /></div>
<div>
Some basic descriptions are after the break.</div>
<div>
<a name='more'></a><br /></div>
<h2>
iTerm2</h2>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://www.iterm2.com/img/logo.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="124" src="https://www.iterm2.com/img/logo.jpg" width="320" /></a></div>
<div>
<i><br /></i></div>
<div>
<i><br /></i></div>
<div>
<a href="https://www.iterm2.com/">iTerm2</a> is an alternative to the standard <i>Console</i> program that comes with Mac OSX. It offers many features over <i>Console, </i>like Tabs, hotkeys, improved customisation, better clipboard support and more focus on the needs of the power user.</div>
<div>
<br /></div>
<div>
iTerm2 is GPLv2 and you have the option to donate on the <a href="https://www.iterm2.com/">website</a>.</div>
<div>
<br /></div>
<h2>
Sublime Text 3</h2>
<div>
<a href="https://www.sublimetext.com/">Sublime Text 3</a> is a coder's text editor, not an IDE. I started using it back when it was Sublime Text 2, and I had no problem justifying the sub-$100 license.</div>
<div>
<br /></div>
<div>
Alongside the major productivity features - tabs, completely mouse-less navigation, the innovative 'mini-map', the Goto-Anywhere feature and lots more - the robust 3rd party add-on eco-system means Sublime can be extended to support any major language, testing frameworks, linters, markup languages, source control systems, and anything else someone can dream up.</div>
<div>
<br /></div>
<div>
ST3 is therefore a good editor for Ruby, Python, the web... and who knows what else. </div>
<div>
<br /></div>
<div>
ST3 is a cross-platform editor, and while I use it all day at work on the Windows platform, ST3 benefits from the more mature unix-compatible tooling available for Ruby. Being behind a ruthless corporate proxy also commonly gets in the way. So I'm quite excited to see how I can set it up on a Mac at home.</div>
<div>
<br /></div>
<div>
Installing the <a href="https://packagecontrol.io/">Package Control</a> add-on is a must - outside the corporate proxy installation is super-simple. Once installed, further discovery and installation of anything else is trivial.The Package Control website is also a good destination just to find out what is going on in the world of ST3 packages.</div>
<div>
<br /></div>
<div>
I also found a possibly useful <a href="https://mattbrictson.com/sublime-text-3-recommendations">set of tips for setting ST3 up for Ruby</a> which I will try. There are many of these around, and the exact mix for you will depend on your platform, ruby frameworks, build systems and arbitrary preferences. ST3, if you want it to, can replace your entire shell console, but I haven't taken that leap yet.</div>
<div>
<br /></div>
Anonymoushttp://www.blogger.com/profile/15141304569652949781noreply@blogger.com25tag:blogger.com,1999:blog-9174832840890796616.post-67691665944897353472016-03-06T19:25:00.002-08:002016-03-06T19:51:13.990-08:00Life - a new casual projectAs mentioned in the previous post, I'm interested in doing some more software development in my own time. Here I formally announce a casual project to work on and even more formally denounce myself for having forgotten about it in a few weeks.<br />
<br />
Having just read and re-read some books on Darwinism, Natural Selection and Evolution while on holiday, I'm feeling inspired to write some code to demonstrate some of the principles my brain has been turning over. To that end I'm starting a new project I'm calling 'Life'. Its going to be a CLI (Command Line Interface) program written in <a href="https://www.ruby-lang.org/en/">Ruby</a>. I'm hosting it as a <a href="https://github.com/bendavieshe3/life">project on Github</a>.<br />
<br />
I'll blog some more details about the project - like how I imagine it will work and what things I intend to investigate - soon.<br />
<br />Anonymoushttp://www.blogger.com/profile/15141304569652949781noreply@blogger.com22tag:blogger.com,1999:blog-9174832840890796616.post-74847440951843565322016-03-06T18:01:00.005-08:002016-03-06T18:02:51.345-08:00Update - Its been a whileIts been a while since I posted anything to this blog. I've obviously fallen out of the habit of blogging.<br />
<br />
I can only blame the fact that every working hour is one I spend directly or indirectly on Software Engineering, and I generally can't blog about it there and then, if at all. My desire to spend precious downtime in the same has been limited by competing priorities of family, good TV, computer games (long time favourites are <a href="https://kerbalspaceprogram.com/">Kerbal Space Program</a> and <a href="https://www.factorio.com/">Factorio</a>, if you are wondering) and tiredness.<br />
<br />
Still, I've just had a holiday, and in listening to a few different books on evolution and natural selection my interest in observing via simulation some of the properties of these processes has been piqued. It is not the <a href="http://www.learningtechnicalstuff.com/2011/05/my-generations-project-and-prisoners.html">first</a> <a href="http://www.learningtechnicalstuff.com/2011/06/better-prisoners-dilemma-simulation.html">time</a>.<br />
<br />
More to come - a lack of personal time not-withstanding.Anonymoushttp://www.blogger.com/profile/15141304569652949781noreply@blogger.com8tag:blogger.com,1999:blog-9174832840890796616.post-2681057757340256102013-02-22T19:20:00.000-08:002013-02-22T19:20:11.976-08:00No such file or directory?Sometimes when a shell session shows you this error it baffles. You check the file exists, you check the syntax for the command, you check the permissions. You do everything that a page like <a href="http://askubuntu.com/questions/133389/no-such-file-or-directory-but-the-file-exists">this</a> suggests you do.<br />
<br />
And then you realise that the entire directory you are attempting to execute a command within has been deleted or recreated since your shell set it as its current working directory.<br />
<br />
I stumble across this problem from time to time when I have multiple shell windows open. If you are in a particular directory in session 1, and delete that directory in another, even if you immediately recreate a directory with the same name, all further commands in the first session that are dependent on relative directories are doomed to failure.<br />
<br />
This makes sense, but sometimes it takes me a while to remember. Maybe writing this post will trigger my memory earlier in the piece in the future.<br />
<br />Anonymoushttp://www.blogger.com/profile/15141304569652949781noreply@blogger.com5tag:blogger.com,1999:blog-9174832840890796616.post-29102118281491656422013-02-22T04:38:00.001-08:002013-02-22T04:38:28.393-08:00Quick Patch, Diff GuideYesterday I <a href="http://www.learningtechnicalstuff.com/2013/02/getting-meteor-running-on-cloud-9-ide.html">posted</a> about releasing a patch for the Cloud 9 IDE Meteor patch. I didn't mention I found a nice <a href="http://jungels.net/articles/diff-patch-ten-minutes.html">10 minute guide to diffing and patching</a> which was a great reference.<br />
<br />
Just thought I would pass that along.Anonymoushttp://www.blogger.com/profile/15141304569652949781noreply@blogger.com5tag:blogger.com,1999:blog-9174832840890796616.post-37348079490428127452013-02-20T21:45:00.000-08:002013-02-20T21:45:08.872-08:00Getting Meteor Running on Cloud 9 IDEI have been looking at <a href="http://meteor.com/">Meteor</a> recently, which is part of a new breed of JavaScript combined client and server frameworks built on <a href="http://nodejs.org/">Node.js</a> (DerbyJS is an example of another possibly abandoned framework I found).<br />
<br />
If, like me, you would prefer to have to option to develop on <a href="https://c9.io/">Cloud 9 web IDE</a> when circumstances require it you might be wondering how to install Meteor and make it work.<br />
<br />
Meteor can run on Cloud 9 IDE but it needs to be patched first to remove some of the assumptions assumptions around the local IP and Port it should use.<br />
<br />
<a href="http://ploki.info/">Vianney Lecroart</a> (aka acemtp) has already patched Meteor and offers a <a href="http://c9install.meteor.com/install.html">super-simple way to install Meteor 0.5.4</a>. This works great, but Meteor is now up to 0.5.6 and the auto-update helpfully unpatches the framework.<br />
<br />
Based on Acemtp's diff file I have created a <a href="https://github.com/bendavieshe3/meteor-c9-patch">patch for Meteor 0.5.6 to run on Cloud 9</a> and posted it to Github with instructions. Essentially, you need to apply Acetmp's installation and apply my patch using the included shell script (or manually yourself).<br />
<br />
This seems to work, but the delivery and installation is very crude. For the moment though, I am up and running with Meteor 0.5.6 on Cloud 9.<br />
<br />
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/15141304569652949781noreply@blogger.com8tag:blogger.com,1999:blog-9174832840890796616.post-15540174490979147622013-01-28T17:17:00.002-08:002013-01-28T17:17:51.662-08:00CoffeeScript in Node.jsI'm throwing together a <a href="http://blog.maxaller.name/2011/10/coffeescript-in-node-js/">Node.js</a> and Express application at the moment and trying out in anger a few of the technologies I've read about but not practiced. One of those of <a href="http://coffeescript.org/">CoffeeScript</a>.<br />
<br />
The CoffeeScript compiler is primarily available implemented on Node.js as a command line utility. You might expect that for Node.js projects, there should be a way where compilation could be handled transparently without intermediate Javascript files during development.<br />
<br />
And you would be right. But how it works is not well documented, and so I wanted to make a note of that here. I found the information in a <a href="http://blog.maxaller.name/2011/10/coffeescript-in-node-js/">blog post</a> by Max Aller.<br />
<br />
Here is the summary for an application-homed install:<br />
<ol>
<li>Include coffee-script in your application <kbd>package.json</kbd> dependencies:
<br /><kbd>package.json</kbd>
<code><br />
<pre>{
<em>snipped...</em>
<strong>"dependencies": {</strong>
"express": "3.0.6",
"jade": "*",
<strong>"coffee-script": "*"</strong>
<strong>}</strong>
<em>snipped...</em>
}
</pre>
</code>
</li>
<li>Install dependences ( npm install in the application folder)</li>
<li>Import the module: <kbd>require('coffee-script');</kbd> in your application</li>
</ol>
<div>
Once done, the .coffee extension is transparently compiled to Javascript in any require() statement.<br />
<br />
For example:<br />
<br />
<code>
require('coffee-script');<br />
require('./myCoffeeScriptFile'); <br />
# will find, parse and execute ./myCoffeeScriptFile.coffee<br />
</code>
</div>
Anonymoushttp://www.blogger.com/profile/15141304569652949781noreply@blogger.com4tag:blogger.com,1999:blog-9174832840890796616.post-30537572441152782962013-01-28T17:04:00.004-08:002013-01-28T17:04:43.242-08:00Coffee Script Literals - Do not like mixed spaces and tabsI spent a lot of time this morning trying to work out why my <a href="http://coffeescript.org/">CoffeeScript</a> literal was not working. I was trying to describe a hash containing an array containing hashes. I assumed my parse errors was simply me getting the format incorrect - Literal syntax examples for CoffeeScript available on the internet are pretty basic and don't describe nesting well.<br />
<br />
Here was the parser error:<br />
<br />
<kbd>Error: In /Volumes/Data/users/ben/(snipped)/dashboard.coffee, Parse error on line 20: Unexpected '{'<br />
at Object.parseError (/Volumes/Data/users/ben/(snipped)/node_modules/coffee-script/lib/coffee-script/parser.js:477:11)</kbd><br />
<br />
<a name='more'></a><br />
So I broke out a separate .coffee file and tried to duplicate the problem, and failed. I made sure the command line version was the same one Node.js was calling. I duplicated the Node.js parser error in the command line. I put my (working) test code side-by-side with the broken code, and the parser still walked on by the test code to fail on the original code.<br />
<br />
As the title implies, it turned out this was a simple mixed tabs and spaces problem. (I hadn't worked in .coffee files in my IDE prior and I remember needing to change the tab defaults).<br />
<br />
So the moral of the story is to check whitespace first when you see CoffeeScript parser errors.<br />
<br />
And for anyone wondering how to describe a hash-containing-array-containing-hashes literal in CoffeeScript, you write:<br />
<br />
<br />
<code>
hashContainsArrayContainsHashes =<br />
key1: "value1"<br />
key2: [<br />
key211: "value211"<br />
key212: "value212"<br />
,<br />
key221: "value221"<br />
key222: "value222"<br />
]<br />
key3: "value3"<br />
</code>
<br />
<br />
hope that helps someone!<br />
<br />Anonymoushttp://www.blogger.com/profile/15141304569652949781noreply@blogger.com4tag:blogger.com,1999:blog-9174832840890796616.post-82065262952259327232013-01-25T03:36:00.000-08:002013-01-25T03:36:22.694-08:00Node.js + Express + Connect resourcesI'm tracking a list of learning resources for node.js and popular modules like middleware collection Connect and application framework Express.<br />
<br />
As I trolled through endless videos on youtube I thought I would start making a list of the good resources I find, as some help me a lot more than others.<br />
<br />
Videos<br />
<br />
<span style="font-family: inherit;"><a href="http://www.youtube.com/watch?v=F2qsnYkF-5M">Build an object oriented RESTful web with Express.js</a></span><br />
<br />
....Anonymoushttp://www.blogger.com/profile/15141304569652949781noreply@blogger.com2tag:blogger.com,1999:blog-9174832840890796616.post-83355178055718375882013-01-25T03:26:00.000-08:002013-01-25T03:28:10.109-08:00Node.js + Github + Cloud9 + Heroku = AwesomeI don't know if there is much more to say than that. We have been performing research at work around performance and scaling for one of our applications with ridiculous quantities of data and alongside investigations of different nosql solutions came some interest in <a href="http://nodejs.org/">node.js</a>.<br />
<br />
I've obviously had a <a href="https://github.com/bendavieshe3">Github account</a> forever, and certainly used <a href="http://www.heroku.com/">Heroku</a> before, but when a colleague arrived at work one day raving about <a href="https://c9.io/">Cloud 9</a>, a web-based IDE, it felt like I had discovered the missing link.<br />
<br />
Cloud 9 lets you check out git repositories, write code, run processes and access the terminal in your own persistent development environment. Along with Github and Heroku, I now have access to a completely cloud-based development environment. There is something ridiculously attractive about that.<br />
<br />
To be clear, Cloud 9 isn't perfect. Over the course of a day I need to restart my session several times. And latency on your keystrokes is present and a persistent, minor annoyance. But I keep using it (having such excellent node.js support is a major plus).<br />
<br />
Try it if you haven't already. Cloud 9 has a charging strategy like Github - you pay for privacy but open use is free.<br />
<br />Anonymoushttp://www.blogger.com/profile/15141304569652949781noreply@blogger.com2tag:blogger.com,1999:blog-9174832840890796616.post-20290001025209794622012-06-11T05:34:00.003-07:002012-06-11T07:01:50.690-07:00Javascript Web Applications and Spine.jsIt has been a while since I even mentioned any particular book on this blog, but lately I have been reading a lot of technical books on my daily transit to and from work and this one stood out as one I received a lot of value from.<br />
<br />
<a href="http://www.amazon.com/gp/product/144930351X/ref=as_li_ss_tl?ie=UTF8&tag=leartechstuf-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=144930351X">JavaScript Web Applications</a><img alt="" border="0" height="1" src="http://www.assoc-amazon.com/e/ir?t=leartechstuf-20&l=as2&o=1&a=144930351X" style="border: none !important; margin: 0px !important;" width="1" /> (Amazon link) by Alex MacCaw is about applying the discipline of the Model View Controller software design pattern to Javascript applications.<br />
<br />
You would be forgiven for assuming these days that the only JavaScript knowledge worth knowing is how to use <a href="http://jquery.com/">JQuery</a>. Certainly only a few other domains within JavaScript get even a fraction of the ink devoted to that DOM selection and manipulation framework. My experience is that the topic of application design patterns is under served. As powerful as a framework like JQuery is it only really gives you more rope to hang yourself with if you don't have an actual application architecture.<br />
<a name='more'></a><br />
<br />
<a href="http://www.amazon.com/gp/product/144930351X/ref=as_li_ss_il?ie=UTF8&tag=leartechstuf-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=144930351X" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" src="http://ws.assoc-amazon.com/widgets/q?_encoding=UTF8&Format=_SL160_&ASIN=144930351X&MarketPlace=US&ID=AsinImage&WS=1&tag=leartechstuf-20&ServiceVersion=20070822" /></a>Javascript Web Applications begins with explaining the basics of the Model View Controller pattern and why it (or something like it) is just as critical in modern JavaScript web applications as it is in the server back end. Alex MacCaw goes on to explain and demonstrate methods of implementing inheritance, models, views, controllers and custom events within Javascript. Along the way the author builds a library of objects and methods that he refers to throughout the book, lifting your frame of reference above the nuts and bolts.<br />
<br />
Towards the end of the book I became aware that Alex MacCaw had actually created and continues to host a Javascript Framework called <a href="http://spinejs.com/">Spine.js</a> (as opposed to <a href="http://backbonejs.org/">backbone.js</a>, a popular framework with a similiar mission) based on his work in this book. It is still in development and is now available in <a href="http://coffeescript.org/">CoffeeScript</a>. Continuing to look around at Alex's work I realise he has really impressive resume and for all that he has achieved (getting this book written amongst many other things) is ridiculously young.<br />
<br />
Javascript Web Applications is a relatively opinionated book. This is something I don't mind. Alex MacCaw dislikes synchronous user interfaces and prefers his inheritance to be prototypical, not classical. His prescription for building JavaScript web applications is to separate the application into separate smaller, loosely coupled applications, sometimes organised into 'Controller stacks'. The result in the case of this book and framework is clear guidance on one approach to putting together an application.<br />
<br />
Spine.js itself is a useful framework that is still very similar to the one he presents in his book. The ajax extension library makes persisting to a backend REST service very easy. An alternative extension does the same thing for <a href="http://diveintohtml5.info/storage.html">HTML 5 local storage</a>. The Spine.js website has a lot of useful documentation and patterns (with code in both CoffeeScript and JavaScript) and presents more server-side integration points (such as Node and Rails).<br />
<br />
My first experiment with Spine.js was also my first using <a href="http://jquerymobile.com/">JQuery Mobile</a> and <a href="http://www.learningtechnicalstuff.com/2012/05/grails-and-rest.html">REST in Grails</a>. Learning these three things together was perhaps a mistake. I will write more about that application in a later post. In any case my interest in the JavaScript-centric programming and development has been rekindled in no small part to this book.<br />
<br />
Having looked around the internet as I read the book, I was surprised at how many MVC JavaScript frameworks I found. I like spine.js and I am pretty comfortable with it now but many of these other libraries offer similar features and are worth investigating. I found a useful <a href="http://codebrief.com/2012/01/the-top-10-javascript-mvc-frameworks-reviewed/">comparison of the different MCV frameworks for Javascript</a> which served as a nice jumping off point for individual libraries (even if I don't agree with the author's conclusions)<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/15141304569652949781noreply@blogger.com2tag:blogger.com,1999:blog-9174832840890796616.post-5300960085024824602012-05-23T07:24:00.000-07:002012-05-23T07:24:06.151-07:00Grails and RESTI've always been a fan of <a href="http://en.wikipedia.org/wiki/Representational_state_transfer">REST</a> (REpresentation State Transfer) APIs. As part of a simple application I am working on in my spare time I just implemented some basic REST interfaces (at least the URIs) for the ajax calls involved. I thought I would share some specifics of my experience as note for myself and for anyone else working this out as well.<br />
<br />
Implementing REST in Grails 2 is not hard, but not overly documented. The <a href="http://grails.org/doc/latest/guide/webServices.html#13.1 REST">documentation</a> is brief. I wandered far and wide from their simple example trying to resolve issues, and then made my way back.<br />
<br />
Implementing REST URIs in Grails requires changing the <a href="http://grails.org/doc/latest/guide/theWebLayer.html#6.4 URL Mappings">URL mappings</a> for that resource and the controller you need to handle these requests.<br />
<br />
<a name='more'></a><br />
For my Page resource my UrlMappings.groovy needed to contain this:<br />
<br />
<pre class="code">static mappings = {
class UrlMappings {
static mappings = {
...
//page resources
"/pages" (controller:"page", action:"list")
"/pages/$id?" (resource:"page")
...
}
</pre>
<br />
Note the use of the resource parameter. In practice this is a shortcut for specifying a standard HTTP action to controller method mapping for CRUD operations, such as GET mapping to show(), POST mapping to save(), PUT mapping to update() and DELETE mapping to delete().
Any collection resource (in the example above, '/pages') needs to be independently declared.
<br />
A fast and loose controller implementation might look like this:<br />
<br />
<pre class="code">package myapp
import grails.converters.JSON
class PageController {
def list() {
render Page.list(sort:"pageOrder") as JSON
}
def show() {
render Page.get(params.id) as JSON
}
def update() {
def page = Page.get(params.id)
bindData(page, params, excludes:'id')
render page as JSON
}
def delete() {
Page.get(params.id).delete()
render(status:204)
}
def save() {
def page = new Page()
bindData(page, params, excludes:'id')
page.save()
render(model:page,status:201) as JSON
}
}
</pre>
<br />
There is a trick to testing RESTful URL mappings. The out of the box test helpers like assertForwardUrlMapping() do not allow you to specify an HTTP method, so it needs to be set separately prior to the test:
<br />
<br />
<pre class="code">...
void testPageDelete() {
<b>webRequest.currentRequest.setMethod("DELETE")</b>
assertForwardUrlMapping("/pages/1", controller:'page',action:'delete')
}
...
</pre>
<pre class="code">
</pre>
<pre class="code">Let me know how you go.</pre>Anonymoushttp://www.blogger.com/profile/15141304569652949781noreply@blogger.com3tag:blogger.com,1999:blog-9174832840890796616.post-65029230540521292922012-05-18T04:46:00.001-07:002012-05-18T04:46:28.527-07:00Grails Resources Plugin DebuggingI'm working through an issue right now with the <a href="http://grails.org/">Grails</a> all-powerful<a href="http://grails.org/plugin/resources"> Resources Plugin</a> not live updating within the development server.<br />
<br />
I thought I would highlight a few easy choices for debugging I found on the <a href="http://grails-plugins.github.com/grails-resources/guide/8.%20Debugging.html">Resources Plugin debugging page</a>.<br />
<br />
Firstly, you can pass a couple of couple of query strings to influence behaviour<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;"><b>http://your-app-url?_debugResources=y</b></span><br />
<br />
The _debugResources=y query string parameter completely disables the resources plugin beyond simply including them in the page in the correct order. Your application shouldn't break, but resources will not be bundled or processed.<br />
<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;"><b>http://your-app-url?_refreshResources=y</b></span><br />
<br />
The _refreshResources=y query string parameter forces the resources to be refreshed and the browsers' cache to be busted.<br />
<br />
You can turn on full debugging as well relatively easily by adding the following to your conf/config.groovy file within the log4j section:<br />
<br />
<pre class="code">log4j = {
...
<b>debug 'org.grails.plugin.resource'</b>
...
}
</pre>
<br />
I hope that was helpful to someone. My issue still eludes me.Anonymoushttp://www.blogger.com/profile/15141304569652949781noreply@blogger.com2tag:blogger.com,1999:blog-9174832840890796616.post-79967882343499002362012-05-11T06:36:00.003-07:002012-05-11T06:36:54.241-07:00install-plugin not working for local targets in Grails 2.0.3Just a note for anyone coming across this error:<br />
<br />
After getting the <a href="http://grails.org/plugin/jslint">JsLint for Grails plugin</a> to work (see the previous post) I noticed there was some easy cleanup I could do on the plugin code. It was a good opportunity to get my feet wet with plugin development.<br />
<br />
In the process I learnt that the grails command install-plugin does not work for local plugin targets as <a href="http://grails.org/doc/latest/guide/plugins.html#creatingAndInstallingPlugins">specified in the documentation</a>, resulting in a failure to resolve dependency/null pointer error.<br />
<br />
<pre class="code"> ::::::::::::::::::::::::::::::::::::::::::::::
:: UNRESOLVED DEPENDENCIES ::
::::::::::::::::::::::::::::::::::::::::::::::
:: org.grails.plugins#jslint;0.4: java.lang.NullPointerException at org.apache.ivy.plugins.resolver.AbstractResolver.initRepositoryCacheManagerFromSettings(AbstractResolver.java:396)
::::::::::::::::::::::::::::::::::::::::::::::
</pre>
<br />
After quite a bit of Googling I found a <a href="http://grails.1312388.n4.nabble.com/Grails-2-0-2-Unable-to-install-downloaded-plugins-td4528413.html">comment from a <span id="goog_609970655"></span>Grails contributor</a><span id="goog_609970656"></span> that the feature was actually broken and will produce an error in Grails 2.1 when that is released. He also point referred to a useful section of the documentation that described how to reference a local, unpackaged plugin from one project to another during plugin development, which solved my requirement quite handily:<br />
<br />
<pre class="code">// Useful to test plugins you are developing.
grails.plugin.location.shiro =
"/home/dilbert/dev/plugins/grails-shiro"
// Useful for modular applications where all plugins and
// applications are in the same directory.
grails.plugin.location.'grails-ui' = "../grails-grails-ui"
</pre>
<br />
(See <i>Specifying Plugin Locations</i> in the <a href="http://grails.org/doc/latest/guide/plugins.html#creatingAndInstallingPlugins">same section of the documentation</a>)<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/15141304569652949781noreply@blogger.com2tag:blogger.com,1999:blog-9174832840890796616.post-35365155873041366332012-05-10T06:38:00.002-07:002012-05-10T06:38:51.810-07:00Running JSLint Plugin for GrailsAs a side project I am currently working on a Javascript heavy application, and I thought it was a good opportunity to see how easily Javascript testing is brought to a Grails application (which is so good at testing all of the server side components).<br />
<br />
I found the JS Lint Grails Plugin but was disheartened when it complained about a missing dependency (which causes me to reflect how spoilt dependency management has made me these days).<br />
<br />
Here was my issue:<br />
<br />
<pre class="code">grails> install-plugin jslint
| Plugin installed.
grails> jslint
| Error Error running script jslint: : taskdef class com.googlecode.jslint4java.ant.JSLintTask cannot be found
</pre>
<br />
Ridiculously easy to solve. I added the following to BuildConfig.groovy:
<br />
<pre class="code">
</pre>
<pre class="code">dependencies {
compile 'com.googlecode.jslint4java:jslint4java-ant:2.0.2'
}
</pre>
<br />
and voila:
<br />
<pre class="code">
</pre>
<pre class="code">grails> jslint
| Environment set to development.....
Running jslint on:web-app/js
| Error Error running script jslint: : JSLint: 57 errors in 2 files (Use --stacktrace to see the full trace)
</pre>
<pre class="code">
</pre>
<div class="alert">
<strong>No Reports?</strong> Make sure you are running version 0.4 or later. At the time of writing you needed to add the
grailsRepo 'http://grails.org/plugins' repository in BuildConfig.groovy to see the latest and greatest, which in this case was difference between implemented and unimplemented reporting options.
</div>Anonymoushttp://www.blogger.com/profile/15141304569652949781noreply@blogger.com2tag:blogger.com,1999:blog-9174832840890796616.post-91700969184109779382012-05-04T04:05:00.000-07:002012-05-04T04:10:42.416-07:00Building a URL Shortener in Grails - Pt 2 - Unit Testing ConstraintsIn the next few tutorials we will use unit, integration and web tests to address some of the defects in a Grails URL Shortener we created in a <a href="http://www.learningtechnicalstuff.com/2012/04/building-url-shortener-in-grails-pt-1.html">previous post</a>.<br />
<br />
<b>This time we are focusing on testing and fixing domain class constraints with unit tests.</b><br />
<br />
During these tutorials we will take a <a href="http://en.wikipedia.org/wiki/Test-driven_development">Test Driven Development (TDD)</a> approach by creating tests first to find our defects before fixing the problems and watching our tests pass.<br />
<br />
The Grails User Guide has a very nice <a href="http://grails.org/doc/latest/guide/testing.html">section on testing</a> if you need more information.<br />
<div>
<br /></div>
<div class="alert">
This tutorial has the same pre-requisites as the previous tutorial. We're starting with our slink application at the same point it was when we left it last time. If you haven't done the previous tutorial or don't have a copy, you can find it tagged as of the <a href="https://github.com/bendavieshe3/tutorial-grails-slink/tree/end_of_tutorial_1">end of the last tutorial on GitHub</a>.</div>
<h2>
<a name='more'></a>
The Story so Far</h2>
<div>
<div>
Our URL shortener consists of a single redirector controller to handle the redirection to the target URLs and a set of scaffolded admin screens to manage the creation, update and delete of short link definitions.</div>
</div>
<div>
<br /></div>
<div>
To get started, open a command prompt or terminal and navigate to the folder containing slink. Once there, enter the grails command line and run the application.</div>
<div>
<br /></div>
<pre class="code">Jupiter:slink bendavies$ <b>grails</b>
| Downloading: plugins-list.xml
grails> <b>run-app</b>
| Server running. Browse to http://localhost:8080/
| Application loaded in interactive mode. Type 'exit' to shutdown.
| Enter a script name to run. Use TAB for completion:
grails>
</pre>
<div>
<br />
Return to the command prompt and test the application using the <b>test-app</b> command:</div>
<div>
<br /></div>
<pre class="code">grails> <b>test-app</b>
| Running 3 unit tests... 1 of 3
| Failure: testSomething(slink.AdminControllerTests)
| java.lang.AssertionError: Implement me
at org.junit.Assert.fail(Assert.java:93)
at slink.AdminControllerTests.testSomething(AdminControllerTests.groovy:15)
| Running 3 unit tests... 2 of 3
| Failure: testSomething(slink.RedirectorControllerTests)
| java.lang.AssertionError: Implement me
at org.junit.Assert.fail(Assert.java:93)
at slink.RedirectorControllerTests.testSomething(RedirectorControllerTests.groovy:15)
| Running 3 unit tests... 3 of 3
| Failure: testSomething(slink.ShortlinkTests)
| java.lang.AssertionError: Implement me
at org.junit.Assert.fail(Assert.java:93)
at slink.ShortlinkTests.testSomething(ShortlinkTests.groovy:15)
| Completed 3 unit tests, 3 failed in 1315ms
| Packaging Grails application.....
| Tests FAILED - view reports in target/test-reports
</pre>
<br />
When called without parameters, the <b>test-app</b> command runs all the tests - unit integration and functional tests. You might recall that when we created our admin controller, redirector controller and short link domain class a test was automatically generated for all three.<br />
<br />
The above output of the test-app command shows that all three unit tests fail. Grails creates each unit test case with a single test that will that forces a test failure.<br />
<br />
If you would like to see a pretty HTML report of your most recent test executions, type <b>open test-report</b> at the Grails command prompt.<br />
<br />
Grails has a home for all tests, separate from the source code of the application, in a folder named <i>test</i> immediately below the application's home folder. Here is what the domain class Shortlink's unit test looks like, unchanged from when it was generated with our <b>create-domain-class Shortlink </b>command in the first tutorial, and found under /test/unit/slink as <i>ShortlinkTests.groovy</i>:<br />
<br />
<pre class="code">package slink
import grails.test.mixin.*
import org.junit.*
/**
* See the API for {@link grails.test.mixin.domain.DomainClassUnitTestMixin} for usage instructions
*/
@TestFor(Shortlink)
class ShortlinkTests {
void testSomething() {
fail "Implement me"
}
}
</pre>
<br />
From this we can see only one test is defined, testSomething(), and it uses the fail() method to force a failure lest we forget to implement an automatically generated test.<br />
<h2>
Testing Domain Class Constraints</h2>
One of the problems we pointed out at the end of the last tutorial was that any value could be entered into the scaffolded administration screens, to ruinous effect. Spaces and non-web-friendly characters could be entered into either the shortLink or targetUrl properties of the ShortLink class which would cause the redirector to fail messily when a user tried to access the short link URL.<br />
<br />
The grails framework encourages validation to be performed by the model to avoid duplication and ensure that no matter how data is entered in an application, it is always validated. This means we can use a unit test to ensure that validation is being carried out according to our requirements.<br />
<br />
Open /test/unit/slink/ShortlinkTests.groovy in your favourite editor or IDE if you haven't already. We are first going to define a happy path test where the data matches our expectations, and watch it pass. Delete the testSomething() method and add this test instead:<br />
<br />
<pre class="code">void testExpectedInputOK() {
def s = new Shortlink(shortLink:'grails', targetUrl:'http://grails.org')
mockForConstraintsTests(Shortlink, [s])
assert s.validate()
}
</pre>
<br />
This simple test creates a new Shortlink and validates it. The mockForContraintsTests() method is specifically designed to facilitate testing constraints by making validation outcomes more accessible.<br />
The validate() method, on the other hand, exists on the domain class (being provided by a mixin). Its use within application code is rare because it is normally called automatically by the persistence methods such as save() and update().<br />
<br />
Back on the Grails command line, run only this unit test for the shortlink domain class:<br />
<br />
<pre class="code">grails> <b>test-app Shortlink :unit</b>
| Completed 1 unit test, 0 failed in 89ms
| Tests PASSED - view reports in target/test-reports
grails>
</pre>
<br />
We now have a working unit test for our domain class. Add another two tests to ShortlinkTests.groovy:<br />
<br />
<pre class="code">void testNullValuesFailValidation() {
def s = new Shortlink()
mockForConstraintsTests(Shortlink, [s])
assert !s.validate()
assert 'nullable' == s.errors['shortLink']
assert 'nullable' == s.errors['targetUrl']
}
void testLongShortLinkFailsValidation() {
def s = new Shortlink (shortLink:'Iamareallylongshortlinkwhichshouldnotbeallowed',
targetUrl:'http://grails.org')
mockForConstraintsTests(Shortlink, [s])
assert !s.validate()
assert s.hasErrors()
assert s.errors['shortLink'] == 'size'
}
</pre>
<br />
Run these unit tests using the same procedure. Both of these tests will pass, but instead of checking the normal operation of the domain class these tests purposefully set bad or incorrect data into the Shortlink instance - in the first by not setting any property values and in the econd by using too long a string for the shortLink property. Notice we not only check that the Shortlink doesn't validate but also that the expected errors are found recorded against the domain class instance.<br />
<br />
To see why these tests pass, we need to examine the Shortlink domain class:<br />
<br />
<pre class="code">class Shortlink {
String shortLink
String targetUrl
static constraints = {
shortLink size:1..25
targetUrl size:1..255
}
}
</pre>
We specify the validation we require in two ways:<br />
<br />
<ul>
<li>At a very basic level, by choosing the correct data type for our properties</li>
<li>In the static constraints block</li>
</ul>
<div>
The constraints block allows us to set a range of built in constraints, or to apply our own custom validations. As mentioned above, the domain object can not be persisted if these fail, and if they fail, useful information about the failure is stored in the domain class instance itself.</div>
<div>
<br /></div>
<div>
Grails will also introspect the constraints of a domain class during scaffolding. This is why, for example, our shortLink property uses an input(type=text) form element within the create and edit screens while the targetUrl is given a textbox. Grails sees that targetUrl is a much bigger field and needs more space.</div>
<div>
<br /></div>
<div>
When we try to create shortLink of more than 25 characters, as in testLongShortLinkFailsValidation(), validation fails because the constraints specify the size of the String must be between 1 and 25 characrters long. Because that is the behaviour we want, our test asserts that validation has in fact failed, and failed for the correct reason.</div>
<div>
<br /></div>
<div>
In our other test, testNullValuesFailValidation() we do not set any properties before validating. This fails because all properties implicitly have a contraint nullable:false, which needs to be overridden with nullable:true if we want our properties to be optional. Again, because we do not want Shortlinks to have a null short link name or target URL the test asserts that this is the correct behaviour. </div>
<h2>
Making our tests fail...</h2>
<div>
Having established the existing behaviour (vaguely), we can target the defects we already suspect are present:<br />
<br />
<ul>
<li>Nothing prevents a short link name from containing whitespace or special characters</li>
<li>Our target URL might not contain a real URL at all</li>
</ul>
<div>
Lets confirm both with a couple of tests:</div>
<div>
<br /></div>
<pre class="code">void testInvalidCharactersInShortLinkFailsValidation()
{
def s = new Shortlink (shortLink:'a short link',
targetUrl:'http://grails.org')
mockForConstraintsTests(Shortlink, [s])
assert !s.validate()
}
void testInvalidUrlInTargetUrlFailsValidation()
{
def s = new Shortlink (shortLink:'grails',
targetUrl:'not a URL')
mockForConstraintsTests(Shortlink, [s])
assert !s.validate()
}
</pre>
<br />
These tests follow the same format as the other constraint tests. Load an instance variable with property values and assert they should or should not pass validation. If you rerun your unit tests with <b>test-app Shortlink :unit</b> you will see that both tests fail, so our suspicions were correct.<br />
<h2>
And then pass...</h2>
Now, how to fix? Fixing the targetUrl property is easiest since Grails has a built in validation for properties which should only contain URLs. Update the constraints block in the Shortlink.groovy domain class file to look like this:<br />
<br />
<pre class="code">static constraints = {
shortLink size:1..25
targetUrl size:1..255, <b>url:true</b>
}
</pre>
<br />
Save the file and run the Shortlink unit tests again. Simply adding this one additional validation parameter now allows our testInvalidUrlInTargetUrlFailsValidation() method to pass. That is, a value that is not a valid URL will not validate, which is the behave we want. We know we have not broken the existing behaviour because our other tests still pass.<br />
<br />
Making testInvalidCharactersInShortLinkFailsValidation() pass is only slightly less straight forward. We essentially only want alphanumeric characters in the shortLink property. We can turn to the <i>matches</i> constraint to check that the provided value matches a given regular expression. Update the constraints declaration again to specify this:<br />
<br />
<pre class="code">static constraints = {
shortLink size:1..25, <b>matches:"[a-zA-Z0-9]+"</b>
targetUrl size:1..255, url:true
}
</pre>
<br />
rerun the unit tests and watch all 5 pass. Now that know how we are validating these two issues we can update the tests to check that validation error is recorded as the correct type. This I will leave as an exercise for you. The original passing tests we defined show an example of how this is done.<br />
<br />
I mentioned earlier that the scaffolding would adjust to reflect the constraints of the domain class. Start your development server if it is not already running (using <b>run-app</b>). If you now try to create short link name with spaces or otherwise not meeting our new constraints, Grails is smart enough to validate this as you type:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgu6bDeptCQVCoqfTdcyNwc7MVvYuaOD6AAXooGH0UinT4pu_7Zp8d1QvsgzS4Ld7zs9k1ld5RbKhlBqtoU3TlKPXGgg4NEtkO0C64rCWmWXXlcC-SlqLGSVmH2keBhqpJzrasbdbuEavo/s1600/grails+bad+short+link.tiff" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="176" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgu6bDeptCQVCoqfTdcyNwc7MVvYuaOD6AAXooGH0UinT4pu_7Zp8d1QvsgzS4Ld7zs9k1ld5RbKhlBqtoU3TlKPXGgg4NEtkO0C64rCWmWXXlcC-SlqLGSVmH2keBhqpJzrasbdbuEavo/s320/grails+bad+short+link.tiff" width="320" /></a></div>
Although the scaffolding won't detect an invalid URL until it is submitted:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIx9_z9sbL82jvpTCnuYJmdgMzGKPe5KPZ7Qy_LBvv5zFuJbYO2w4S-7hsxrbx9HXu6-ecju5UwmjosSWiL0OF8HhRcP86WeU6eb8obcYU5ttfG8QlHTxK3hfmrwCnromiF6BjdVB1N14/s1600/grails+bad+target+url.tiff" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="113" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjIx9_z9sbL82jvpTCnuYJmdgMzGKPe5KPZ7Qy_LBvv5zFuJbYO2w4S-7hsxrbx9HXu6-ecju5UwmjosSWiL0OF8HhRcP86WeU6eb8obcYU5ttfG8QlHTxK3hfmrwCnromiF6BjdVB1N14/s400/grails+bad+target+url.tiff" width="400" /></a></div>
<br />
<h2>
The End</h2>
There is certainly more unit testing we can do on the constraints and at least one more major problem with the validation being applied. But I might leave this tutorial here.<br />
<br />
As mentioned, Grails provides a way to test nearly everything, and the approaches you use are well documented in the <a href="http://grails.org/doc/latest/guide/testing.html">testing section of the User Guide</a>. Test your domain-class constraints in the domain class unit tests to make sure you get them right.<br />
<br />
<br /></div>Anonymoushttp://www.blogger.com/profile/15141304569652949781noreply@blogger.com1tag:blogger.com,1999:blog-9174832840890796616.post-65201449837093999182012-04-29T05:55:00.001-07:002012-05-04T04:07:02.140-07:00Hello GroovyThis is a quick exploration of how <a href="http://groovy.codehaus.org/">Groovy</a> relates to <a href="http://www.java.com/">Java</a>.<br />
<h2>
Compiling and Running</h2>
Take a simple Java HelloWorld program, HelloWorld.java:<br />
<br />
<br />
<pre class="code">/**
* A Simple Hello World Program in Java
*/
public class HelloWorld {
public static void main(String[] args) {
String name;
if(args.length > 0) {
name = args[0];
} else {
name = "World";
}
System.out.println("Hello, " + name);
}
}
</pre>
<div class="p2">
and confirm it compiles and executes in java:</div>
<div class="p2">
<br /></div>
<div class="p2">
</div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Jupiter:src bendavies$ <b>javac HelloWorld.java</b></span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"></span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Jupiter:src bendavies$ <b>ls HelloWorld.class</b></span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">HelloWorld.class</span></div>
<br />
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Jupiter:src bendavies$ </span><b style="font-family: 'Courier New', Courier, monospace; font-size: small;">java HelloWorld Ben</b></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Hello, Ben</span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<br />
<div class="p2">
See that we can compile it and run it as is using Groovy:</div>
<div class="p2">
<br /></div>
<div class="p2">
</div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Jupiter:src bendavies$ <b>rm *.class</b></span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Jupiter:src bendavies$ <b>groovyc HelloWorld.java</b></span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Jupiter:src bendavies$ <b>groovy HelloWorld Ben</b></span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Hello, Ben</span></div>
<br />
<div class="p2">
</div>
<a name='more'></a><br />
<div class="p2">
Groovyc is the Groovy compiler, which can compile both Groovy and Java source code.</div>
<div class="p2">
<br /></div>
<div class="p2">
If we change the file extension to 'groovy' we can run it directly without the compile step:</div>
<div class="p2">
<br /></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Jupiter:src bendavies$ <b>cp HelloWorld.java Helloword.groovy</b></span></div>
<div class="p2">
</div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Jupiter:src bendavies$ <b>groovy HelloWorld.groovy Ben</b></span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Hello, Ben</span></div>
<div class="p2">
<br /></div>
<div class="p2">
All without changing any Java code.</div>
<h2>
Simplifying the code</h2>
<div>
We've chosen an extremely simple example, but it still amounts to 8 lines of code. Groovy allows this code to be simplified dramatically. </div>
<div>
<br /></div>
<div>
To start with, we do not need the surrounding class and main function - Groovy does something similiar for us automatically. This is now a groovy script. </div>
<div>
<br /></div>
<div>
Try this by changing the HelloWorld.groovy file to </div>
<div>
<br /></div>
<div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">String name;</span></div>
<div class="p3">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span></span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="s1">if</span>(args.<span class="s2">length</span> > 0) { </span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> name = args[0];</span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">} <span class="s1">else</span> {</span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> name = <span class="s3">"World"</span>;</span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">}</span></div>
<div class="p3">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span></span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">System.<span class="s2">out</span>.println(<span class="s3">"Hello, "</span> + name);</span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
</div>
<div class="p2">
and run it again:</div>
<div class="p2">
<br /></div>
<div class="p2">
</div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Jupiter:src bendavies$ <b>groovy HelloWorld.groovy Ben</b></span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Hello, Ben</span></div>
<br />
<div class="p2">
<br /></div>
<div class="p2">
Groovy does not require semi-colons to separate statements on separate lines, nor does it require parenthesises around method parameters. Taking this into account:</div>
<div class="p2">
<br /></div>
<div class="p2">
</div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="s1">S</span>tring name</span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="s2">if</span>(<span class="s1">args</span>.<span class="s1">length</span> > <span class="s3">0</span>) { </span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span"></span> name = <span class="s1">args</span>[<span class="s3">0</span>]</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">} <span class="s2">else</span> {</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span"></span> name = <span class="s4">"World"</span></span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">}</span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">System.<span class="s5">out</span>.println <span class="s4">"Hello, "</span> + name</span></div>
<br />
<div class="p2">
<br /></div>
<div class="p2">
Groovy automatically imports system APIs into the namespace and extends the String class to become a GString, which has many additional capabilities including support for inline variable evaluation. The last line can be changed to:</div>
<div class="p2">
<br /></div>
<div class="p2">
</div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="s1">println </span>"Hello, ${name}"</span></div>
<br />
<div class="p2">
<br /></div>
<div class="p2">
Groovy also has its additional methods of boolean evaluation (known as Groovy Truth). In particular List objects (which by default replace Array objects) whose length is zero evaluate to false. We can simplify our conditional and change:</div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">if( args.length > 2 ) { .. }</span></div>
<div class="p2">
<br /></div>
<div class="p2">
to simply:</div>
<div class="p2">
<br /></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">if( args ) { .. }</span></div>
<div class="p2">
<br /></div>
<div class="p2">
Famously, Groovy is a dynamically typed language. When we declare the variable name we do not need to type it - Groovy will detect and assign a data type at runtime. The 'def' keyword is used for untyped declarations:</div>
<div class="p2">
</div>
<div class="p1">
<span class="s1"><br /></span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="s1">d</span><span class="s2">ef</span> name</span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="s2">if</span>(<span class="s3">args</span>) { </span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span"></span> name = <span class="s3">args</span>[<span class="s4">0</span>]</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">} <span class="s2">else</span> {</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span"></span> name = <span class="s5">"World"</span></span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">}</span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="s6">println </span>"Hello, ${name}"</span></div>
<br />
<div class="p2">
<br /></div>
<div class="p2">
Using the ternary '?' operator we can actually move the entire conditional inside of the GString parameter to println. We can now write the entire Groovy HelloWorld example in a single line:</div>
<div class="p2">
<br /></div>
<div class="p2">
</div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="s1">p</span><span class="s2">rintln </span>"Hello, ${<span class="s3">args</span>?<span class="s3">args</span>[<span class="s4">0</span>]:'World'}"</span></div>
<br />
<div class="p2">
<br /></div>
<div class="p2">
Which is pretty neat. As you can tell Groovy strips back a lot of the unnecessary or mundane scaffolding required in Java with some solid assumptions and additional support that is a good fit for many applications.</div>
<br />
<div class="p2">
<br /></div>
<div class="p2">
Note that apart from a few edge cases any Java code can simply be renamed and treated as Groovy code. Groovy code can be called from Java and vice versa. </div>
<div class="p2">
<br /></div>Anonymoushttp://www.blogger.com/profile/15141304569652949781noreply@blogger.com2tag:blogger.com,1999:blog-9174832840890796616.post-51119429000340152122012-04-26T07:14:00.003-07:002012-04-26T07:16:17.446-07:00Adding a Grails 2.0* application to GitThis is a quick note to remind me what my <a href="http://book.git-scm.com/4_ignoring_files.html">.gitignore file</a> looks like for Grails 2.* applications:<br />
<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">*.iws</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">*Db.properties</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">*Db.script</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">.settings</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">.classpath</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">.project</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">eclipse</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">stacktrace.log</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">target</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">target-eclipse</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">/plugins</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">/web-app/plugins</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">/web-app/WEB-INF/classes</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">web-app/WEB-INF/tld/c.tld</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">web-app/WEB-INF/tld/fmt.tld</span><br />
<div>
<br /></div>
<br />
I found this <a href="https://devcenter.heroku.com/articles/grails">list on Heroku</a> and added the eclipse-specific target-eclipse.<br />
<br />
To add to git:<br />
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">Jupiter:slink bendavies$ Jupiter:slink bendavies$ git init</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">Initialized empty Git repository in /Volumes/Data/users/bendavies/Documents/Projects/grails/slink/.git/</span><br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">Jupiter:slink bendavies$ git add .</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">Jupiter:slink bendavies$ git commit -m init</span><br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;">[master (root-commit) a212627] init</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> 62 files changed, 2847 insertions(+), 0 deletions(-)</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> create mode 100644 .gitignore</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> create mode 100644 application.properties</span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> create mode 100644 grails-app/conf/ApplicationResources.groovy</span><br />
<span style="font-family: 'Courier New', Courier, monospace;">...</span><br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/15141304569652949781noreply@blogger.com4tag:blogger.com,1999:blog-9174832840890796616.post-37777339345109343812012-04-25T05:51:00.002-07:002012-04-30T05:50:43.922-07:00Building a URL Shortener in Grails - Pt 1This is a lightning tutorial about how to create a URL shortener in <a href="http://grails.org/">Grails</a> (working with 2.03) that I prepared in my own time and shared with some colleagues at work. I present it below with a bit more explanatory wording. I hope it is useful.<br />
<h2>
What we are building</h2>
The design goal of this tutorial is to build a simple URL shortener. URL shorteners have no been around for years (for an example look at the <a href="http://bit.ly/">bit.ly service</a>). By navigating to a short URL, your browser is redirected to the longer one (which might be highly unmemorable and clumsy - I'm looking at you, Sharepoint!)<br />
<br />
Throughout this tutorial I refer to <i>Short URL</i> as the actual URL you would type into your browser and <i>Short link</i> as the name of the unique part of the URL after the domain.<br />
<br />
For our application we want to be able to:<br />
<ol>
<li>Create new short link definitions (eg. Our short link 'cats' should send the user to http://en.wikipedia.org/wiki/Cat) and then edit and delete them as required</li>
<li>Actually redirect the user when they visit a short URL corresponding with a short link we have defined.</li>
</ol>
<div>
We'll call our application 'slink', for 'short link.' Lets get started.<br />
<br />
<div class="alert">
<b>Update 30-Apr-2012</b>: This application is <a href="https://github.com/bendavieshe3/tutorial-grails-slink">available on Github</a> and <a href="https://github.com/bendavieshe3/tutorial-grails-slink/tags">tagged as it is at the end of the tutorial</a>.</div>
</div>
<div>
<a name='more'></a></div>
<h2>
Pre-requisites</h2>
To complete this tutorial, you need a working Grails installation, so therefore you need to have Java and Groovy installed. These need to be installed in this order: <a href="http://www.java.com/">Java</a>, <a href="http://groovy.codehaus.org/">Groovy</a>, <a href="http://grails.org/">Grails</a>. Grails is built on Groovy which in turn is built on Java.<br />
<br />
Take care to set up (or check that the installation program has set up) your environmental variables. From the command line in whichever folder you would like to use as a working directory, you should be able to run the following commands:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">C:\projects\> <b>java -version</b></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">java version "1.6.0_31"</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Java(TM) SE Runtime Environment (build 1.6.0_31-b04-415-11M3635)</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01-415, mixed mode)</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">C:\projects\> <b>groovy -version</b></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Groovy Version: 1.8.6 JVM: 1.6.0_31 Vendor: Apple Inc. OS: Mac OS X</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">C:\projects\> <b>grails -version</b></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Grails version: 2.0.3</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">C:\projects\> </span><br />
<br />
The versions don't really matter unless you might have installed one of these a long time ago.<br />
<h2>
Creating an Application</h2>
Grails is a web framework, development environment, test framework and automation framework all in one. It provides everything you need to get an application developed quickly from a standing start.<br />
<br />
When starting a new Grails application, the first thing you need to do is to ask Grails to create a new application. The <b>create-app</b> command creates a new subfolder to your current folder and populates it with both a starting point to your application code and all in the information required to deploy it locally.<br />
<br />
To run a grails command directly from the <a href="http://grails.org/doc/latest/guide/commandLine.html">command line</a>, use the format:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">C:\projects\> </span><b style="font-family: 'Courier New', Courier, monospace; font-size: small;">grails <i>command</i> [<i>params</i>]</b><br />
<br />
From the command line in your working folder, create a new application named 'slink':<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">C:\projects\> <b>grails create-app slink</b></span><br />
<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Loading Grails 2.0.3</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Configuring classpath.</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Environment set to development.....</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Installing zip tomcat-2.0.3.zip.....</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">...</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">C:\projects\></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span><br />
<span style="font-family: Times, 'Times New Roman', serif;">When using Grails commands to modify or run or test an application (as Grails development normally entails), we need to be within our application folder.</span><br />
<span style="font-family: Times, 'Times New Roman', serif;"><br /></span><br />
<span style="font-family: Times, 'Times New Roman', serif;">Navigate to the subfolder that grails just created for your new application:</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">C:\projects\> <b>cd slink</b></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">C:\projects\slink ></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><br /></span><br />
<span style="font-family: Times, 'Times New Roman', serif;">Have a look around using the command line, Windows Explorer, Finder or however you feel comfortable. This folder already contains a folder structure for your application code, resources, tests, configuration and more.</span><br />
<span style="font-family: Times, 'Times New Roman', serif;"><br /></span><br />
<span style="font-family: Times, 'Times New Roman', serif;">We are going to launch the Grails command line interface, which lets us enter commands without constantly prefixing them with 'grails'. It also gives us access to tab-completion, which really helps to explore all of the commands available within Grails.</span><br />
<span style="font-family: Times, 'Times New Roman', serif;"><br /></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">C:\projects\slink\> <b>grails</b></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Enter a script name to run. Use TAB for completion:</span><br />
<br />
If you need to exit back to the raw command prompt or shell, just type <b><span style="font-family: 'Courier New', Courier, monospace;">exit</span></b>. The first time you run Grails, it will download a number of supporting libraries.<br />
<br />
Even now we can run our application. Into the grails command-line, execute the run-app command:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">grails> <b>run-app</b></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Server running. Browse to http://localhost:8080/slink</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Application loaded in interactive mode. Type 'exit' to shutdown.</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Enter a script name to run. Use TAB for completion: </span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">grails> </span><br />
<br />
<div>
<span style="font-family: Times, 'Times New Roman', serif;">The run-app command starts a lightweight development server hosting your application. To demonstrate this is true, open <i>http://localhost:8080/slink</i> in your browser as directed. You will see the default Grails homepage - your only page so far - showing a welcome message and listing the plugins you have installed. Creating this empty application is nearly always the first thing you will do when beginning grails development.</span><br />
<span style="font-family: Times, 'Times New Roman', serif;"><br /></span><br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5XxFUTOxRtwbWuB0Hbo89KN2AP2dpSqBb_LJZlROESykLg3rgyx8njff7hqbJITEM2emc7ZJTpw5z95rzP0sWVlcIyWh3xJK7E_30WYbzjKNggt7uosdwvP29vDVf2reh00Gc4668G48/s1600/grails_default_home_page.tiff" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="156" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5XxFUTOxRtwbWuB0Hbo89KN2AP2dpSqBb_LJZlROESykLg3rgyx8njff7hqbJITEM2emc7ZJTpw5z95rzP0sWVlcIyWh3xJK7E_30WYbzjKNggt7uosdwvP29vDVf2reh00Gc4668G48/s400/grails_default_home_page.tiff" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Default home page of a Grails application</td></tr>
</tbody></table>
<h2>
Creating a ShortLink Domain Class</h2>
</div>
Its time to start turning your empty application into the URL shortener we intend to make. One of the advantages to working with a framework like Grails is that you are strongly encourage to follow good development practices and separate the different parts of your application. Grails separates the model into what it calls <i>domain classes</i> and makes it super-simple to persist instances of those classes to the database.<br />
<br />
In the URL shortener we are making, we only really need to track our list of short links. Create the application's model now:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">grails> <b>create-domain-class shortlink</b></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Created file grails-app/domain/slink/Shortlink.groovy</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Created file test/unit/slink/ShortlinkTests.groovy</span><br />
<br />
As the messages show, Grails has created two files - the actual domain class Shortlink.groovy and a unit test for this class.<br />
<br />
We will put aside talking about the unit test for the purpose of this tutorial, but it is worth noting that nearly everything has a defined approach to testing in Grails, and many commands - like the above - create a corresponding test for an item you create.<br />
<br />
Open grails-app/domain/slink/Shortlink.groovy in your favourite text editor or IDE. You’ll see:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">package slink</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">class Shortlink {</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> static constraints = {</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> } </span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">}</span><br />
<br />
This is an empty domain class. Lets define the data we are trying to model. To do this we add property definitions to the class that Grails will automatically map to the database when we class special methods added to this class at runtime. <br />
<br />
Add a short link and target URL property to the domain class. We represent both these as strings:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">class Shortlink {</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> <b>String shortLink</b></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> <b>String targetUrl</b></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> static constraints = {</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">}</span><br />
<br />
add some constraints, save, and close the file:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">class Shortlink {</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">...</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> static constraints = {</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><b> shortLink size:1..25</b></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><b> targetUrl size:1..255</b></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> } </span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">}</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span><br />
Constraints provide additional behaviour about the properties that Grails can use when validating new objects prior to saving or for influencing how the property is displayed when a domain class is scaffolded (more on that later).<br />
<br />
And thats all you need to do within the domain class for the moment. Later you can go into the class, add additional constraints and perhaps a few more useful properties.<br />
<h2>
Creating an Admin Controller</h2>
So far we defined a single domain class, but our application is unchanged (visit your application if you want to make sure - the Development Server is still running unless you have stopped it).<br />
<br />
We need to tell our application to actually <i>do</i> something. That is what controllers are for: responding to user input (such as requesting a specific web page) and deciding how to react.<br />
<br />
We are now going to create a controller for our application. This controller will be responsible for responding to all of our instructions to <i><b>admin</b></i>ister our short links. Back at the Grails command line, type the following:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">grails> <b>create-controller admin</b></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Created file grails-app/controllers/slink/AdminController.groovy</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Created file grails-app/views/admin</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Created file test/unit/slink/AdminControllerTests.groovy</span><br />
<br />
Grails has created 2 files and a folder<br />
<ul>
<li><i>AdminController.groovy</i> is the controller itself. Notice how Grails appended Controller to the name.</li>
<li>The folder <i>/views/admin</i> is a default location for any views you create for that controller. A view defines how the program output is presented to the end user, quite separately from the controller (which decides what to do).</li>
<li><i>AdminControllerTests.groovy</i> is a unit test.</li>
</ul>
<br />
Open the newly created controller in your text editor or IDE. You will see something like:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">package slink</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">class AdminController {</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> def index() { }</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">}</span><br />
<br />
There isn't much there, but as of the creation of this file, Grails will direct any requests for <i>http://localhost:8080/slink/admin</i> to this controller to work out what needs to be done. Each public method inside of the controller defines an action that can be undertaken by the controller. Grails determines the action from the URL of the request. By default:<br />
<br />
<b>http://.../slink/admin</b> will call method <b>AdminController.index()</b> (index is the default controller action)<br />
<b>http://.../slink/admin/index</b> will call method <b>AdminController.index()</b><br />
<b>http://.../slink/admin/abc</b> will call method <b>AdminController.abc()</b><br />
<b>http://.../slink/admin/dogsandcats</b> will call method <b>AdminController.</b><b> dogsandcats</b><b>()</b><br />
<div>
<b><br /></b></div>
<div>
...and so forth.</div>
<br />
Remove the index method and tell Grails that this controller should use dynamic scaffolding for provide create, read, update and delete functionality for ShortLink domain class objects.<br />
<br />
Make your controller file look like this:<br />
<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">package slink</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">class AdminController {</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> <b>static scaffold = Shortlink</b></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">}</span><br />
<h2>
Scaffolding</h2>
Scaffolding is the name for automatically generating code to suit a common generic purpose. What we did with our changes to the AdminController above was tell Grails it should scaffold the domain class. In this context that means Grails will dynamically generate methods on our controller to provide create, read, update and delete (CRUD) actions for the ShortLink domain class. The corresponding views are also dynamically generated.<br />
<br />
What this means is that a basic version of our Short Link administration functionality is complete.<br />
<br />
Have another look at the application. If you refresh the page at http://localhost:8080/slink you should see now that a list of controllers is included on the homepage, which now includes the AdminController we just created. If you click the link for the AdminController or type in the URL http://localhost/slink/admin you will see you have a fully functional facility to view and manage Short Link objects.<br />
<br />
Try creating, updating or deleting some short links.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZ54MWRBMUxWXFTTcvLdp0BYsgN3rrbxjAnY9CR6wZOMsDHAGNr1wHt-5mJ7xUwCXKt4nNAv0vX7icHIbXh6Il1PREuQc1YgfL9fBN93FXiys4KXvKO-d6sAhquibCuddzxOMoBYs-DzY/s1600/grails+slink+scaffold+admin+screen.tiff" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="137" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZ54MWRBMUxWXFTTcvLdp0BYsgN3rrbxjAnY9CR6wZOMsDHAGNr1wHt-5mJ7xUwCXKt4nNAv0vX7icHIbXh6Il1PREuQc1YgfL9fBN93FXiys4KXvKO-d6sAhquibCuddzxOMoBYs-DzY/s400/grails+slink+scaffold+admin+screen.tiff" width="400" /></a></div>
<br />
<b>Note:</b> Grails does its best to update the development server as you make changes, but my experience is that sometimes you need to restart the development server to see changes or clear a strange error. To restart the development server you started at the command prompt, type <b>exit</b> and then <b>run-app</b>.<br />
<br />
As you add, update, view and delete Short Links, Grails is using its own GORM (Grails Object Relational Mapper) technology store the date you enter and change in the bundled in-memory H2 database. The default database and its configuration means that any data you enter only exists until the development server is running. This makes a lot of sense for development work but like everything else in Grails, if you don't like the convention you can choose configuration.<br />
<h2>
Adding a Controller for Redirection</h2>
Creating and managing short links is useless we implement the means by which a user requests a short URL containing the short link and is redirected to the target URL. Since this is a response to a user event (requesting the short URL) and generates a response (the redirection) this is the job for a new controller. Lets create one now. Back at the Grails command prompt:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">grails> <b>create-controller redirector</b></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Created file grails-app/controllers/slink/RedirectorController.groovy</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Created file grails-app/views/redirector</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Created file test/unit/slink/RedirectorControllerTests.groovy</span><br />
<br />
Again, notice that Grails has gone to the trouble of creating not only the controller, but also a test and a folder to contain default views for the controller.<br />
<br />
Unlike the Admin Controller where we could use scaffolding to achieve our aims, there is no way Grails could know what we actually want from this controller. So we need to know what we want.<br />
<br />
What we need the controller to do is handle a request routed to the controller to accept a short link and redirect to the corresponding target URL. In other words, we want to:<br />
<br />
<ol>
<li>Accept a value from the request, being the short link we want to redirect to</li>
<li>Find the the ShortLink object with the same short link value, and</li>
<li>redirect to the URL in the targetUrl property of that short link </li>
</ol>
<br />
To write the controller method that will do this, open the RedirectorController.groovy file we have just created in your text editor or IDE and provide an implementation of the index() method, like this:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">class RedirectorController {</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> def index(<b>String shortLinkName</b>) {</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> <b>redirect url:Shortlink.findByShortLink(shortLinkName).targetUrl</b></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> }</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">}</span><br />
<br />
Save the controller when you are done. There are quite a few things here we could take note of:<br />
<ul>
<li>We are accepting a shortLinkName parameter. Grails will provide this value when it is provided in the request. Whether or not the parameter is found in a request query string, form post or the request URL is not important from the point of view of the controller.</li>
<li>We use the redirect method to send a redirection instruction back to the user's browser</li>
<li>We find the target URL we want to redirect to by retreiving the appropriate short link using a static method defined on the ShortLink (findByShortLink()). We didn't have to create this method in our domain class - it's behaviour is dynamically generated when it is called.</li>
</ul>
<div>
Despite the number of things we could note, the entire method is implemented in one line of code, and the basic behaviour of our redirection is now defined.</div>
<h2>
Testing the Redirection Manually</h2>
<div>
If your development server is still running, return to the home page (http://localhost:8080/slink if you have followed along exactly) and see if the new RedirectorController is listed. If not, restart the development server by typing <b>exit</b> and then <b>run-app</b> at the Grails command line.</div>
<div>
<br /></div>
<div>
Vist the administration pages again by browsing to http://localhost:8080/admin and create a short link to test. In this example, we define a <b>grails</b> short link pointing to target URL <b>http://www.google.com.au/search?q=grails</b> (a google search for the term 'grails'):</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcWcxdshyphenhyphen-TaSs-anG6PhhRL2pSuHr8deSekm2BCZtmtdxcnCENPg77e12WvsAoazBYmZ0WuUD9mdq3of7afirYFbvV5b54mtYJfLmjVOEA8tSgbz5gv0M09zE0zll3Z7mcurmFnlPUgs/s1600/grails+slink+shortlink+definition.tiff" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="147" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcWcxdshyphenhyphen-TaSs-anG6PhhRL2pSuHr8deSekm2BCZtmtdxcnCENPg77e12WvsAoazBYmZ0WuUD9mdq3of7afirYFbvV5b54mtYJfLmjVOEA8tSgbz5gv0M09zE0zll3Z7mcurmFnlPUgs/s400/grails+slink+shortlink+definition.tiff" width="400" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Once created and saved, visit http://localhost:8080/slink/redirector?shortLinkName=grails. You should be redirected to the Google search result for 'grails'. There is your redirection!</div>
<div>
<br /></div>
<div>
But wait - We had to enter: </div>
<div>
http://localhost:8080/slink/redirector?shortLinkName=grails</div>
<div>
<br /></div>
<div>
...to be redirected to:</div>
<div>
http://www.google.com.au/search?q=grails</div>
<div>
<br /></div>
<div>
How is that a short URL? The next few sections will make it much shorter.</div>
<h2>
Shortening our Short URLs - Remapping URLs</h2>
<div>
The first thing to shorten about our short URLs is the way we are specifying the short link name. Currently, we are passing the short link name to the redirector controller through the <a href="http://en.wikipedia.org/wiki/Query_string">query string</a>. Grails' default parameter handling mechanism is automatically mapping the ShortLinkName parameter in our URL to the shortLinkName parameter in the redirector controller. </div>
<div>
<br /></div>
<div>
<div>
To modify the way grails maps URLs in particular and requests in general to controllers is specified in a (appropriate named file called UrlMappings.groovy in the conf directory immediate under the root directory of the application. Open this file and you will see the default mapping:</div>
</div>
<div>
<br /></div>
<div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">class UrlMappings {</span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span"></span> static mappings = {</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span> "/$controller/$action?/$id?"{</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span> constraints {</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span> // apply constraints here</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span> }</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span> }</span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> "/"(view:"/index")</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span> "500"(view:'/error')</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span"></span> }</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">}</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div class="p1">
The default UrlMappings.groovy file contains three URL mappings: a mapping to automatically select a controller and action from the requested URL and pass an id value, a view handler for a server error (status code 500) and the home page. Both of the later render views only, so no controller is called.</div>
<div class="p1">
<br /></div>
<div class="p1">
</div>
<div>
Instead of this URL with a query string:</div>
<div>
http://localhost:8080/slink/redirector?shortLinkName=grails</div>
<div>
<br /></div>
<div>
We really want to use a URL like this to pass in the ShortLinkName:</div>
<div>
http://localhost:8080/slink/grails</div>
<div>
<br /></div>
<div class="p1">
From an implementation point of view what we are really saying is that the application should call the RedirectorController by default and pass in the second path element of the URL as the shortLinkName.</div>
</div>
<div>
<br /></div>
<div>
The one caveat to our plan is that we still need to access our administrations pages, so</div>
<div>
http://localhost:8080/admin should not follow a short link called 'admin' but display the default page of our administration pages. ie. it should call the AdminController, not the RedirectorController.</div>
<div>
<br /></div>
<div>
Modify and save the UrlMappings.groovy file so that it looks like this:</div>
<div>
<br /></div>
<div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="s1">class</span> UrlMappings {</span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span"></span><span class="s1"> static</span> mappings = {</span></div>
<div class="p3">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><b> "/admin/$action?/$id?"<span class="s2"> (controller:</span>"admin"<span class="s2">)</span></b></span></div>
<div class="p3">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><b><span class="s2"><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span></span> "/$shortLinkName"<span class="s2"> (controller:</span>"redirector"<span class="s2">)</span></b></span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div class="p2">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span"> </span><span class="Apple-tab-span"> </span></span></div>
<div class="p3">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="s2"><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span></span> "/"<span class="s2">(view:</span>"/index"<span class="s2">)</span></span></div>
<div class="p3">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="s2"><span class="Apple-tab-span"></span><span class="Apple-tab-span"></span></span> "500"<span class="s2">(view:</span>'/error'<span class="s2">)</span></span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span class="Apple-tab-span"></span> }</span></div>
<div class="p1">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">}</span></div>
</div>
<div>
<br /></div>
<div>
In the above file we are explicitly defining the admin controller mapping prior to defining the mapping that shortens our short URLs. The use of the $shortLinkName parameter in our short link mapping means that whatever follows the first slash below the application is treated in exactly the same way as original redirector URL with the short link name in the query string.</div>
<div>
<br /></div>
<div>
Try it out - you should now be able to browse to your short link at </div>
<div>
http://localhost:8080/slink/grails. You might need to restart the development server for the change to take effect. If you do, remember to recreate the short link you wish to test.</div>
<div>
<h2>
Shortening our Short URLs - Changing the Context Root</h2>
</div>
<div>
You might have noticed the name of our application is still taking up valuable keystrokes in the format of our short URLs. When Grails applications run they run as an application inside a <a href="http://java.sun.com/j2ee/overview.html">Java Enterprise Edition</a> (Java EE) container. These containers have the concept of a context root or document root which is the top level virtual 'folder' in which a single application lives. This allows multiple applications to co-exist on a single server.<br />
<br />
For our purposes we would like to use the root context so that any request reaching server at a URL below '/' reach our application. To do this we simply need to edit a Grails property. The config.groovy file in the conf subfolder of our application contains most of the standalone properties configuring a Grails application. Open this file (conf/config.groovy) now and add this line anywhere:<br />
<br /></div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><b>grails.app.context = "/"</b></span><br />
<br />
Exit the development server and run it again. Note the URL is different when you run the application:<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">grails> <b>run-app</b></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Server running. Browse to http://localhost:8080/</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Application loaded in interactive mode. Type 'exit' to shutdown.</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Enter a script name to run. Use TAB for completion:</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">grails></span><br />
<br />
Create your testing short link again (‘grails’ = ) again since the database is transient. The URL for our short link is now:<br />
<br />
http://localhost:8080/grails<br />
<br />
which compares to the original<br />
<br />
http://www.google.com.au/search?q=grails<br />
<br />
somewhat better.<br />
<h2>
Shortening our Short URLs - The rest</h2>
Sometime in the future, when we deploy our application to production it will most probably run on port 80, the default port for unsecured HTTP. We will then not need to include the port in our URLs. We'll also use a domain name, preferably a short one. Assuming we purchased the domain 'short.ly' (which in reality would never be available) our short URLs would take the form<br />
<br />
http://short.ly/grails<br />
<br />
which is probably the shortest you could choose to make it without limiting our short link name or finding a shorter domain name.<br />
<h2>
Running as Production</h2>
Grails provides an easy way to compile and execute our Grails application as if it was in production. Using the run-war command, Grails compiles and creates a WAR file and then launches it in the configured server environment, which is Tomcat by default.<br />
<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">grails> <b>run-war</b></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Done creating WAR target/slink-0.1.war</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Running Grails application</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">Tomcat Server running WAR (output written to: C:\Project\target\tomcat-</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">out.txt)</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Server running. Browse to http://localhost:8080/</span><br />
<br />
<h2>
Epilogue: Done and not Done</h2>
At this point our application is functional as per our original intentions. We can add, edit and delete our short links using the scaffolded admin screens, and the short links we define create short URLs which redirect the requests correctly. This is very far from a robust application however, which you might have noticed.<br />
<br />
One of the things that need to be fixed with this application includes the complete lack of running tests. If you type <b>test-app</b> at the Grails command line you will see we already have some failing tests we should implement. Additionally since we change the URL mappings we should probably put some tests around them. Writing these tests would do a good job of revealing other problems with the application. The good news is that Grails makes testing nearly everything very easy.<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span><br />
<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">grails> <b>test-app</b></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Running 3 unit tests... 1 of 3</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Failure: testSomething(slink.AdminControllerTests)</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| java.lang.AssertionError: Implement me</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> at org.junit.Assert.fail(Assert.java:93)</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> at</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">slink.AdminControllerTests.testSomething(AdminControllerTests.groovy:15)</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Running 3 unit tests... 2 of 3</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"></span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Failure: testSomething(slink.RedirectorControllerTests)</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| java.lang.AssertionError: Implement me</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> at org.junit.Assert.fail(Assert.java:93)</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> at</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">slink.RedirectorControllerTests.testSomething(RedirectorControllerTests.</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">groovy:15)</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Running 3 unit tests... 3 of 3</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Failure: testSomething(slink.ShortlinkTests)</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| java.lang.AssertionError: Implement me</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> at org.junit.Assert.fail(Assert.java:93)</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> at slink.ShortlinkTests.testSomething(ShortlinkTests.groovy:15)</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Completed 3 unit tests, 3 failed in 1015ms</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Packaging Grails application.....</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">| Tests FAILED - view reports in target/test-reports</span><br />
<br />
<br />
The application is hardly robust either. Nothing stops or prevents a user from using a Short URL that does not exist. For that matter nothing stops a user from creating a target URL that is not a real URL. Under these conditions our application will fail in a not too graceful way - Try it now.<br />
<br />
Security is also completely lacking. Anyone can create a short link or use a short URL, which is probably not a practical attribute in most usage situations.<br />
<br />
Fixing the above are all excellent points for a later blog post, but this tutorial ends here. If you have comments or corrections, please leave them below.<br />
<br />
In the meantime, enjoy Grails.Anonymoushttp://www.blogger.com/profile/15141304569652949781noreply@blogger.com4tag:blogger.com,1999:blog-9174832840890796616.post-78275532966697784492012-04-15T05:08:00.000-07:002012-04-15T05:08:00.900-07:00Using the Root Application Context ('/') in GrailsHi all,<br />
<br />
Its been a long time since I posted on this blog (since June of last year!) but as I was trying to remember how I did something only a week ago I was reminded of why posting to this blog is useful - for me at least!<br />
<br />
To get you up to speed, I have been investigating and enjoying <a href="http://grails.org/">Grails</a>, a 'rails-like' web application platform built on Groovy and Java. 'Rails-like' is best mentioned in quotes because a lot of Grails fans will tell you that the similarity is only skin-deep. I don't know <a href="http://rubyonrails.org/">Ruby on Rails</a> well enough to comment (oh but how many create-a-blog tutorials have I done?) but I am surprised by how deep Grails is.<br />
<br />
In any case, the nugget of information I would like to share today is how to get Grails 2.* to publish to root context. By convention Grails will publish to an application context the same as or derived from your application name. When running the local development server this would mean your application would be hosted at and below http://localhost:8080/myapp/.<br />
<br />
To publish to the root application context you can add the following line to your conf/Config.groovy file:<br />
<br />
<span style="color: blue; font-family: 'Courier New', Courier, monospace;"><b>grails.app.context = '/'</b></span><br />
<br />
Pretty simple. My understanding on J2EE application contexts pretty limited but the above setting can be overridden during the deployment anyway (<a href="http://www.heroku.com/">Heroku</a>, which provides hosting for Grails amongst other platforms, does this).Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-9174832840890796616.post-78662780891080945812011-06-23T05:37:00.000-07:002011-06-23T05:40:58.311-07:00Installing Pylint for Python 2.5 on MacIn a <a href="http://www.learningtechnicalstuff.com/2011/06/getting-started-with-google-app-engine.html">previous post</a> I discussed how to set up Google App Engine (Python) development environment on Mac OS X 10.6. I'm liberally mining some of <a href="http://www.learningtechnicalstuff.com/2010/10/installing-python-google-appengine-sdk.html#more">my own notes</a> on setting up Google App Engine on Ubuntu 10.10.<br />
<br />
In my previous Ubuntu environment I had a neat Ant script for building, testing and uploading my Google App Engine applications such as My Web Brain. One of tests the script performed was Python code style checks using <a href="http://www.logilab.org/857">Pylint</a>, which I have also mentioned before in the context of Ubuntu. I've set this up again on my Mac, so I thought I thought I would post my notes here.<br />
<br />
In this post I talk about:<br />
<br />
<ul><li>Installing Setup Tools for Python 2.5,</li>
<li>Installing PyLint using SetupTools, and</li>
<li>Configuring Aptana/Pydev to use PyLint</li>
</ul>Lets go!<br />
<a name='more'></a><br />
A couple of pre-requisites first: You need to have <a href="http://support.apple.com/kb/ht1528">enabled the root user</a> to be able to Sudo and I'm assuming you have already installed Python 2.5 (see my <a href="http://www.learningtechnicalstuff.com/2010/10/installing-python-google-appengine-sdk.html#more">previous post</a> for more information on that)<br />
<br />
<b>Installing SetupTools</b><br />
<br />
I still prefer to install Pylint via <a href="http://pypi.python.org/pypi/setuptools">SetupTools</a>. SetupTools makes the <code>easy_install</code> command available from the shell to automatically install python eggs and sort out their dependencies. You might already have SetupTools on your system, but do you have the Python 2.5 version? I assume it is important (it does after all need to install packages into the correct site-packages folder). To install SetupTools, first download the egg file:<br />
<br />
<a href="http://pypi.python.org/packages/2.5/s/setuptools/setuptools-0.6c11-py2.5.egg">http://pypi.python.org/packages/2.5/s/setuptools/setuptools-0.6c11-py2.5.egg</a><br />
<br />
Open a terminal session and cd into the folder you saved it into. Type the following into the commandline:<br />
<br />
<code>$ sudo sh setuptools-0.6c11-py2.5.egg</code><br />
<br />
This will install setup tools. When you run easy_install, make sure to use the command easy_install-2.5 to make sure you are addressing the correct Python installation on your system.<br />
<br />
<b>Installing PyLint </b><br />
<br />
Type the following into your terminal shell:<br />
<br />
<code>$ sudo easy_install-2.5 pylint</code><br />
<br />
This will install PyLint and all of its dependencies. You can now run PyLint from the command line (or from an Ant Task).<br />
<br />
<b>Using PyLint in Aptana</b><br />
<br />
Aptana (now incorporating PyDev - again see my previous post) can integrate with PyLint to give you feedback on code style as you work and make changes to your source files. To configure Aptana to do this, open Preferences -> Pydev -> PyLint, check the the <i>Use PyLint</i> option and locate your Pylint executable. Despite the hint to look for a file named <code>lint.py</code>, I've never found such a file.<br />
<br />
Instead, find the pylint binary. If you installed PyLint as per the above the following path should be where it is at:<br />
<br />
<code>/Library/Frameworks/Python.framework/Versions/2.5/bin/pylint</code><br />
<br />
Click OK, open a python file and make some changes. Warnings and errors from PyLint should start appearing in the Problems view (Window -> Show View -> Problems if you can't see it). You can also specify a preferences file in the preferences page for PyLint to pass in any global settings (to ignore certain style rules, for example).<br />
<br />
There you go. PyLint is installed and ready to use from the command line, an Ant Task or in Aptana. Let me know in the comments if you can suggest a better approach, have a question or any sort of general comment.Unknownnoreply@blogger.com5tag:blogger.com,1999:blog-9174832840890796616.post-26320215742738050552011-06-19T05:54:00.000-07:002011-06-19T05:54:42.252-07:00Getting Started with Google App Engine, Python 2.5 and PyDev on OS X 10.6Last week my shiny new Apple iMac 27 inch arrived and I thought I would share my steps in getting my <a href="http://code.google.com/appengine/">Google App Engine</a> (Python) environment set up. I have previously written about setting up Ubuntu 10.10 for the same purpose and that post remains one of the most popular on this blog.<br />
<br />
To set up our Google App Engine environment we will need the correct version of Python, the Google App Engine SDK and a Python/GAE friendly IDE.<br />
<br />
<a name='more'></a><br />
<b>Installing Python 2.5</b><br />
<br />
Firstly comes Python itself. Despite rumours of eventually upgrading the Python version supported on Google App Engine to 2.7, Google App Engine for Python still only supports Python 2.5. Mac OS X 10.6 ships with a distribution of Python 2.6. For hassle-free Google App Engine development it is always best to stick with the supported version.<br />
<br />
Finding a packaged distribution of Python 2.5 for Mac is more difficult than it was the last time I looked, but you can still find a package <a href="http://pythonmac.org/packages/py25-fat/index.html">here</a> at <a href="http://pythonmac.org/">pythonmac.org</a>. Download the package and install it by running the installer. If you open a command prompt and type <code>python --version</code> you should see Python 2.5 is now the default version.<br />
<br />
What happened to the existing bundled Python distribution? (or any others, if installed?) They are still present - the Python executable found by the shell is the one under /Library/Frameworks/Python.framework/Versions/Current, where <i>Current</i> is a symbolic link to a specific version's folder. Remember this if you ever need the shell to find a different version.<br />
<br />
<b>Getting the Google App Engine SDK</b><br />
<br />
The Google App Engine SDK is easy to find, but the <a href="http://code.google.com/appengine/downloads.html">Google App Engine SDK download page</a> is a touch misleading. In the download the links for the SDK, the link offered for Mac OS X is for the Google App Engine launcher. Contrary to my original assessment this download does in fact contain the SDK. When you finish downloading the package, open it and drag the launcher file to your applications folder. When you first launch it, the program will offer to create the necessary symbolic links in your <i>/usr/local/bin </i>folder.<br />
<br />
If you would like more control over how and where the SDK is installed, you can grab the <i>Linux/Other Platforms</i> archive instead.<br />
<br />
I never use the graphical launcher itself; I tend to start and upload my local App Engine programs via my IDE or an Ant build script (which is probably worth a post).<br />
<br />
<b>Setting up an IDE</b><br />
<br />
I've <a href="http://www.learningtechnicalstuff.com/search/label/PyDev">previously posted</a> about PyDev for Eclipse being my Python IDE of choice for Google App Engine and this has not changed. Fortunately getting it set up is now easier - PyDev is now a bundled component of <a href="http://www.aptana.com/">Aptana Studio 3</a>. Aptana Studio is built on the open source <a href="http://www.eclipse.org/">Eclipse IDE</a>, and can either be installed as a standalone application, with all the extensibility of Eclipse, or added as a plugin to an existing Eclipse installation. Download the standalone version or find the details of required update site for a plugin installation <a href="http://www.aptana.com/products/studio3/download">here</a>. The nice thing about Aptana for Google App Engine development is the inclusion of support for general web technologies and specific support for Django Templates.<br />
<br />
You can also optionally install the <a href="http://code.google.com/eclipse/">Google Plugin for Eclipse</a>. The vast bulk of this plugin is dedicated to assisting Google Web Toolkit development with Java, however, and out of the box Aptana seem to have included some or all of the limited Python/Google App Engine features in their studio, such as a way to launch the development server and a project wizard for setting up a Google App Engine project. ( To install the plugin, visit the <a href="http://code.google.com/eclipse/docs/getting_started.html">installation page</a>. Note that if you installed Aptana Studio as a standalone install you might need to satisfy some other Eclipse dependencies not included in the Aptana Eclipse distribution. I'm skipping the installation of the plugin at the moment.)<br />
<br />
Within Aptana (or Eclipse), open the Preferences and add the Python 2.5 interpreter (Aptana -> Preferences -> PyDev -> Interpreter - Python). Click <i>New</i> and enter a name (eg. 'Python 2.5') and the path to Python 2.5. This will be the specific 2.5 path under /Library/Frameworks/Python.framework/versions/2.5/bin. Aptana/Eclipse will successfully find a range of folders to add to the PythonPath for that interpreter.<br />
<br />
<b>Starting a New Google App Engine Project</b><br />
<br />
As mentioned, Aptana Studio now ships with a Google App Engine project wizard. This is helpful but not necessary - the most critical work to be done in making a Python project a Google App Engine project is to correctly add the SDK libraries to the Python Path recognised by the IDE. Doing this manually is described <a href="http://code.google.com/appengine/articles/eclipse.html">here</a>. To use the project wizard instead, select <i>File -> New -> PyDev -> Google App Engine project</i> to create a new project. Make sure to change the Grammar and the Python Interpreter both to Python version 2.5.<br />
<br />
You will be then be asked to locate the Google App Engine SDK files. If you installed the launcher application, the SDK files are actually within the installed .app file (folder?), which might make finding these files in Finder difficult. These easiest way to track down this path is through the terminal. Find where the dev_appserver.py symbolic link is (via which dev_appserver.py) and then inspect where it is pointing (ls -l usr/local/bin/dev_appserver.py). Grab this path from the terminal and paste it into the Aptana/Eclipse prompt.<br />
<br />
You will then be prompted to confirm the folders to add to the Python path, with your only decision about which version of Django templates you will be using.<br />
<br />
The new project wizard will close, and your new Google App Engine project will be ready.Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-9174832840890796616.post-62096938992992680012011-06-06T07:01:00.000-07:002011-06-06T07:01:25.818-07:00A Better Prisoner's Dilemma Simulation?In my <a href="http://www.learningtechnicalstuff.com/2011/05/my-generations-project-and-prisoners.html">previous post</a> I had started work on a python program named generations to try to replicate the simulations of <a href="http://www.learningtechnicalstuff.com/2011/05/my-generations-project-and-prisoners.html">Robert Axelrod</a> in comparing differing Prisoner's Dilemma strategies. At the time I was simulating single organisms ('Critters') with different strategies accumulating food over a number of iterations with the critter with highest food at the end of the iterations judged the winner.<br />
<br />
The result of this simple simulation was that two strategies - <i>Grudger</i> and <i>Tit-for-tat</i> - were continually vying for the top spot, with Grudger taking the mantle more often than not. In Axelrod's tournament Tit-for-Tat was the unambiguous winner, so I knew my generations script needed some work.<br />
<br />
(Read my <a href="http://www.learningtechnicalstuff.com/2011/05/my-generations-project-and-prisoners.html">previous post</a> for an introduction to Prisoner's Dilemma, why it interests me and what the various strategies were.)<br />
<br />
I've been developing the simulation since. Technically it is a bit of a mess, but when I next refactor I will be focusing on new parts of the model aside from PD and so I wanted to deliver this conclusion to Prisoner's Dilemma now.<br />
<br />
In this post I want to talk about how I changed the simulation and what effect these changes had. For the impatient - yes I have managed to tweak the simulation such that Tit-for-tat is the unambigously best strategy. Many critters had to die to make it so...<br />
<img src="https://spreadsheets0.google.com/a/he3.com.au/spreadsheet/oimg?key=0Ai9fn3aXjsWRdHZjbm5ZZ2lGN21aRWhqall5U2lXcWc&oid=1&zx=bbutf0f0uxtn" /><br />
<br />
<a name='more'></a><b> Go forth and multiply</b><br />
<br />
In beginning my simulation only ran the same 5 organisms against each other, with each accumulating food indefinitely but at different rates as their strategies proved more or less successful. I specifically wanted to uncover how differing frequencies of strategies influenced the success of themselves or others, so I had to break free of this fixed model.<br />
<br />
To this end I introduced reproduction into the simulation, and turned the simulation into one focused on measuring accumulated food to measuring reproductive success. My process for controlling reproduction was simple: When a critter accumulated enough food to pay an arbitrary cost of reproduction, another critter of the same strategy was created, and the cost deducted from the parent.<br />
<br />
This change meant that any critter would eventually reproduce - and reproduce multiple times - if it was even marginally successful. More successful strategies would accumulate food faster and thus reproduce faster. Since the offspring could eventually reproduce, this change let to an exploding growth in the populations being tracked.<br />
<br />
At the end of the simulation I could now see the success of the strategies: A count of the number of individuals with each strategy and their combined amount of food (which would become an increasingly irrelevant metric).<br />
<br />
Adding reproduction and the resulting exploding population immediately pointed out the computational unfeasibility of running the simulation over a large number of iterations in its current form. Each additional critter had to interact with every other which form an exponentially growing computational task. Iteration after iteration, the simulation slowed down.<br />
<br />
The results at this stage were unsatisfactory. Over the iteration counts I was prepared to run the simulation for, huge variations were seen from execution to execution. In some executions the Grudgers became the most prolific. In others it was Tit-for-tat. The random, cheater and sucker strategies were competitive on some runs, but not in others.<br />
<br />
The source of this variance in outcome was the fortunes of the random strategy and those it interacted with. At this stage the random strategy produced the only non-deterministic part of the simulation. While growth was unrestricted the number of random interactions (interactions involving the Random strategy) was steadily increasing, even as the proportion of those interactions decreased as a part of the total number of interactions.<br />
<br />
<b>Everyone Eats... Everybody Dies</b><br />
<br />
To put the breaks on the explosive population growth I next added the concept of death to the simulation. A Critter would die if it ever had an amount of food lower than 0. In theory a Critter could be 'suckered' through a string of interactions into this position, but with the success of the more altruistic strategies, this wasn't very likely. To make success in interactions essential, I added an attritional element to the simulation - That Critters, regardless of their success in interactions - expend a fixed amount of food each iteration.<br />
<br />
These additions did not drastically change the outcomes of the simulation. Population growth was slowed, but it was not halted. Within a thousand iterations there were a thousand critters and every iteration more were added than were added the iteration prior. Reaching 1500 iterations took several minutes under these computation conditions.<br />
<br />
The success of the random and cheater strategies declined noticeably, however. In the case of the random strategy, statistically assured runs of bad luck thinned their numbers. The cheater strategy could no longer afford to wait between successful cheats, and against the resurgent grudger and tit-for-tat strategies, success for a cheater most often came when encountering the offspring of these two strategies that had never met this individual cheater before.<br />
<br />
<b>A new form of Random</b><br />
<br />
With the decline of the Random strategy in the population I wondered if a tweak to its strategy that made cooperation more likely than defection would prosper, or at least be reliably more successful than my initial equal probability implementation. In a simulated world dominated by altruists that held a grudge, defecting once ever two interactions was not performing well.<br />
<br />
I changed the random strategy to be more initially flexible and allow the relative weighting of likelihood for cooperation, whilst breeding this weighting true in successive generations. I then added an additional random strategy to the simulation's initial state that was 3 times more likely to cooperate than defect, This strategy was known as Random 3.<br />
<br />
To my surprise, the new cooperative random strategy faired no better in the simulation than the completely random strategy. I am still assessing why this might be the case. Grudgers would never forgive a defecting random, but a random strategy less likely to defect would be less likely to continually arouse the punitive defections from the tit-for-tat strategy, which should have been a noticeable advantage.<br />
<br />
<b>Limited Interactions</b><br />
<br />
Until this point every iteration provided an opportunity for every critter to interact with every other critter. Universal interaction presented some problems. Apart from contributing to the exponential complexity of the computation, the sheer predictability of each iteration's interactions- varying only from iteration to iteration based on the addition of offspring- meant that altruistic strategies, once entrenched, gained an inevitable advantage that shielded every altruistic critter from risk. For example, if altruistic critters (ie critters with Tit-for-tat or Grudger strategies) made up 75% of the overall population, 75% of all an individual altruistic critter's interactions were certain to end in cooperation, making the consequences of the remaining interactions immaterial to the critter's eventual reproductive success.<br />
<br />
Furthermore, as a simulation of non-zero sum social interactions, this universal interaction on every iteration was not realistic. No analagous organism has the capacity to continuously expand its capacity for interaction to all members of a population as the same population undergoes explosive growth.<br />
<br />
Because of these issues I implemented a change to the available interactions for each critter each iteration. 5 iterations are chosen at random from amongst the possible combinations. Over multiple iterations and across the entire population, a given strategy will interact with a representative amount of each strategy in the population, but on any given iteration an altruistic critter might interact with entirely non-altruistic strategies. The effect of this change was not noticeable apart from an improvement in speed of the simulation.<br />
<br />
<b>The Constrained Environment</b><br />
<br />
At this stage the population the Critter population within my simulation was unendingly growing, albeit at a slower rate, as countless Critters interacted and generated food out of... well nothing. In any real world ecosystem, however, the environment places a constraint on the population size that lives off of it. Apart from the need to achieve a minimum of success in the interaction stakes, my critters had an easy life of interacting and reproducing, and their success, especially for altruistic critters in an altruistically dominated world, did not come at the expense of any other critter.<br />
<br />
I wanted to place a population cap on my Critters. This population cap would ideally not sacrifice the successful Critters from current and future generations in order to be maintained. I wanted the population cap to exert a selection pressure on the population that was analagous to the selection pressures in the real world.<br />
<br />
To this end I decided not to directly enforce a population cap, but rather, enforce a hard limit to the amount of food available each iteration. With this limit in place, once interactions within an iteration had exhausted the environmental supply of food, no further interactions (and no additions or subtractions of food) were possible. I had no basis to prefer any particular strategy to always appear at the head of the line however, so I was careful to again randomise the interactions which were being considered.<br />
<br />
Implemented this constrained environment had a dramatic effect. Firstly, the endless growth was over. For a particular environmental food limit there would be a set population that never varied more than 10 or 20 Critters either side. Suddenly running simulations across much larger numbers of iterations was possible. The effect on the outcome was startling as well: In simulations of 10,000 iterations, cheater and random strategies died out completely early on. The sucker strategy performed well for a time before dwindling and dying out. As before, both guardedly altruistic strategies grudger and tit-for-tat performed well out of the gate, but over the time period the grudger strategy fell by the wayside and leaving tit-for-tat to take the field - <i>just like in the 1980's Axelrod Tournament I was trying to replicate.</i><br />
<br />
<b>Enabling Comebacks</b><br />
<br />
That might have been the end of the story, but I wanted to ensure strategies which were extinct early in the simulation didn't fair better in the late game. For example, would a cheater strategy have more success against a field dominated only by Tit-for-tat critters as opposed to the tit-for-tat/grudger strategy duo seen in the early game? Would a Cooperatively slanted Random strategy do better without the Cheater strategy? Could any strategy upset an entrench tit-for-tat population?<br />
<br />
Apart from answering these questions, the question of realism also begged the question. The history of evolution shows that once a trick is learnt, many organisms can retreat to old strategies and ways of life across evolutionary timespans when the environment changes.<br />
<br />
I could have simply monitored the environment for strategies that had completely died off and reinjected candidate critters from those strategies at some future time. This seemed overly artificial to me however, so I instead engineered a constant (and yet small - 1%) chance of mutation in any Critter's offspring. When this mutation happened, a Critter with any strategy could emerge. This ensured that no matter which strategy or strategies were in pre-eminence, a 'background noise' of alternative strategies were always waiting in the background to take advantage of a beneficial change in the environment. (An environment is beneficial or not is solely dependent - in this simulation at least - on which other strategies are present in the environment).<br />
<br />
There was no amazing change in outcome with this facility for mutation in place. The 'loser strategies' (the randoms, cheaters and later, suckers and grudgers) would invariable go extinct, reappear in small numbers, perhaps become extinct again before re-appearing.<br />
<br />
<b>Try it yourself</b><br />
<br />
If I have been vague on providing specific numbers in this description (such as the amount of food consumed per iteration, the exact payoffs for cheating, defection and cooperation, etc) it has been because I have been acutely aware of how arbitrary some of my costs and allowances have been. Gross changes these arbitrary numbers will change the economics of strategy success.<br />
<br />
The way these economic constants affect the simulations is interesting and worthy of experimentation.<br />
<br />
<i>Question: </i>If the payoff for cheating is doubled, how what effect does this have on the population?<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://spreadsheets.google.com/a/he3.com.au/spreadsheet/oimg?key=0Ai9fn3aXjsWRdG5hX2lVTjloZFJ6YTlSRVVxYzRfWHc&oid=1&zx=4pqo1g784fvm" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="197" src="https://spreadsheets.google.com/a/he3.com.au/spreadsheet/oimg?key=0Ai9fn3aXjsWRdG5hX2lVTjloZFJ6YTlSRVVxYzRfWHc&oid=1&zx=4pqo1g784fvm" width="320" /></a></div><br />
<i>Answer:</i> Cheaters lead early before the inevitable population crash. Grudgers rise highest out of the critter carnage.<br />
<br />
<i>Question: </i>Does an environment with a higher food-cap, supporting a higher population, have more room for alternative strategies on the fringes?<br />
<br />
<i>Answer:</i> Only slightly<br />
<br />
If you want to find out for yourself, download my <a href="https://github.com/bendavieshe3/generations">generations python script</a> (use <a href="https://github.com/bendavieshe3/generations/tree/v1.5-PD">tag v1.5-PD</a> for this version - as I mentioned in my previous blog generations will not track solely the Prisoner's Dilemma scenario).<br />
<br />
The script should be easy to use - run the script without arguments to use default values<br />
<br />
<ul><li>The -i or --iterations option lets you specify the number of iterations run</li>
<li>The -t or --track option lets you specify an arbitrary critter to track (the initial critter names are c1, s1, r1, r2, t1 and g1 after the strategies. Their offspring are c1_1, c1_2 and c1_1_1, for example, named after their lineage and their birth order from their parent). </li>
<li>The -r or --reporting options lets you specify the reporting interval</li>
<li>The -f or --filename option lets you specify a filepath to save a tab-separated datafile to for analysis in spreadsheet and charting programs.</li>
<li>Use -h or --help to get usage information.</li>
</ul><div>For example:</div><code><br />
Mimas:src bendavies$ ./generations.py -i 10000 -f cheatpayoff.tsv -r 50<br />
</code><br />
<br />
Runs the simulation for 10000 iterations, reports every 50 iterations and outputs the population data to cheatpayoff.tsv<br />
<br />
I wouldn't pay too much attention to the technical implementation, since the code is somewhat between plugin, event and direct manipulation architectures at the moment.<br />
<br />
<b>What is next?</b><br />
<br />
This exercise was interesting to me since it allowed me to observe emergent population trends based on individual strategies. More-over, I am keen to leave the confines of the prisoner's dilemma simulation and try simulation of other behavioural strategies under evolutionary processes. Some answers I wouldn't mind pursuing would be:<br />
<br />
<ul><li>Can I evolve cooperative strategies from scratch against a selfish population?</li>
<li>What factors influence parental investment?</li>
<li>How might embryological complexity weigh in reproduction strategies?</li>
<li>Can I define a critter genome that is flexible enough to 'mutate slightly', light enough to be computationally feasible and yet expressive enough to allow interesting emergent behaviours and qualities to emerge?</li>
<li>How would critters move, if given the choice, in an environment whose food resources did not reset every iteration, but rather depleted. How would fragmentation of population affect interaction strategies?</li>
<li>Would it be possible to evolve critters from a common base to two or more very different lifestyles?</li>
</ul><div>All of this will take time, and I need to take a break to do some work on <a href="http://www.mywebbrain.com/">My Web Brain</a> and <a href="http://code.google.com/p/he3-appengine-lib/">he3-appengine-lib</a>. Still, I'm tempted to simply dive right in....</div><div><br />
</div><div>If you have any comments on this above exercise please let me know. This has been an absurdly long blog post, but I wanted to share my experience and take the opportunity to examine how this experiment played out.</div><div><br />
</div>Unknownnoreply@blogger.com5tag:blogger.com,1999:blog-9174832840890796616.post-89257286382633880692011-05-23T02:46:00.000-07:002011-05-23T02:46:43.855-07:00My Generations Project and Prisoner's DilemmaApologies for the lack of recent posts. I have been 'learning technical stuff' mostly at work and mostly not in a form that can be easily shared. I have recently found the time to start a new project I call Generations - a python program I am developing to simulate some aspects of natural economy and natural selection.<br />
<br />
Recently I re-read Richard Dawkins' <a href="http://www.amazon.com/Selfish-Gene-Anniversary-Introduction/dp/0199291152?ie=UTF8&tag=leartechstuf-20&link_code=btl&camp=213689&creative=392969" target="_blank">The Selfish Gene</a><img alt="" border="0" height="1" src="http://www.assoc-amazon.com/e/ir?t=leartechstuf-20&l=btl&camp=213689&creative=392969&o=1&a=0199291152" style="border: none !important; margin: 0px !important; padding: 0px !important;" width="1" /> and Robert Wright's <a href="http://www.amazon.com/Moral-Animal-Science-Evolutionary-Psychology/dp/0679763996?ie=UTF8&tag=leartechstuf-20&link_code=btl&camp=213689&creative=392969" target="_blank">The Moral Animal</a><img alt="" border="0" height="1" src="http://www.assoc-amazon.com/e/ir?t=leartechstuf-20&l=btl&camp=213689&creative=392969&o=1&a=0679763996" style="border: none !important; margin: 0px !important; padding: 0px !important;" width="1" /> and was fascinated by the idea that computer simulations could tell us useful information about effective behavioral strategies, how those strategies prosper and in turn what effect these strategies may have on their own effectiveness and that of other strategies.<br />
<br />
Currently this initial version of my program only simulates Prisoner's Dilemma. Wikipedia <a href="http://en.wikipedia.org/wiki/Prisoner's_dilemma">describes</a> the Prisoner's Dilemma scenario, a classic game from the field of Game Theory, like this:<br />
<blockquote>Two suspects are arrested by the police. The police have insufficient evidence for a conviction, and, having separated the prisoners, visit each of them to offer the same deal. If one testifies for the prosecution against the other (defects) and the other remains silent (cooperates), the defector goes free and the silent accomplice receives the full one-year sentence. If both remain silent, both prisoners are sentenced to only one month in jail for a minor charge. If each betrays the other, each receives a three-month sentence. Each prisoner must choose to betray the other or to remain silent. Each one is assured that the other would not know about the betrayal before the end of the investigation. How should the prisoners act?</blockquote>Prisoner's Dilemma is an example of a non-zero-sum game, meaning that players are not attempting to beat other players, just achieve the best outcome for themselves. That is to say: winning doesn't automatically imply the other player or players have lost. When played repeatedly and scored (ie. 'Iterative Prisoner's Dilemma') the interesting question becomes which strategy, if any, is the most successful against the widest range of counter-strategies. Always cooperate? Always defect? Some mixture of the two?<br />
<br />
<a name='more'></a><br />
The relevance of this game to the field of Darwinism (which both Dawkins and Wright were asserting) is that this situation of deciding to trust (or abuse trust) is a good abstraction of the issues underlying <a href="http://en.wikipedia.org/wiki/Reciprocal_altruism">reciprocal altruism</a>, one of the motivators of altruistic (or 'nice') behaviour in the neo-Darwinist worldview. Both Dawkins and Wright discussed a competition held in the 1970s and again in the early 1980's where Robert Alexrod challenged interested parties to design strategies for the game and test them out against the strategies of other players.<br />
<br />
I am running my own tournament of sorts within Generations. Instead of the prisoner analogy however, my program simulates 'critters' adopting different strategies and receiving or losing 'food' as a result of the success or failure at the prisoner's dilemma game. I have currently implemented the following strategies:<br />
<br />
<ul><li>Sucker, who always cooperates blindly</li>
<li>Cheater, who always defects</li>
<li>Random, who randomly cooperates or defects</li>
<li>Grudger, who cooperates with anyone who has never defected against them, and</li>
<li>Tit-For-Tat, who cooperates initially but punishes defections in the previous round by another player with a defection in the current round. </li>
</ul><div>My ratio of scoring for defection and cooperation is arbitrary and by default the simulation runs over 1500 iterations. The most successful strategies so far are Grudger and Tit-For-Tat, With Grudger always just beating out Tit-for-Tat. </div><div><br />
</div><div>In Alexrod's tournament, Tit-for-Tat was judged the winner. One reason why my simulation might be playing out differently is that I have precisely one critter for each strategy, and whereas once bitten Grudger will never trust random again, Tit-for-Tat will 'trust' Random again after a random cooperation. </div><div><br />
</div><div>The specific economic rewards I have assigned might also be making a difference. </div><div><br />
</div><div><div>In the real-world, less successful 'critters' would reproduce in proportion with their success, and their hereditary strategies would be passed on their offspring. Critters with bad strategies would shrink as a proportion of the population, altering the dynamics of which strategy is more effective. Simulating this, as well as some other strategies I found on the Wikipedia page, is what I will do next.</div></div><div><br />
</div><div>In the meantime, you can get my <a href="https://github.com/bendavieshe3/generations">Generations program on Github</a>. Use the v*-PD tags to download the Prisoner's Dilemma only versions - I will be adding decidedly un-Prisoner's Dilemma elements (ie. other ways to simulate critters) in the near future. The current PD tag is <a href="https://github.com/bendavieshe3/generations/commits/v1.0-PD">v1.0-PD</a>.</div><div><br />
</div><div>Let me know if you have questions, or comments. </div><div><br />
</div>Unknownnoreply@blogger.com3