Paulo Poiati | Blog

How do I Configure Environment Variables in Ansible

It’s common to use environment variables to configure applications, especially to store sensible information like passwords and keys (if you are familiar to Heroku you know what I mean). Here I will show how I do it using Ansible and Supervisor.

The solution is simple, in the same directory of your playbook create another named private_vars (it can be named anything but I like this name because of the contrast with the Ansible group_vars convention). Don’t forget to put this directory in the ignore file of your CVS (you don’t want to share your passwords, right?).

Now create an yaml file inside private_vars with your configurations, e.g.

# production.yml

---
app_environment: |
  DJANGO_SETTINGS_MODULE="myapp.settings.production"
  DB_HOST=example.com
  DB_USER=frodo
  DB_PASSWORD=precious

I like to put the name of my environment in the file, e.g., production, staging

Now lets configure Supervisor, bellow is an simple example of the Ansible template file.

# example.j2.conf

[program:example]
user=nobody
command=start.sh
directory=/usr/local/src/example
environment={{ app_environment | mandatory | replace('\n', ',') }}

The important here is the environment parameter. We are using the app_environment from production.yml. We are also applying two filters to it.

  • mandatory to fail fast and verbose if for some reason the variable isn’t defined
  • replace to format the parameter to an acceptable syntax for Supervisor (comma separated)

That’s it, you are ready to go, just run your playbook passing the environment file as parameter, e.g.

$ ansible-playbook -l production -e @private_vars/production.yml site.yml

This is the way I handle environment variables in Ansible but there is other solutions for sure.

Copying content from vim to Mac OS clipboard

As a heavy user of vim and Mac OSX I very often need to copy something from vim to the OS clipboard. This can be easily accomplished with the mouse, but I hate to touch it.

You can copy within the terminal using the pbcopy builtin command. That said we can write the following function:

function! CopyToOSClipboard() range
  exec(":silent !cat %:p | sed -n " . a:firstline . "," . a:lastline . "p | pbcopy")
  :redraw!
endfunction

A brief explanation of what is going on:

  • silent is used to not show the process output into the screen
  • I’m using sed to select between the lines of the range
  • and finally I’m feeding pbcopy with the sed output

Now lets map it to <Leader><Leader>c in normal and visual mode:

nnoremap <Leader><Leader>c :call CopyToOSClipboard()<CR>
vnoremap <Leader><Leader>c :call CopyToOSClipboard()<CR>

Now if you hit <Leader><Leader>c the current cursor line will be copied to the clipboard. Of course you can also go into visual mode, select some lines and press <Leader><Leader>c to copy more than one line.

IMPORTANT Because this function works in the file of the current vim buffer, not in the buffer memory the file needs to be saved.

Django Outbox Released

I enjoy the development experience of the Django framework. But there is something I miss, a better way to evaluate and debug emails while coding.

What I am used to do is enable file based email backend, and see the emails directly on my file system. This is nice, but, if I had a web interface this should be even better. That is the idea behind django-outbox.

You can also preview html emails.

The configuration is simple, just follow the instructions in the README.

Running Cron In Elastic Beanstalk Auto-Scaling Environment

Who already worked with Elastic Beanstalk knows the lack of documentation of the platform. If you need to deploy a simple application it’s straight forward, but if you need to do more complex stuff, it can be a pain in the ass.

The problem with Cron and Elastic Beanstalk begins when we are using Auto Scaling. Generally we need only one of our machines in the cluster to run the jobs, not all of them. We can use the leader_only option to ensure the job will just run in the leader of the cluster, but it’s not enough, since the leader can change over time, for example, during deploys. To ensure all the machines crontab is wiped in every deploy we need to add another container_command (before the command to add the crontab).

Add this to your configuration file.

container_commands:
  01_remove_old_cron_jobs:
    command: "crontab -r || exit 0"
  02_cronjobs:
    command: "cat .ebextensions/crontab | crontab"
    leader_only: true

The || exit 0 is mandatory because if there is no crontab in the machine the crontab -r command will return a status code > 0 (an error). Elastic Beanstalk stop the deploy process if one of the container_commands fail.

