msgbartop
Just a little about development! Think before you write!
msgbarbottom

06 Feb 09 Tips And Tricks: Adobe Flex – avoid accessing null objects

One of the many possible ways of iterating over an array in Flex is:

1
2
3
4
5
private function iterateOverArray(arr : Array) : void {
  for(var i : int = 0; i < arr.length; i++){
    doSomethingWith(arr[i]);
  }
}

But this code will cause problems if the Array is null, to avoid this kind of problems you can use the following code instead:

1
2
3
4
5
private function iterateOverArray(arr : Array) : void {
  for each(var o : Object in arr){
    doSomethingWith(o);
  }
}

This way we do not need two variable declarations, and we do not try to read the length of a possible null variable.

If you enjoyed this post, make sure you subscribe to my RSS feed!

Tags: , ,

20 Nov 08 Commenting source code is only for the weak

Many of you will probably not agree with me, but if you read all this post, you will probably agree that commenting your source code is a sign that your code sucks. Real men write code that other people can read!
But keep in mind that I’m talking about comments that tell what the code do, and not documentation like “Javadoc”.
For example, if you ware not a Java programmer, or even being a java programmer, can you quickly tell what the code bellow do?

1
2
3
4
5
6
7
8
9
10
public String write(StringBuilder fle, StringBuffer con) {
  File f = new File(fle.toString());
  FileReader fr = new FileReader(f);
  BufferedReader br = new BufferedReader(fr);
  String lin;
  while((lin=br.readLine())!=null){
    con.append(lin).append("\n");
  }
  return con.toString();
}

Hard one? And this is a very simple code, but we can make it a little better …

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public String read(StringBuilder fle, StringBuffer con) {
  //Opens the file with the name container in the fle parameter
  File f = new File(fle.toString());
  //Create a file reader, then a buffered reader to make our work easier
  FileReader fr = new FileReader(f);
  BufferedReader br = new BufferedReader(fr);
  String lin;
  //Read each line of the file until it is null
  while((lin=br.readLine())!=null){
    //Put the content read into the buffer pointed by the parameter "con"
    con.append(lin).append("\n");
  }
  //The caller already have the content, because he created the buffer, but I'll return the string anyway
  return con.toString();
}

Easier, right? Now you can read the comments in the code, and understand it, but the code still crappy.

This is the kind of comment I’m talking about. Commenting your code is a sign that you are a very bad programmer (with little exceptions, in very complex algorithms that you can not break in smaller pieces of code).
When you do this, you are doing a “hack” to hide from others your own incompetence. This mean that you cannot write a clearer code. One that other programmers can read.

Here we have a little solution for the code above, a refactoring of that crappy method:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public String readFileContents(File fileToRead) {
  boolean canReadFile = fileToRead.exists();
  if(!canReadFile)
    return "";
  StringBuilder buffer = new StringBuilder();
  BufferedReader readerForFile = openBufferedReaderForFile(fileToRead);
  readFileContetIntoBuffer(buffer,readerForFile);
  closeFileReader(readerForFile);
  return buffer.toString();
}
private  BufferedReader openBufferedReaderForFile(File fileToRead){
  return new BufferedReader(new FileReader(fileToRead));
}
private void readFileContetIntoBuffer(buffer,readerForFile){
  String line;
  while((line=readerForFile.readLine())!=null){
    buffer.append(line).append("\n");
  }
}
private void closeFileReader(readerForFile){
  readerForFile.close();
}

Now if you pay attention to the method name “readFileContents”, you can already know what it does, besides that, the method code is almost legible, as you can see bellow:

if not can read file, return null
open Buffered Reader For File: fileToRead
read File Contet Into Buffer: buffer, readerForFile
close File Reader: readerForFile
return buffer.toString();

What I’m telling is that if you can read english, you can read the code, and almost every programmer in the planet knows how to read english, right?

I have even seen people doing worst things, like the snippet bellow:

1
2
3
4
5
public String write(StringBuilder fle, StringBuffer con) {
  File f = new File(fle.toString()); FileReader fr = new FileReader(f);  BufferedReader br = new BufferedReader(fr);
String lin; while((lin=br.readLine())!=null){  con.append(lin).append("\n");  }
  return con.toString();
}

