I had a bit of an "aha!" moment earlier while working on my ES project that helped me get over one of the major sticking points I had with dynamic languages like ruby. But I'm going to make you read through some background before I actually share the moment itself. If you don't like it, well, too bad. You'll just have to skip a paragraph or three.
Up until a couple years ago the only languages I did any meaningful work in were C++ and Java. I found that I really liked Java's approach to OOP, and I got used to the explicit typing of everything. Most of the errors made in the code could be found by the compiler due to the strict typing requirements (broke down a little bit with collections, but that got better in Java 5).
Over time I started getting used to the dynamic approach and found a few pieces I really liked. I was still put off by the loss of the safety net Java provided with its compile-time type checking, but I started to notice that I could be a lot more expressive with my code, especially once I discovered closures.
By the time I started learning Ruby I had mostly gotten over my discomfort with dynamic languages, but I still worried about typos causing problems. Then some experiences I had working on ES and a snarky comment (link goes to question the comment is on) on stackoverflow clicked together and made me realize the typo problem was already being handled, just not by the compiler.
Typos and other errors that dynamic language compilers/parsers won't find are problems because they only manifest at runtime and only when the actual code path where the typo exists in is hit. Unless your QA people (you have QA people, right?) happen to hit that case it probably won't be found. If it's a rare case that isn't easily triggered by the testers then it's even worse.
Unless you have unit tests. If your code is covered by unit tests then you should find the typos and other errors right away. Mistype a variable name? Test fails with a NameError. Pass the wrong type? You should get an error when the code tries accessing some method that doesn't exist.
I'm trying to have full code coverage in ES, and it's been very helpful finding these. If one of my methods has multiple code paths (for example: handling for a valid move request and raising error for invalid move request) then I'll write a test for each of those paths. Since each path is triggered when I run the tests the errors in the code are found immediately.
Conceptually the unit tests have become the compiler, at least in the context of checking for errors. After I've written some ruby code I'm triggering the tests just like I would have triggered the compiler when writing java code. But it's even better than the compiler. Not only does it help to find typos, it also finds problems in the logic itself, which the compiler never could. It's more work to have, as you have to write the tests, but the benefit of having the tests far outweighs the cost of writing them. You end up finding both code and logic errors much faster, along with a number of other benefits like making it easier to verify any refactoring you did didn't break anything.
PS: On a completely unrelated note - I bought my first domain! This blog is now at http://blog.aherrman.com (or just http://aherrman.com) instead of aherrman.blogspot.com)
Unit tests work as a compiler replacement for finding typos and other code errors that dynamic languages like ruby don't normally fail on.