Flask flash messages testing

Testing with Flask is generally straightforward but some things aren’t trivial. The Flask-Testing extension helps us with some really useful assertions like TestCase#assert_context and TestCase#assert_template_used but it miss a way to test flash messages.

One of the ways to test flashes is asserting if the message is in the response data.

Suppose the production code.

@app.route('/post/')
def new_post(self):
  if storage.create_post(request.form['post']):
    flash(u'Post added')
    return redirect(url_for('home'))
  return render_template('new-post.html')

And the test code.

def should_flash_a_success_message(self):
  response = self.client.post('/post/', data=self.valid_post_data,
                              follow_redirects=True)

  assert 'Post added' in response.data

This works but personally I don’t like it. One reason is we need to follow the redirect and this can lead to testing the same thing twice because we should have a test for the home route already.

The other reason is related to isolation. If we want to test the view without rendering the template we can’t because we are making assertions in the generated document.

Curiosity: Rails by default doesn’t render any view in controller specs. In Flask-Testing it renders but you can turn off template rendering.

Another way to test flash messages is using a mock. You replace the flash method with a mock and use expectations to assert flash calls. This works but I like to avoid mocks when possible.

My solution consist in defining a new method to do the job. I recommend you to define it in a base test class so you can reuse it.

from flask.ext.testing import TestCase

import myapp


class BaseTest(TestCase):
                                                                                
    def create_app(self):
        return myapp.create_app(TESTING=True)
                                                                                                 
    def assert_flashes(self, expected_message, expected_category='message'):
        with self.client.session_transaction() as session:
            try:
                category, message = session['_flashes'][0]
            except KeyError:
                raise AssertionError('nothing flashed')
            assert expected_message in message
            assert expected_category == category

And now my test looks like this.

def should_flash_a_success_message(self):
  self.client.post('/post/', data=self.valid_post_data)

  self.assert_flashes('Post added')

Don’t forget to subclass BaseTest in your test classes. Another trick thing about flashes is that they need the session to work and sessions doesn’t work without the SECRET_KEY set in Flask so be sure you set it before running the tests.

Installing RMagick in Mac OS X Mountain Lion / Maverick with Homebrew

Installing RMagick with homebrew should be trivial, but it’s not. For some reason the last version of RMagick (2.13.1) does not compile with the last version of ImageMagick (6.8.2-0).

If you install the last version of ImageMagick with homebrew it will work without problems but the RMagick extension will fail during the build with the following error:

checking for ImageMagick version >= 6.4.9... yes
checking for HDRI disabled version of ImageMagick... yes
checking for stdint.h... yes
checking for sys/types.h... yes
checking for wand/MagickWand.h... yes
checking for InitializeMagick() in -lMagickCore... no
checking for InitializeMagick() in -lMagick... no
checking for InitializeMagick() in -lMagick++... no
Can't install RMagick 2.13.1. Can't find the ImageMagick library or one
of the dependent libraries. Check the mkmf.log file for more detailed
information.

I’m not sure but I think there are some compatibility problems with the new versions of ImageMagick and RMagick. One version I know works well is 6.6.7-0 let’s install it using homebrew.

If you already have ImageMagick installed uninstall it before continue.

$ brew uninstall imagemagick

Now let’s edit the brew formula.

$ brew edit imagemagick

You should set the url to ftp://ftp.sunet.se/pub/multimedia/graphics/ImageMagick/ImageMagick-6.6.7-0.tar.gz and comment the sha256 line.