It has less lines of code than my version, but you will have a hard time trying to read a program wrote by the monster that wrote the snippet above.

Of course the example I used was a simple one, and I know that writing legible code needs practice …
But I’ll let you a proposal, not really a proposal, an exercise …

I’ll let a code example bellow, and you will try to make it more readable. And I’ll post my solution in one or two days.
If you want to post the refactored code in the comments, just use the tags <pre lang=”java” line=”1″> … </pre>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package blog;
 
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
 
public class VeryBadlyNamedFile {
	private static final char[] asdfg = new char[] {'I', ' ', 'c', 'a', 'n', ' ', 'd', 'o', ' ', 'v', 'e', 'r', 'y', ' ', 'u', 'g', 'l', 'y', ' ', 'c', 'o', 'd', 'e'};
	private String an;
	private BufferedReader rfsdw;
	private FileReader temp;
 
	public VeryBadlyNamedFile(String an, BufferedReader rfsdw, FileReader temp) {
		super();
		this.an = an;
		this.rfsdw = rfsdw;
		this.temp = temp;
	}
 
	public void doIt() throws IOException {
		ctfiidne();
		startDoing();
		try {
			canIDoAnyThing();
		} catch (RuntimeException yicdet) {
			nowReallyDoIt();
		}
	}
 
	private void nowReallyDoIt() {
		firstDoTheOtherThing();
		reallyDoItInternal();
	}
 
	private void firstDoTheOtherThing() {
		rfsdw = new BufferedReader(temp);
	}
 
	private void reallyDoItInternal() {
		while (true) {
			try {
				imDoingIt();
			} catch (Exception e) {
				break;
			}
		}
	}
 
	private void imDoingIt() throws Exception {
		String s = rfsdw.readLine();
		if (s == null)
			throw new Exception("hahaha, I bet you did not understood the code");
		System.out.println(s);
	}
 
	private void ctfiidne() throws IOException {
		File a = new File(an);
		if (!a.exists()) {
			FileWriter wrfedsd = new FileWriter(a);
			wrfedsd.write(asdfg);
			wrfedsd.close();
		}
	}
 
	private void canIDoAnyThing() {
		if (new File(an).exists() && new File(an).canRead() && new File(an).canWrite())
			throw new RuntimeException();
	}
 
	private void startDoing() throws FileNotFoundException {
		File f = new File(an);
		temp = new FileReader(f);
	}
}

And now a “main” file to exebute the trash above.

1
2
3
4
5
6
7
8
9
package blog;
 
import java.io.IOException;
 
public class Main {
	public static void main(String[] args) throws IOException {
		new VeryBadlyNamedFile("c:\\anyFile.any",null,null).doIt();
	}
}

The examples in this post are using Java, but the concept apply to any language, if you are programming and using comments to explain your code, you are a terrible programmer. Just pray for god’s help, and beg him that the next one to read the crap you are creating is not a serial killer that knows where you live.

PS.: I really do not think that you should not comment your code, but if your code is not understandable without the comments, you do not know how to write programs yet.

PS2.: I think I need better examples.

PS3.: the secret to write good code is to write it as if the next one that will read your code is a serial killer that knows where you live. (I do not remember who wrote this sentence in the first place, I’ll research and post it here)

If you enjoyed this post, make sure you subscribe to my RSS feed!

Tags: , ,

31 Oct 08 Solving the Alzheimer of your PopUpButton

As you can see here, Adobe created a big problem (at least for me) after solving a memory leak problem.
But thanks to Scott Melby at this post, now I have a medicine to the Alzheimer of the PopUpButtons in mu Applications, and I called this medicine “PopUpMenuGuardian”.
The problem is that the PupUpButton stops poping up after a screen resize for example.
The exact proposed solution was not good enough for me because I have many PopUpButtons, so, I created this helper class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
	import flash.events.Event;
 
	import mx.controls.Menu;
	import mx.controls.PopUpButton;
 
	public class PopUpMenuGuardian
	{
		private var rbtn : PopUpButton;
		private var mnu : Menu;
 
		public function PopUpMenuGuardian(rbtn : PopUpButton)
		{
			this.mnu = rbtn.popUp as Menu;
			this.rbtn = rbtn;
			rbtn.addEventListener(Event.ADDED_TO_STAGE,restoreMenu);
		}
 
		public function restoreMenu(evt:Event):void{
			rbtn.popUp = mnu;
		}
	}

