update to appconstants it can now be used as a gem
This is just a quick post to let you know that AppConstants can now be used as gem!
Just add it to your Gemfile and 'bundle install' it:
#in your Gemfile
gem "app_constants"
#in the console
$ bundle install
$ rails generate app_constants
#then follow the instructions on-screen instructions
It can also be used without Rails. Check out full instructions on the GitHub repository.
Feedback welcome :)
clouds against the floods
I think by now everyone's heard of the hard time the guys up in Queensland, Australia are having because of the recent floods. People have lost their lives and many others have lost their homes and businesses, product of years of hard work.
As a result of this massive disaster the Queensland Government decided to run a telethon to encourage donations to help the flood victims. The Telethon aired last Sunday, 09/01/11, on Channel 9 and lasted for 2 hours.
The problem was the existing donations system that the Government had been using so far: it was just not thought out to handle the load we were expecting to have on Sunday.
That's when my employer, ThoughtWorks, kindly offered a hand to Smart Services Queensland in the attempt to make sure they could receive all donations that were likely to come through the web.
After that, on the Thursday afternoon before the event, Phillip Calçado, Ben Barnard and I set off on a mission against the clock: we had a little over 48 hours to develop, test and deploy an application that was expected to handle thousands of users. Not only that but an application that, should it fail, would prevent millions of dollars from reaching the people in need in Queensland. This was a great responsibility but we knew we could do it.
Given the time constraints it was a bit obvious that we would use Ruby on Rails for this app. Both because of the productivity it's known for and because we had the knowledge right there. With that out of the way, we had to decide how and where we would deploy this thing. We thought a little about it and came down to to 2 options: Amazon EC2 or Heroku (which is powered by Amazon EC2 under the hood). I pushed hard for Heroku and that's what we ended up going with.
Now it was time to get down and dirty and start coding the app. In principle it should be fairly simple. It needed a form where a potential donor would fill out his/her information, giving the option to receive the tax receipt by email or regular mail - more on that later. Upon clicking submit users would be taken to the secure payment gateway website where they could input their credit card number and finish the payment, after which they would be taken back to our app with a success - or an error - message and a transaction number.
Now this work flow has a couple of implications: First, all emails would have to be sent in the background so as to not interfere with the website performance. We were expecting to be sending thousands of them - workers anyone?
Second, the payment gateway integration would have to be developed and tested from scratch. Up until now the Queensland Government integrated with it in a different manner that could not be reused in this case.
And most important of all, although simple in concept, we had no idea of the load we should be preparing for. There was just no data from previous telethons. Thus we decided to prepare for the maximum we possibly could.
As we developed the application we deployed continuously to Heroku in order to test the payment gateway integration, benchmark the app using Apache AB, setup cache headers - Heroku uses Varnish - and find bottlenecks.
Email was one of these bottlenecks and that's why we decided to handle that in the background using Delayed::Jobs.
Since the first deployment, we also tweaked a couple of things at Heroku, such as migrating from their free PostgreSQL offering to a dedicated instance that we believed would both take the load and have plenty of room for all the data - as I write this post, we are already well over the 5MB limit they offer for free.
Long story short, by Saturday evening the website was up and running on 5 app instances, a 6th instance running background jobs - sending emails - and a dedicated PostgreSQL database server.
As Heroku is outside the Government network, their SMTP server was a no go on the short term so we also integrated the app with SendGrid, an email delivery service that fitted perfectly our needs - although the site got so much traction that we went over our monthly quota with them. But the nice guys from SendGrid increased our limit after I opened a ticket explaining the situation!
As for performance we used NewRelic to monitor the application, which Heroku also makes a breeze to integrate with.
We all went home to rest and get ready for Sunday, the day of the Telethon, when we would be monitoring the app throughout the day. We were all excited and when the show went live, we started seeing all those beautiful access charts moving like crazy, spiking over 720 requests per minute and being solid like a rock with flat and fast response times throughout the night.
In about two hours we had over AUD$2,000,000.00 (two million) donated through our website.
Since then the number of transactions dropped but has stayed constant and as of today we've received AUD$25,438,518.32 (over 25 millions of dollars) that will be donated to the flood victims in Queensland.
Oh, and the site is still up and going strong so move your fingers and go help: telethon.smartservice.qld.gov.au - there will be heaps of people grateful for your donation.
help stop the ie money drain
I'm a big heavy metal fan. And so are most of my friends. As a result I launched RottingNames, a band name generator that will generate the most hilarious, nastiest and nonsense names the metal world is yet to discover - ok, that's probably a bit of an overstatement but the idea is good.
However, a friend pointed out the code had a bug when running under - gasp - Internet Explorer. That didn't surprise me at all and I didn't bother to fix it. It's a small app, it's for my own - a few other's - amusement but it did give me the idea about my next micro app.
Ever wondered how much time people all around the world are wasting trying to fix nasty IE bugs? How about putting that in numbers and actually seeing how much money is going down the hole? We can't just drop support - yet. But we can help those poor souls to upgrade to something better.
Enter The IE Money Drain. Whenever you waste time working on trying to make IE behave the way it should, go there and log your hours. Share it with your clients and managers. Show them how much time and money could be saved if we were proactively helping users make the move.
And don't forget to tell colleagues, friends, even your grandma! Share the love ;)
are_you_testing_your_javascript_yet
What's the difference between your application's javascript code and its java/ruby/python/whatever code?
Think about it for a second. Done? Well, the answer is: none!
In today's web applications your javascript code is no different from the rest of your code base but yet we treat it with disregard - and we're all to blame.
We often see developers investing time writing all sorts of automated tests around their code base but fail to do the same for their javascript - and yet they get surprised when their client can't click on a button on their web app that depends on that ajax call that has been manually tested once when the page was first released.
Ask yourself this question if you're not sure if you should be testing your javascript: If it breaks, can my users still benefit from my app? - I think the answer for most web apps is obvious.
As for tools, I can only speak of two, JsTestDriver and screw-unit, the latter being the one we're using in my current project at ThoughtWorks.
What I liked about screw-unit is that it's very easy to get it up and running. Being a Behavior-Driven Testing Framework it's not surprising it has a syntax similar to Rspec -which I prefer over JsTestDriver's similarity to JUnit's.
This is how a test written with screw-unit could look like:
Not too bad for a javascript test suite huh?
So the next time you write a javascript line of code, how about writing a test for it? Consider using screw-unit as your tool but if you have been writing tests using a different framework and you're happy with it, share your experience.
I'm always keen to learn better ways of doing what I do.
Cheers!
small update to appconstants
It's been now over a week since we moved to Sydney and everything is just great. We're still house hunting but I got a feeling we'll have a home soon. :)
In the meantime, this morning I got a feature request on github to allow AppConstants to interpret YAML files with embedded code like this:
I haven't needed it myself but thought it would be a nice addition so my latest commit does exactly that. Let me know if you find any issues.
goodbye europe a two year retrospective
Now several months after I announced my odyssey to obtain my Australian work visa, the time has finally come!
I'll be flying to Sydney next week, April 15th, and as you can probably guess, I'm excited as hell! :) This starts an important new page both in my life and my career, but that's not what this post is about. It's about sharing the experience of living for over two years in Europe.
First off, I traveled. A whole lot. Both for work and leisure. I've been to 23 cities in 11 countries, which you can check on my map. Getting to explore all these different cultures was definitely rewarding and fun, to say the least. But I have my favorites, including Prague, London, Dublin and Bruges...
While in Madrid, I worked for Mirai España, the company that provided me with great professional experiences. I had the opportunity to work with a few very smart people that, in a way or another, contributed to improve my skills as a software engineer. Not to mention the several conferences I attended, including QCon in London, RailsConf in Berlin and serveral others.
Being a rock/metal fan I am in the ideal place to see just about every band I always wanted to. Concerts in Europe are high quality, frequent and affordable and as such, I've attended a whole bunch of them:
- Metallica
- Megadeth
- Soilwork
- Machine Head
- Offspring
- Cavalera Conspiracy
- Within Temptation
- The Haunted
- At the gates
- Judas Priest
- Testament
- Nine Inch Nails
- AC/DC
- Rammstein
- Grave
- Krisiun
- Nile
On a more personal note Madrid is also the place where I met Enif, my beloved girlfriend. We are both very excited about this new experience and, of course, we're moving together to Sydney, with plans of getting married next year! :D
As you can see, Europe has been kind to me and I will certainly miss the experiences, cities, cultures and people I've met. But I'm only making room for more and more interesting things that will certainly happen on the land down under. Let's conquer it all!
Hopefully my next post will be written by the beach, in my new home in Australia.
Cheers, mate! :)
fallingdreams my very own tetris clone
This will come as no surprise to my closest friends, but I am a long time game development admirer. Although I've never done anything professionally I did spend some time in the past studying this amazingly interesting field - it's my dark hobby. As hardware evolves and gamers demand more and more reality from their consoles, the game development industry is one of the few that basically didn't suffer with the latest economic crisis.
3D games are getting more and more sophisticated to the point that it's very hard for a single person, or even a small team, to develop something worthwhile - think of all the people you need to develop a game such as God of War III: screenwriters, artists, musicians, sound engineers, 3D artists, animators, programmers, level designers, combat designers, actors, voiceovers...
So I just wanted to have the experience of writing a full game, end-to-end, and that's where FallingDreams comes in. To be able to do that in a short amount of time, it had to be something simple and that's why I chose Tetris. Although simple, it does share most of the steps common to modern games development. It was a very interesting project to work at and you can grab the result here. The source code is also available on my github account, here.
FallingDreams is written in Java (JDK 6) and as such it should work fine on Windows, Linux and Mac OS. I tried to be as loyal as possible to the original Tetris rules, but you might find one thing or two that don't work as one'd exepct.
Enjoy! ;)
Disclaimer: This was my first 'full game' and is not intended to be production ready. The code has definitely got room for improvement and it served as my playground where I experimented different design techniques, both game and general software related. And it doesn't have a single line of tests - crucify me :P
As I said, it's not supposed to be considered bug free but I'm sure people interested in games development can benefit from the source files. Feel free to fork it as well! It would be cool to see what people would do with it :)
upgrading appconstants to rails 3
Back in January I announced a small but useful plugin called AppConstants, that basically provides a central place where you can store environment specific constants. And since I started using Rails 3 in the past week, I thought I'd make it Rails 3 compatible.
The code is really simple and - as I expected - the upgrade process was quite straight forward.
I'm not gonna write a guide here on how to upgrade your plugins to Rails 3 - there is plenty about that around the web - but instead, just show the steps I went through to upgrade mine. Similar plugins might have a similar upgrade path.
- Generators
My plugin makes use of a simple generator that copies its default constants file and initializer to Rails.root/config and Rails.root/config/initializers, respectively. In Rails 2.x it was located under Rails.root/vendor/plugins/app_constants/generators/app_constants and it was defined like so:
In Rails 3, the generators had to be moved to Rails.root/vendor/plugins/app_constants/lib/generators. Notice the root directory app_constants under generators has been removed as well. And the code was changed to this:
We had three simple changes here:
- The generator now extends from Rails::Generators::Base: This class uses the Thor infrastructure to handle generators. - more info here.
- I had to implement the source_root class method, which basically tells your generator where to find your template files.
- The manifest method is now called copy_config_files - or anything you want.
The way this works is that, once you invoke the generator, Thor will sequentially call all instance methods in your generator class - or the only instance method in the example above. If your generator does a lot, it will allow for a better organization of your tasks.
And that's it! I did change a couple of other things but that had to be changed anyway and are not related to the migration.
For Rails 2.3.x users, you'll find a 2.3.x branch on github that should work for you.
Cheers
learning objective c a ruby analogy
Learning new programming languages is fun. And if it's your 2nd, 3rd...Nth programming language you will eventually look for features you already know and love.
Coming from Ruby - but after having done my fair amount of Java for many years, among other things - I end up looking for features like blocks, open classes and syntax sugar like automatic generation of attribute accessors. These are hard to let go of.
Having decided to learn Objective-C recently, I was delighted to find out that all of these are available - for better or for worse - and wanted to share this analogy with its Ruby counterparts.
- Attribute accessors
In ruby, this class definition
implements for you the getters and setters of the instance variable name.
In Objective-C, the combination of the @property and @synthesize directives provides you with roughly the same result:
Now the compiler is responsible for writing those getters/setters for you.
- Open classes & blocks
Blocks in ruby are the structures that allow you to - among other things - iterate over arrays like this:
Objective-C doesn't have an 'each' method in its root array class (NSArray) but since it does support blocks and open classes, you could just write it yourself:
Yes, I know the syntax isn't appealing, but using it in your program is a bit better:
Given the syntactic differences, the code above is very similar to its ruby counterpart. Iterating over an array is just one of the many things blocks are useful for. Others might include dealing with files, network sockets etc...
Blocks are powerful structures and are not created everyday, but it's nice to know that you can resort to them when the time comes. ;)
hacking rubys syntax
What?
In Ruby you have basically two ways of defining private methods:
I see a small problem with both approaches. In the first one, and the most obvious, is that you need to duplicate the method name as well as add an extra method call - private - just to change its visibility.
The second approach avoids this but adds the risk of accidentally putting a method that is intended to be public under the private section of the source file, which can render an annoying debugging session.
Why?
Personally, I like to have a smooth reading flow in my source files. That means that if the public method_a makes use of the private method_b, I want method_b defined right below its caller, which is possible - but verbose - using the private method call:
But can be somewhat harder to accomplish if you decide to split your source file in sections:
I wanted to be able to define a private method with a single reserved keyword...
How?
What if I could define a private method using this new syntax:
It turns out I can.
Notice the def_p keyword? This is a new keyword I created by changing ruby's parser and that behaves mostly like the def keyword, except that it defines a private method instead.
If you wanna read the code that allows this behavior and try it yourself, download the patch I wrote and apply it to the ruby source code - I patched version 1.9.1-p376.
After applying the patch, just build ruby as usual:
And then try running this script:
You should see the following output:
Happy hacking :)