class Imagemagick < Formula
  homepage 'http://www.imagemagick.org'

  # upstream's stable tarballs tend to disappear, so we provide our own mirror
  # Tarball from: http://www.imagemagick.org/download/ImageMagick.tar.gz
  # SHA-256 from: http://www.imagemagick.org/download/digest.rdf
 
  # Remove this url
  # url 'http://downloads.sf.net/project/machomebrew/mirror/ImageMagick-6.8.0-10.tar.gz'
 
  # Add this new url
  url 'ftp://ftp.sunet.se/pub/multimedia/graphics/ImageMagick/ImageMagick-6.6.7-0.tar.gz'

  # Comment this line
  # sha256 'b3dfcb44300f73e73ffa8deef8bba4cf43f03d7150bf1fd0febedceac1a45c7e'

  head 'https://www.imagemagick.org/subversion/ImageMagick/trunk',
    :using => UnsafeSubversionDownloadStrategy

  .
  .
  .
end

After saving the file you can install ImageMagick. You should also disable openmp and build it from source.

$ brew install imagemagick --disable-openmp --build-from-source

Now the RMagick installation should work like a charm!

$ gem install rmagick

Browsing between most recent buffers in VIM

Vim has the concept of buffer, a buffer can be just an open file. For example, to list all the open buffers type :ls.