And now I just need to create one of this objects after I create each popupbutton :D

I think Adobe should fix this ASAP, but at least I have a workaround now.

PS.: I know I’m a looooong time without posting, but I just finished writing my RoR book, I’ll probably post more often now.

If you enjoyed this post, make sure you subscribe to my RSS feed!

Tags: , ,

12 Jul 08 Unit tests in c++ for a Java GUI

I have worked with C++ in my early days of programming (between 1997 and 2000), but I used to work with Borland C++ Builder and Microsoft Visual C++, in that time I have not heard about unit tests yet, after that I worked with Delphi, PHP, ASP, ColdFusion,  …
Since 2002 I worked most of the time with Java, and learned a lot since then, lots of good practices, a lot more about object orientation and I learned to love unit tests.
Little time ago I starter working with C++ again, but I’m already in love with unit tests, and want to do them for my C++ code too, and this post is a very short example of how a Java programmer can work with C++ and do unit tests.

A C++ project starts with a Makefile, I’m used with ANT and do not like the idea of enumerating all my source files in a build configuration file like most examples of Makefiles do, so I created a simple but very flexible Makefile for my project.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
TESTDIRECTORIES := test
DIRECTORIES := src
SOURCES := $(foreach dir,$(DIRECTORIES),$(wildcard $(dir)/*.cpp))
TESTSOURCES := $(foreach dir,$(TESTDIRECTORIES),$(wildcard $(dir)/*.cpp))
OBJECTS := $(patsubst %.cpp,%.obj,$(SOURCES))
TESTOBJECTS := $(patsubst %.cpp,%.obj,$(TESTSOURCES))
TESTOBJECTS += $(filter-out src/main.obj,$(OBJECTS))
TARGET := example
LINK := g++
CC := g++
CFLAGS := -c
LFLAGS :=
 
all: $(OBJECTS)
	$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS)
 
test: $(TESTOBJECTS)
	$(LINK) $(LFLAGS) -lcppunit -o $(TARGET)_unit $(TESTOBJECTS) 
	./$(TARGET)_unit
 
%.obj:%.cpp
	$(CC) $(CFLAGS) -o $*.obj $*.cpp

With this make file, all cpp files in the src directory will be part of the target executable, more directories can be added just enumerating the source directories in the “DIRECTORIES” variable, the same for the test code, under the test directory and the “TESTDIRECTORIES” variable.
The trick here is the combination of the functions foreach and wildcard, the function pathsubst is used to change the extensions from .cpp to .obj and the filter-out function is used to remove the main.cpp (the entry point for the main application) from the test objects.
This Makefile is the nearest I could get from ANT functionality for C++ programming, but of course it can be improved a lot.
But the Makefile is not the target of this post, I’m writing this post to tell you about CppUnit, a great unit test framework for C++.
I started writing this unit test runner using CppUnit:
testRunner.hpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <cppunit/CompilerOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TestRunner.h>
#include <cppunit/BriefTestProgressListener.h>
 
int main (int argc, char* argv[])
{
    // informs test-listener about testresults
    CPPUNIT_NS :: TestResult testresult;
 
    // register listener for collecting the test-results
    CPPUNIT_NS :: TestResultCollector collectedresults;
    testresult.addListener (&collectedresults);
 
    // register listener for per-test progress output
    CPPUNIT_NS :: BriefTestProgressListener progress;
    testresult.addListener (&progress);
 
    // insert test-suite at test-runner by registry
    CPPUNIT_NS :: TestRunner testrunner;
    testrunner.addTest (CPPUNIT_NS :: TestFactoryRegistry :: getRegistry ().makeTest ());
    testrunner.run (testresult);
 
    // output results in compiler-format
    CPPUNIT_NS :: CompilerOutputter compileroutputter (&collectedresults, std::cerr);
    compileroutputter.write ();
 
    // return 0 if tests were successful
    return collectedresults.wasSuccessful () ? 0 : 1;
}

CppUnit is very flexible, allowing lots of outputs for the tests, I’ll write another post about this soon, but the idea of this runner is to use the CppUnit test registry, what makes a lot easier to work, because you can forget about the runner, just write your tests and register it.
It is almost like the fileset you pass to the junit task of ANT but written in C++.
After the test runner is ready, you can start writing your tests.
C++ different from Java, you use 2 files for each class, one header and one implementation file.
Let’s start with the header …
mainTest.hpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#ifndef MAINTEST_H
#define MAINTEST_H
 
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>
#include "../src/HelloWorld.hpp"
 
using namespace std;
 
class MainTest : public CPPUNIT_NS :: TestFixture
{
    CPPUNIT_TEST_SUITE (MainTest);
    CPPUNIT_TEST (testHello);
    CPPUNIT_TEST_SUITE_END ();
 
    public:
        void setUp (void);
        void tearDown (void);
        void testHello (void);
    private:
        HelloWorld *hello;
};
CPPUNIT_TEST_SUITE_REGISTRATION (MainTest);
#endif

In this header we have a simple class declaration, extending TestFixture from the cpp unit namespace.
C++ is a static language without reflection, because of that CppUnit has the macros you can see in the top of the class declaration, you need one CPPUNIT_TEST line for each test method you write.
Ant the line: CPPUNIT_TEST_SUITE_REGISTRATION (MainTest);
Does the magic of test auto registration.
After this you can write your test as you do in Java:
mainTest.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "mainTest.hpp"
 
void MainTest::setUp(){ 
	hello = new HelloWorld("Test");
}
 
void MainTest::tearDown(){
	delete hello;
}
 
void MainTest::testHello(){
	string expected("Hello Test\n");
	CPPUNIT_ASSERT_EQUAL(expected,hello->sayHello());
}

As in JUnit we have a setUp and a tearDown method, this methods does exactly the same thing, they initialize/uninitialize the variables you will use in your test code, and the “testHello” method is our test.
the assertions in CppUnit are done using macros.
These are the available assertions:

  • CPPUNIT_ASSERT(condition)
  • CPPUNIT_ASSERT_MESSAGE(message,condition)
  • CPPUNIT_FAIL( message )
  • CPPUNIT_ASSERT_EQUAL(expected,actual)
  • CPPUNIT_ASSERT_EQUAL_MESSAGE(message,expected,actual)
  • CPPUNIT_ASSERT_DOUBLES_EQUAL(expected,actual,delta)
  • CPPUNIT_ASSERT_THROW( expression, ExceptionType )

A lot less assertion types than junit, but enough for working.
After the test done, now we just need to write our code!
HelloWord.hpp

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <iostream>
 
#ifndef MAIN_HPP
#define MAINHPP
class HelloWorld{
private:
	std::string name;
public:
	HelloWorld(char* name);
	std::string sayHello();
};
#endif

and the implementation:
HelloWord.cpp

1
2
3
4
5
6
7
8
9
10
11
#include "HelloWorld.hpp"
 
HelloWorld::HelloWorld(char* name){
	this->name = name;
}
 
std::string HelloWorld::sayHello(){
	std::string result("Hello ");
	result = result + name + "\n";
	return result;
}

To run the tests, you just need to type in the console:
make test
With all tests written and passing, the last step is the application runner (like the test runner).
main.cpp

1
2
3
4
5
6
7
8
#include "HelloWorld.hpp"
int main(int argc, char** argv){
	if (argc >= 2) {
		HelloWorld* hello = new HelloWorld(argv[1]);
		std::cout << hello->sayHello();
		delete hello;
	}
}

And you have your first test driven C++ application up and running!
PS.: if you are using my makefile, remember that application code is placed into src folder and test code is placed into test folder.
PS2.: the example was tested on linux with cpp unit installed using the package manager, if you want to install cpp unit from source, remember to update CFLAGS with the include path and LFLAGS with the library path. and if you are not using g++ as the compiler and linker, change the CC and LINKER variables with appropriated values.

If you enjoyed this post, make sure you subscribe to my RSS feed!

Tags: , , , ,

09 Jun 08 GEdit plugin formatting Ruby and ERB code now!

I have published some time ago a GEdit plugin for formatting Ruby code.

Now I just updated the plugin and added support for formatting html.erb and .xml.erb files too.

The main idea  is to make this plugin a generic language code formatter for GEdit, contributions are welcome.

As told before, to install it, grab the source from GitHub and copy all files to ~/.gnome2/gedit/plugins.

To download the files using Git use the following command line:

git clone git://github.com/urubatan/gedit_formatter.git

If you want to contribute just send a pull request in GitHub or send me a patch by e-mail.

To use the plugin, just press CTRL+ALT+F after installing and enabling it.

If you do not have git installed, you can download a tarbal with the latest sources from this link.

If you enjoyed this post, make sure you subscribe to my RSS feed!

Tags: , , ,

17 May 08 Tired of looking at the console to know if the tests passed or failed?

AutoTest (part of ZenTest suite) is a very useful tool when you are working with Ruby On Rails development, but I always had problems configuring cool notifications for it, until now!

A friend of mine, started a little project to develop a gem (his first idea was just a lib for his own use, but now it turned to be an open source gem), that makes really easy to setup AutoTest to notify you of test results in a very cool way!

If you have a Mac, it will use Growl.
If you have windows, it will use Snarl.
If you have a Linux Box, it will use zenity or libnotify for Gnome and kdialog for KDE (I think libnotify works for any desktop environment).

And it is even cooler that this, if you run a Mac or Linux box, it can talk to you when your tests fail!

The project is hosted at GitHub, and to use it, you just need to run this two commands:

gem install carlosbrando-autotest-notification --source=http://gems.github.com
an-install

if you want it to talk to you, replace the last command with:

an-install -s

the voice code for linux is not in the main repository yet, it is on my fork, so if you run a linux box, and want to play with voice notification, you need to have espeak installed, and install my instead of the primary one (at least until the code is pushed back).

gem install urubatan-autotest-notification --source=http://gems.github.com

If you have a Windows box and want to play with voice notification, be a smart guy, format your machine ans install linux, you will be a lot happier that you are today :D
If this is not an option for you, you can always fork the project, write the code for a windows speech engine, and send us a pull request :D

Bellow a quote from the project readme about the dependencies of each platform:

* If you’re using a Mac:
You need to have Growl and growlnotify installed on your machine.

Download the Growl [http://growl.info/index.php] and install it like any other application on your Mac

Then you must install the growlnotify.

In your shell, cd to the directory on the Growl disk image containing growlnotify, and type ./install.sh.
That script will install growlnotify to /usr/local/bin and the manpage to /usr/local/man.

* If you’re using Windows (with cygwin):
You need to have Snarl and sncmd installed on your machine.

Download Snarl [http://www.fullphat.net/] and install it like any other application on your machine.

Then download sncmd [http://www.k23productions.com/download.php?view.105] open the zip file and place
the executable from the zip in any directory in windows PATH (for example c:\windows).

* If you’re using Windows (without cygwin):
You need to have Snarl, diffutils and ruby-snarl installed on your machine.

Download Snarl [http://www.fullphat.net/] and install it like any other application on your machine.

Download DiffUtils for Windows [http://gnuwin32.sourceforge.net/packages/diffutils.htm] and follow the installation
instructions on the site.

Run in the command prompt:

$ gem install ruby-snarl

After all that. You must update the environment variable PATH with the path to the bin of diffutils.
It’s the price that was paid for using Windows (try cygwin).

* If you’re using Linux:
You need to have libnotify binaries installed.

For ubuntu this means: sudo apt-get install libnotify-bin

Other distributions may package it with other names, do a search for libnotify using your distribution package
manager.

If you use KDE and do not have libnotify-bin installed, it will try to use kdialog wich is part of KDE.
It also works if you have zenity installed.

If you want to be notified with voice of the test results, instal espeak too, it is not needed.
And when running an-install, pass a “-s” switch, when you do not want voices notifications anymore, just run it
again without the “-s” switch.

I know that you can live without this cool new toy, but think about your work mates trying to figure out, how do your computer can tell you that your tests passed or not :D

If you enjoyed this post, make sure you subscribe to my RSS feed!

Tags: , , , , , ,

04 May 08 GEdit plugin for formatting ruby code


I work with Java for a long time, and I’m used to Eclipse facilities, but to work with ruby on rails I think an IDE is not needed, I work better with GEdit (or even VIM, depends on my humor) than ith NetBeans or Aptana.
But there are some features of an IDE that I miss when working with GEdit, for example code formatting.
As a heavy eclipse user, I prefer to let eclipse take care of the indentation of my source files …
So I have created this GEdit plugin to format ruby files, if you want to use it, just checkout the source code from GitHub and copy all files to ~/.gnome2/gedit/plugins, restart gedit and you are ready to go …
After reopening GEdit, click Edit\Preferences\plugins and enable the “Code Formatter” plugin.
then, when you are editing a ruby file, just click CTRL+ALT+F and the code will be formatted for you.
if you are more a mouse gui, just click Tools\Format Code.

I hope this plugin can be useful for others too.
I plan to add support for more languages, for example XHTML and RHTML (ERB + XHTML), I know tidy plugin can do this, but I do not like the default tidy configuration, but will probably use tidy as a backend to this feature :D

to checkout the code, you can download the zip file available in the project page, or use git:

git clone git://github.com/urubatan/gedit_formatter.git

Any doubts, problems or tips for improvements just leave a comment, here or in github.

PS.: this was my first GEdit plugin, and my first experience with python, the code can be improved a lot, any comments about that are very welcome.

If you enjoyed this post, make sure you subscribe to my RSS feed!

Tags: , , ,

22 Apr 08 easyb-test – Grails Tests Made Easy (in a way your boss can read)

Have you ever read about easyb? and about Grails? May be you answer yes to one or both previous questions, but this is the first time you will find them together I guarantee, at least in a plugin form.

This is the first post I’m writing about my latest toy project (at least for now it is only a toy project).

The project is hosted at GitHub, and any help will be very welcome since I do not work every day with Grails, but I did a presentation about grails in the last weekend and wanted to use BDD instead of the traditional GUnit based unit tests, I already use Easyb for some of my Java projects, then I wanted to make Easyb and Grails to work together.

It was not an easy task, because of some craziness of Grails class loader, but it is working fine now.

You can write a test with the easyb sintaxe, and the test will look line this:

scenario "Project creation", {
	given "A new project", {
	  project = new Project()
	}
	when "the project name is supplied", {
		project.name = 'My test project'
	}
	and "there is no other project with that name", {
		validateproject = {
			project.validate().shouldBe true
		}
	}
	then "a new project must be created", {
		validateproject()
		project.save(flush:true).shouldNotBe null
	}
}
scenario "User association with a project", {
	given "Any existing project", {
		project = Project.findAll()[0]
	}
	when "a list of users is supplied", {
		users = [new User(login:'testUser1',password:'testUser1',email:'test1@test.com').save(),new User(login:'testUser2',password:'testUser2',email:'test2@test.com').save()]
	}
	then "the users must be associated with that project", {
		users.each{
			ProjectMembership.link(it,project)
		}
	}
}

You can even show it to your boss, because the output of this test is some thing like this:

Story: project management
  scenario Project creation
    given A new project
    when the project name is supplied
    when there is no other project with that name
    then a new project must be created

  scenario User association with a project
    given Any existing project
    when a list of users is supplied
    then the users must be associated with that project

And the best part of it, is that you can use your tests as the specifications of your next grails project!
If you want to know more about the easyb sintax, take a look at the project site.
If you want to know more about grails, take a look at the project site.
If you want a new functionality in this plugin, I’ll probably accept all patches and push requests you send-me :D
And finally, if you want to install the plugin, download it from here and run:
grails install-plugin grails-easybtest-latest.zip

You will need to place the tests you write in the folder tests/behavior
And to run the tests, just type: grails easyb-test
Any doubts or suggestions leave a comment here :D
I hope it can be useful to others.

If you enjoyed this post, make sure you subscribe to my RSS feed!

Tags: , , , , ,

11 Apr 08 Google App Engine – When will programmers learn that a language is just a tool?

Google App EngineGoogle has launched a very cool application server, it is called Google App Engine.

Kudos to google again :D

But this application server started a big war on the internet, lots and lots of developers around the world, are very sad because the only supported language in the application server is Python.

Google App Engine has free accounts with limitations, like heroku for example, which is a great application server that supports only Ruby On Rails.

So, what is the problem?

The big problem is that because App Engine is from Google, most of the developers that haven’t not learned Python yet are yelling around because Google App Engine does not support their language.

But the real problem here is that these developers do not understand that a programming language is only a tool you need for work.

Most of the money I get every month is from Java programming, but I have to use many other languages, like Ruby, Bash, ActionScript/Flex, Java, C++, Object Pascal/Delphi, …

<opinion>
If you think yourself as a developer and you can write programs using only one language, you is probably a very bad developer.
</opinion>

I think this bunch of “why did you choose python instead of my beloved Java/Ruby/Perl” is just because it is from google, and everyone wants some google love.

Why no one yells about Heroku supporting only Ruby On Rails? Not even the Merb programmers …

But if google created Heroku (almost it did now), every one would complain about the chosen language.

I liked the idea of Google App Engine, probably this was the push I needed to learn Python (I never liked it, and never had any good reason for that, I just do not want the idea of spaces defining code blocks :D ), the only boring thing is all this yelling about the supported language.

If you enjoyed this post, make sure you subscribe to my RSS feed!

Tags: ,

24 Jan 08 Writing rails plugins – tips and tricks – plugins with generators

Following the sequence I started here, but changing the proposed order, let’s talk a little about Rails Generators.

Generators are one of the coolest things in Rails!
Of course you have already seem them, remember the first screencast you’ve seen about rails? Yes, that one where the guy wrote an entire CRUD application[bb] in two minutes …

Generators are a way to, generate code :D

But the generated code can be what you want, and rails already has a great support for writing generators, because it is already used in the rails core.

OK, but why would you want to write a generator?
Think about the project that is starting today, remember all that CRUD forms you’ll need to create, or that almost equal start point for every page of the application …
Now think about all the applications for your company …
Got it?

Ok, I agree that “scaffolding” a generic CRUD is not really useful, but if that scaffold is done following your company standards, it can improve a lot the development performance …

Now, I guess you are thinking: Good, generators[bb] seem cool, but stop the easy talk e show me the code!

So, let’s play a little …
Wi’ll start creating a new rails project: rails plugins102
Now from the project directory run: script\generate plugin my_generator
(if you think this is kind of a flash back, maybe you read my previous post about creating rails plugins :D )

Now that you have already created your brand new plugin, let’s write some code!
To create a generator you need to create a generators directory inside your plugin’s directory, a directory with the name you want for your generator (for example test_gen), and a templates directory inside the previous one, for example, it will look like this:

  • my_generator
    • lib
    • tasks
    • test
    • generators
      • test_gen
        • templates

Ok, you do not really need a plugin to create a generator, you can of course, place your brand new generator inside the following directories:

  • RAILS_ROOT/lib/generators
  • RAILS_ROOT/vendor/generators
  • RAILS_ROOT/vendor/plugins/plugin_name/generators
  • USER_HOME/.rails/generators
  • gems ending in _generator

But I think that a plugin is the easiest way to do it, and it will be easier to deploy to your applications too.
Of course that a GEM would be a better way, because you can install only once per machine, and does not need it installed on the server, but I have never created a GEM before, so let’s stay with the plugin for a wile …

to start coding the generator, we’ll need to create a file named [generator_name]_generator.rb inside the generator’s directory, in my case, I’ve created the file: my_generator/generators/test_gen/test_gen_generator.rb

Now inside that file, create the class to define your generator, it must be named according to the file name, in my case TestGenGenerator, and this class must extend one of the base classes for Rails generators:
Rails::Generator::Base or Rails::Generator::NamedBase, I’ll use NamedBase (The base for the controller generator), and I’ll create a generator for a model and a migration, just to show how to do it …

The NamedBase is the perfect base class for generators that expect parameters in the form: Name [param1] [param2] …
For all the others, Base is a best start point …

The starting point for our code is:

1
2
3
4
5
6
7
class TestGenGenerator < Rails::Generator::NamedBase
  def manifest
    record do |m|
 
    end
  end
end

In this class, all we need to do is to set up the generator’s manifest (more on this later) and to setup any local variables to be used by our templates (more on this later too).

with only this, we can already run: ruby script\generate test_gen asdas_dasda asd:ash (randon letters as parameters for now).
The NamedBase will automatically set up some variables for us, and the values for the given parameters will be:

  • class_name -> AsdasDasda
  • class_nesting ->
  • class_nesting_depth -> 0
  • class_path ->
  • file_path -> asdas_dasda
  • name -> asdas_dasda
  • plural_name -> asdas_dasdas
  • singular_name -> asdas_dasda
  • table_name -> asdas_dasdas
  • attributes -> #<Rails::Generator::GeneratedAttribute:0×3716418>
  • args -> asd:ash

of course this generator now will generate nothing, because our manifest is empty, so let’s build a simple example to see how it really works …
so, lets create inside the template directory, a directory called “dummy”, and a blank file called “log.log” inside of it and let’s change the manifest method to some thing like this:

1
2
3
4
5
  def manifest
    record do |m|
      m.file 'dummy/log.log', "log/#{file_path}.log"
    end
  end

This code will tell the generator, to copy our newly created, blank file, to $APP_ROOT/log/asdas_dasda.log if we run the generator with the same parameters as before …
but just copying files from one place to another is not a very cool thing to be done, so let’s play a little with ERB, and let’s create a migration for our plugin, so we need to change again the manifest method as follow:

1
2
3
4
5
6
7
8
  def manifest
    @migration_name = "Create#{class_name}"
    @migration_action = "add"
    record do |m|
      m.file 'dummy/log.log', "log/#{file_path}.log"
      m.migration_template 'lib/mymigration.rb',"db/migrate", :migration_file_name => "create_#{file_path}"
    end
  end

As you can see in the code, I’m telling the manifest that I have a template named mymigration.rb inside the directory lib in my templates directory, it will be processed and the result will be placed inside the directory “db/migrate” and will be called “000_create_asdas_dasda.rb” (the 000 will be replaced with the latest migration number plus one as the normal “generate migration” command do.

to be able to access the attributes migration_name and migration_action in the template, we need create the accessor methods for them, it is as easy as adding the following line to the TestGenGenerator class (outside the manifest method):

1
attr_accessor :migration_name, :migration_action

My migration template is the following:

1
2
3
4
5
6
7
8
9
10
11
class <%= migration_name.underscore.camelize %> < ActiveRecord::Migration
  def self.up<% attributes.each do |attribute| %>
    <%= migration_action %>_column :<%= table_name %>, :<%= attribute.name %><% if migration_action == 'add' %>, :<%= attribute.type %><% end -%>
  <%- end %>
  end
 
  def self.down<% attributes.reverse.each do |attribute| %>
    <%= migration_action == 'add' ? 'remove' : 'add' %>_column :<%= table_name %>, :<%= attribute.name %><% if migration_action == 'remove' %>, :<%= attribute.type %><% end -%>
  <%- end %>
  end
end

It is an ERB template that will generate a ruby file.

Now we have already a very cool working plugin, but what else can we do?
to answer this question, I’ll quote a little the documentation of the Rails::Generator::Commands::Create class, that means, what can you do within the manifest method:

  • class_collisions – Check whether the given class names are already taken by Ruby or Rails. In the future, expand to check other namespaces such as the rest of the user‘s app.
  • directory – Create a directory including any missing parent directories. Always directories which exist.
  • file – Copy a file from source to destination with collision checking.
  • identical? – Checks if the source and the destination file are identical. If passed a block then the source file is a template that needs to first be evaluated before being compared to the destination.
  • migration_template – When creating a migration, it knows to find the first available file in db/migrate and use the migration.rb template.
  • readme – Display a README.
  • route_resources – add a route to the routes.rb
  • template – Generate a file for a Rails application using an ERuby template. Looks up and evaluates a template by name and writes the result.

I think that is it, you can ask more questions if you want, I’ll try to answer all, if any :D

for more resources on Rails generators you can follow this links:
http://wiki.rubyonrails.org/rails/pages/UnderstandingGenerators
http://www.aidanf.net/node/33
http://api.rubyonrails.org/classes/Rails/Generator/Base.html
http://api.rubyonrails.org/classes/Rails/Generator/NamedBase.html
http://api.rubyonrails.org/classes/Rails/Generator/Commands/Create.html

I hope this little step by step help some one!
The next one will be about writing tests for your plugins! and the fourth I have not started to think about yet :D

If you enjoyed this post, make sure you subscribe to my RSS feed!

Tags: , , , , ,