The intention here is not to explain buffers, there is a lot of good sources for that (ex: http://vim.wikia.com/wiki/Vim_buffer_FAQ).

One of the Vim commands I use a lot is the :b# to switch back to the last used buffer (the one you were before the actual open). This can be very useful, for example, if you are working with the application code in one buffer and the correspondent unit test in the other one (another great way to work with two related files is using the :split and :vsplit commands).

But typing :b# and pressing the enter every time can be really annoying. Here is a simple key map to help with this:

function SwitchBuffer()
  b#
endfunction

nmap <Tab> :call SwitchBuffer()<CR>

Put the code above in your .vimrc file. Now every time you press Tab in normal mode the buffer will switch.

A not well known and often over looked css property: box-sizing

The box-sizing (introduced in CSS3) is one of the forgotten properties, no one talks about it but can be really useful in some situations.

What it does? In the Mozilla words:

“The box-sizing CSS property is used to alter the default CSS box model used to calculate widths and heights of elements. It is possible to use this property to emulate the behavior of browsers that do not correctly support the CSS box model specification.”

There are two possible values for this property:

  • content-box (default)
  • boder-box

The content-box is the default value, when it is set, the padding and border properties are put outside the bounds of your element, for example:

  div.box { width: 200px; height: 200px; border: 15px solid black; padding: 10px; }



250px



The above box total width and height will be:

200 + (2 * 15) + (2 * 10) = 250px

Now, if we change to border-box:

div.box { 
  box-sizing: border-box; 
  width: 200px; height: 200px; border: 15px solid black; padding: 10px; 
}



200px



The box size stay unchanged. By the way, this behavior in the box model is analogous to Internet Explorer when the document is in Quirks mode.

jQuery Builder: Introduction

Which web developer never built DOM elements programmatically? It’s a mess, doesn’t is?

Well, it was a lot worse in the past. When the only way to do that was appending strings or with the standard Document Api (Document#createElement, Document#appendChild …). But In the past few years the things got better. Javascript Frameworks emerged and one of the them was the well know jQuery.

jQuery has a smarter API to build DOM elements. The main advantage of using jQuery is the method chaining. But is out there a better approach ? I was seeking for one and I found just a few projects, one of them was jquery.builder from Jeremy Ruppel, a new but promising project. One week later I was helping her to evolve it.

Usage

To start building, use the build method. You can give this build method a block.

$( '#context' ).build( function( )
{
  this.div( 'hello!' );
} );

$( '#context' ).html( ); // =  <div>hello!</div>

In this block and any child blocks, this refers to the builder instance. The same builder instance will also be passed to the block if you want to name the reference.

$( '#context' ).build( function( b )
{
  b.div( 'hello!' );
} );

The builder object has a method for every common html tag, but you can add your own tag methods easily (more on that later).

For building node hierarchies, you can give any tag method a block and the builder will adjust its scope appropriately:

$( '#context' ).build( function( )
{
  this.div( function( )
  {
    this.div( 'nested' );
  } );

  this.span( function( )
  {
    this.a( 'hierarchy' );
  } );
} );

$( '#context' ).html( ); // => <div><div>nested</div></div><span><a>hierarchy</a></span>

Scope can be nested as deeply as you want. Go crazy.

You can pass a hash of options to any tag method and those key-value pairs will be added as attributes to the created node.

$( '#context' ).build( function( )
{
  this.a( { href : 'github.com' } );
} );

$( '#context' ).html( ); // => <a href="github.com"></a>

The options hash may also be passed after the node text, like:

$( '#context' ).build( function( )
{
  this.a( 'github rules', { href : 'github.com' } );
} );

$( '#context' ).html( ); // => <a href="github.com">github rules</a>

If you need the reference to the current scope DOM element you can use the $ variable. For Example, to add a mouse click event to an element:

$( '#context' ).build( function( )
{
  this.span(function ( )
  {
    this.text( 'Click Me' );
    this.$.click(function( )
    {
      alert( 'Hello There!' );
    } );
  } );
} );

Custom Tags

If you’re building XML, you’re going to need some custom tags. jquery.builder can be set up to build any tag that isn’t a reserved word. Just pass your tag name to the build method and it will be available on any new builders.

$( '#context' ).build( 'custom' );

$( '#context' ).build( function( )
{
  this.custom( 'sweet' );
} );

$( '#context' ).html( ); // => <custom>sweet</custom>

If at any point you need to reset the tag list to the defaults, just pass false to the build method.

Right now, custom tags are shared between all builder instances regardless of their context node.

Expressions Syntax

Expressions is the easiest way to create nested elements. Using it you don’t need to specify a function to every nested object. You can also mix expressions style with the standard builder style.

$( '#context' ).build( function( )
{
  this( 'body div ul', function ( )
  {
    this( 'li', function ( )
    {
      this.a( function ( ) { this.text( 'Hello World' ); }, { class: 'text' } );
    } );
  } );
} );

$( '#context' ).html( ); // <body><div><ul><li><a>Hello World</a></li></ul></div></body>

If the tag name is omitted but a class or id is present it will infer a div element, for example:

$( '#context' ).build( function( )
{
  this( '.foo', 'Hello, Foo!!!' );
} );

$( '#context' ).html( ); // <div>Hello, Foo!!!</div>

The source code and documentation is available: on the Github page. Any question or suggestion are welcome.

Installing VimRepress in MacVim (OSX Lion)

Installing VimRepress should be trivial for almost every case but one exception is installing it in MacOSX Lion. If you installed MacVim compiling the source without specifying the architecture it will use the x86_64 (default for Lion) even if you are using homebrew.

The problem is, the python interpreter will not work correctly if you are using the 64 bits version, you need to recompile for the i386 architecture.

If you are not using any package manager you just need to pass the --with-macarchs=i386 to the configure script.

In the case of homebrew you need to change the formula with the command:

$ brew edit macvim

With the formula open search for --with-macarchs and set it to i386 (you will need a little Ruby knowledge).

Uninstall macvim:

$ brew uninstall macvim

And install it again:

It’s important to use the system ruby version when using homebrew (the one that ships with MacOS). If you are using rvm set the current ruby to the system: rvm use system.

$ brew install macvim

If the install was successfully we are ready to install and configure VimRepress.

Easyhash: An easy interface to generate md5 and sha1 hash in hexadecimal format

Generate hash in hexadecimal format is a common need for most developers. Generally this is an easy task, but like a lot of stuff it’s complicated to do in Java. You need to use the java.security.MessageDigest API and convert the result from bytes to a hexadecimal string.

Unfortunately, even in Groovy there is no easy path. With that in mind I developed a small library to do the work.

Using Java

First, Put the easyhash jar into the classpath and then:

import static com.lazythought.easyhash.HashGenerator.*;

assert "ab07acbb1e496801937adfa772424bf7".equals(md5("foo bar baz"));
assert "c7567e8b39e2428e38bf9c9226ac68de4c67dc39".equals(sha1("foo bar baz"));

Using Groovy

With Groovy you can use the @Grab AST:

// Grab the jar
@Grab("com.lazythought:easyhash:1.0")

import static com.lazythought.easyhash.HashGenerator.*

assert 'ab07acbb1e496801937adfa772424bf7' == md5('foo bar baz')
assert 'c7567e8b39e2428e38bf9c9226ac68de4c67dc39' == sha1('foo bar baz')

There is also the HashCategory option:

// Grab the jar
@Grab('com.lazythought:easyhash:1.0')

import com.lazythought.easyhash.HashCategory

use(HashCategory) {
    assert 'b071ed8a2de56ecd5958305641a81755' == 'frodo bags'.md5()
    assert 'b6b5ece040fd0c467cb189a284c6e7c752c747f5' == 'frodo bags'.sha1()
}

Dive in

It’s Available at Maven Central.

<dependency>
    <groupId>com.lazythought</groupId>
    <artifactId>easyhash</artifactId>
    <version>1.0</version>
</dependency>

Source code https://github.com/poiati/easyhash

Grails / GORM: Changing default id name and type from an entity

While developing a simple application at work I got stuck with a common case in GORM, and I didn’t found the solution in the documentation.

I have a table with a column named myid of type varchar. But GORM by default auto generate an id property with the long type. The solution is straight forward, just call the method id in the mapping closure, with the following param(s):

class Foo {

    String myid

    static constraints = {}
    
    static mapping = {
        id generator: 'assigned', name: 'myid'
    }
}

The generator is the strategy to auto-generate the id, you can use a sequence or something like, since it’s a string the value will be assigned, not generated. The name is the current property to bind the value (myid in this case).

Groovy / GMongo tips and tricks

Based on some emails I received last days I will show some features of GMongo that not everyone is aware.

In the mongo official Java driver you can do searches using Regular Expression. To do that you just need to pass a java.util.regex.Pattern instance as the search term. In Groovy there is a shortcut to create a Pattern: ~/regex/.

For example:

def pattern = ~/mypattern/
assert pattern.class.is(java.util.regex.Pattern)

Here is a small script demonstrating the usage of regex search:

// Grab the jar
@Grab('com.gmongo:gmongo:1.0')

import com.gmongo.GMongo

def gmongo = new GMongo('localhost:27017')
def db = gmongo.getDB('tips')

db.so.drop()
db.so << [name: 'Windows XP']
db.so << [name: 'Windows 7']
db.so << [name: 'Windows Vista']
db.so << [name: 'Mac OS X v10.3 "Panther"']
db.so << [name: 'Mac OS X v10.4 "Tiger"']
db.so << [name: 'Mac OS X v10.5 "Leopard"']
db.so << [name: 'Mac OS X v10.6 "Snow Leopard"']
db.so << [name: 'Mac OS X v10.7 "Lion"']

// Mac OS Only
println "\nMac Os Only\n"
db.so.find([name: ~/^Mac/]).each { so ->
    println so
}

// Print: 

// Mac OS Leopard, Snow Leopard
println "\nMac OS Leopard, Snow Leopard\n"
db.so.find([name: ~/Leopard/]).each { so ->
    println so
}

Persisting your POGO

There is an easy way to persist your POGO using GMongo. Suppose we have the class:

class Person {
   def name
   def age
}

In Groovy we can get all properties from a class using the properties property, for example:

def person = new Person(name: 'Paulo', age: 25)
println person.properties

This code outputs something like:

[
  class:class Person, 
  age:25, 
  metaClass:org.codehaus.groovy.runtime.HandleMetaClass@450a1001, 
  name:Paulo
]

As you can see, not every property means something to us. We doesn’t want to store class and metaClass in our storage, because it isn’t part of the domain. So, we need to ignore them:

println person.properties.findAll { !['class', 'metaClass'].contains(it.key) }

Now, all we need to do is persist this Map in MongoDB. Here is a complete example:

// Grab the jar
@Grab('com.gmongo:gmongo:1.0')
import com.gmongo.GMongo

class Person {
   def name
   def age
}

def gmongo = new GMongo('localhost:27017')
def db = gmongo.getDB('example')

def person = new Person(name: 'Paulo', age: 25)

db.persons.drop()
db.persons << person.properties.findAll { !['class', 'metaClass'].contains(it.key) }

def personFromMongo = db.persons.findOne()

assert 'Paulo' == personFromMongo.name
assert 25      == personFromMongo.age

BasicDBObject to POGO conversion

The class com.mongodb.BasicDBObjects extends java.util.LinkedHashMap so it’s easy to convert it to POGO, thankfully to Groovy array notation constructor call. Don’t worry, I will explain. Suppose we have the class:

class Person {
   def name
   def age
}

The two statements bellow are equivalent:

Person mike = new Person(name: 'Mike', age: 23)
Person john = [name: 'John', age: 36]

To this work you need to use typed variable. If you use untyped variable definition Groovy can’t infer what constructor to call.

So, taking advantage of this cool Groovy feature you can do things like this:

// Grab the jar
@Grab('com.gmongo:gmongo:1.0')
import com.gmongo.GMongo

class Person {
   def name
   def age
   
   def whoIAm() {
       "Hello, I'm $name and I am $age years old."
   }
}

def gmongo = new GMongo('localhost:27017')
def db = gmongo.getDB('example')

def person = new Person(name: 'Paulo', age: 25)

db.persons.drop()
db.persons << person.properties.findAll { !['class', 'metaClass'].contains(it.key) }

Person personFromMongo = db.persons.findOne().findAll { it.key != '_id' }

assert "Hello, I'm Paulo and I am 25 years old." == personFromMongo.whoIAm()

As you can see, we need to remove the _id property from the Map before instantiate the class Person, that is because Person hasn’t this property. Another alternative is add the _id property to the Person class.

Any feedback is appreciated.

GMongo available at Maven Central

A maintenance release (0.5.1) of GMongo was launched. It just fixed a bug with com.mongodb.DB#createCollection.

But the good news is the GMongo availability in the Maven Central (http://repo2.maven.org/maven2/).

Maven

<dependency>
      <groupId>com.gmongo</groupId>
      <artifactId>gmongo</artifactId>
      <version>0.5.1</version>
</dependency>

Ivy

<dependency org="com.gmongo" name="gmongo" rev="0.5.1"/>

Groovy Grape

// Grab the jar
@Grab(group='com.gmongo', module='gmongo', version='0.5.1')

This should compile and run seamlessly in an environment with Groovy 1.7.2 (or later):

// Grab the jar
@Grab(group='com.gmongo', module='gmongo', version='0.5.1')

import com.gmongo.GMongo

def mongo = new GMongo("127.0.0.1", 27017)
def db = mongo.getDB('myDb')

db.greetings.insert(hello: 'world')

GMongo 0.5 Released

UPDATE GMongo is in constantly development, for more details check https://github.com/poiati/gmongo.

GMongo is an alternative to de default Java driver for Mongodb. It’s use an easy and less verbose syntax, the grammar is very close to the official mongo shell cliente (javascript).

It’s just a wrapper around the Java driver. So, every single method of the the official driver is available here too.

The main class is the com.gmongo.GMongo. It has the same API of the com.mongodb.Mongo but it’s not a subclass. Instead, the methods calls are delegated. Despite GMongo, all other classes are the same from the Java driver.

To be more practical, here are some examples:

// To download GMongo on the fly and put it at classpath
@Grab(group='com.gmongo', module='gmongo', version='1.0')
import com.gmongo.GMongo
// Instantiate a com.gmongo.GMongo object instead of com.mongodb.Mongo
// The same constructors and methods are available here
def mongo = new GMongo("127.0.0.1", 27017)

// Get a db reference in the old fashion way
def db = mongo.getDB("gmongo")

// Collections can be accessed as a db property (like the javascript API)
assert db.myCollection instanceof com.mongodb.DBCollection
// They also can be accessed with array notation 
assert db['my.collection'] instanceof com.mongodb.DBCollection

// Insert a document
db.languages.insert([name: 'Groovy'])
// A less verbose way to do it
db.languages.insert(name: 'Ruby')
// Yet another way
db.languages << [name: 'Python']

// Insert a list of documents
db.languages << [[name: 'Javascript', type: 'prototyped'], [name: 'Ioke', type: 'prototyped']]

def statics = ['Java', 'C', 'VB']

statics.each {
	db.languages << [name: it, type: 'static']
}

// Finding the first document
def lang = db.languages.findOne()
assert lang.name == 'Groovy'
// Set a new property
lang.site = 'http://groovy.codehaus.org/'
// Save the new version
db.languages.save lang

assert db.languages.findOne(name: 'Groovy').site == 'http://groovy.codehaus.org/'

// Counting the number of documents in the collection
assert db.languages.find(type: 'static').count() == 3

// Another way to count
assert db.languages.count(type: 'prototyped') == 2

// Updating a document using the '$set' operator
db.languages.update([name: 'Python'], [$set: [paradigms: ['object-oriented', 'functional', 'imperative']]])

assert 3 == db.languages.findOne(name: 'Python').paradigms.size()

// Using upsert
db.languages.update([name: 'Haskel'], [$set: [paradigms: ['functional']]], true)

assert db.languages.findOne(name: 'Haskel')

// Removing some documents
db.languages.remove(type: 'prototyped')
assert 0 == db.languages.count(type: 'prototyped')

// Removing all documents
db.languages.remove([:])
assert 0 == db.languages.count()

// To ensure complete consistency in a session use DB#inRequest
// It is analogous to user DB#requestStarted and DB#requestDone
db.inRequest {
	db.languages.insert(name: 'Objective-C')
	assert 1 == db.languages.count(name: 'Objective-C')
}

And a simple MapReduce:

// To download GMongo on the fly and put it at classpath
@Grab(group='com.gmongo', module='gmongo', version='1.0')
import com.gmongo.GMongo

// There is some bug using the [Random] word into codesnipt plugin
import java.util.Random as Rand

def mongo = new GMongo("127.0.0.1", 27017)
def db = mongo.getDB("gmongo")

def words = ['foo', 'bar', 'baz']
def rand  = new Rand()		

1000.times { 
	db.words << [word: words[rand.nextInt(3)]]
}

assert db.words.count() == 1000

def result = db.words.mapReduce(
	"""
	function map() {
		emit(this.word, {count: 1})
	}
	""",
	"""
	function reduce(key, values) {
		var count = 0
		for (var i = 0; i < values.length; i++)
			count += values[i].count
		return {count: count}
	}
	""",
	"mrresult",
	[:] // No Query
)

assert db.mrresult.count() == 3
assert db.mrresult.find()*.value*.count.sum() == 1000

It’s a stable version and still a work in progress. The only dependency is the mongo Java driver version 2.0 and, of course, Groovy. It’s tested under Groovy 1.7.2 and 1.7.3. It’s opensource and hosted at http://github.com/poiati/gmongo.

The binaries can be found at Maven Central. Click here for more details.

Any bug, suggestion or issue please contact me.

Forwarding Objective-C Messages

Unlike Java or plain C, Objective-C work with messages. You don’t invoke a method on an object, instead, you send a message to it (like the Ruby language). This approach let a more dynamic behavior. For instance, suppose that you have this class:

// SomeClass
#import <Cocoa/Cocoa.h>

@interface SomeClass : NSObject {
}

-(void)doSomething
@end

#import "SomeClass.h"
#import "Delegate.h"

@implementation SomeClass

-(void)doSomething {
   NSLog(@"doSomething was called on %@", [self className]);
}

@end

As you can see it has only one instance method definition, called doSomething. Thus, it can respond to the doSomething message. But, what happens when we send a message that the receiver can’t respond to ? Lets make a try:

The receiver is the object that will receive the message. For example, in the statement: [dog bark] dog is the receiver and bark is the message.

Here is our main code:

// MethodMissing
#import <Foundation/Foundation.h>
#import "SomeClass.h"

int main (int argc, const char * argv[]) {
  NSAutoreleasePool *pool = [NSAutoreleasePool new];
  SomeClass *someClass = [SomeClass new];
  [someClass doSomething];
  [someClass doSomethingElse];
  [pool drain];
  return 0;
}

This code compiles with warnings, because the message “doSomethingElse” is not defined in the SomeClass interface. Errors in the Objective-C message dispatch system occurs at runtime. Programmers need to be more careful when dealing with more dynamic languages.

Running the code we got the following result:

MethodMissing[1695:a0f] doSomething was called on SomeClass
MethodMissing[1695:a0f] -[SomeClass doSomethingElse]: unrecognized selector sent to instance 0x10010c6c0
MethodMissing[1695:a0f] *** Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '-[SomeClass doSomethingElse]: unrecognized selector sent to instance 0x10010c6c0'

Not surprisingly the program crashed. First it invoke our declared doSomething message and logged the message to the console, all ok until now. But in line eight we got a NSInvalidArgumentException with the error -[SomeClass doSomethingElse]: unrecognized selector sent to instance 0x10010c6c0.

This error message is very readable, the problem is that, there isn’t any message that respond to doSomethingElse in class SomeClass.

And we got to the key topic of this post. We can handle unrecognized selectors messages and do a special treatment when it arrive to the receiver. How we do that ?

We need to overwrite two methods from the NSObject class in the receiver class: -(void)forwardInvocation:(NSInvocation *)invocation -(NSMethodSignature*)methodSignatureForSelector:(SEL)selector

An NSInvocation is an Objective-C message rendered static, that is, it is an action turned into an object. NSInvocation objects are used to store and forward messages between objects and between applications.

Now our classes looks like this:

// ForwardClass
#import <Cocoa/Cocoa.h>

@interface ForwardClass : NSObject {
}

-(void)doSomethingElse;

@end

#import "ForwardClass.h"

@implementation ForwardClass	

-(void)doSomethingElse {
	NSLog(@"doSomething was called on %@", [self className]);
}

@end
// SomeClass

#import <Cocoa/Cocoa.h>

@interface SomeClass : NSObject {
	id forwardClass;
}

-(void)doSomething;

@end

#import "SomeClass.h"
#import "ForwardClass.h"

@implementation SomeClass

-(id)init {
	if (self = [super init]) {
		forwardClass = [ForwardClass new];
	}
	return self;
}

-(void)doSomething {
	NSLog(@"doSomething was called on %@", [self className]);
}

-(void)forwardInvocation:(NSInvocation *)invocation {
	if (! forwardClass) {
		[self doesNotRecognizeSelector: [invocation selector]];
	}
	[invocation invokeWithTarget: forwardClass];
}

-(NSMethodSignature*)methodSignatureForSelector:(SEL)selector {
	NSMethodSignature *signature = [super methodSignatureForSelector:selector];
	if (! signature) {
		signature = [forwardClass methodSignatureForSelector:selector];
	}
	return signature;
}

@end

When an object receive a message it doesn’t recognize, it wraps the invocation in a NSInvocation object and call the -(void)forwardInvocation passing it as parameter. But, first, it call the -(NSMethodSignature*)methodSignatureForSelector to get the method signature for the given selector.

Now, running the same program again we got:

MethodMissing[523:a0f] doSomething was called on SomeClass
MethodMissing[523:a0f] doSomethingElse was called on ForwardClass

And the program finished without any problems.

There are a lot of uses for this technic, some examples are:

  • Wrap one object in a logger object that intercepts and records the invocation of interesting messages.

  • Implement synthetic messages that are handled by other methods in your class. Imagine creating a generic database record object that catches any property message it receives (i.e., -saleDate, -setSaleDate:) and automatically translates it into a record query. Instead of coding date = [record getDateFieldWithKey:@"SaleDate"], you could simply write date = [record saleDate], without ever writing a -saleDate method. NSManagedObject and CALayer are examples of classes that implement synthetic properties.

  • Create an object that forwards the message to a hierarchy of other objects, like a responder chain. The proxy object would search a collection of other objects looking for one that implements the message

In a future post I will demonstrate one real world application of this.