In the recently released realestate.com.au/share application, one of the most consistent exceptions we received was an “ActionView::TemplateMissing” exception because someone or something was hitting the following URLS.

http://www.realestate.com.au/share/share+accommodation-some-location.xml
http://www.realestate.com.au/share/share+accommodation-some-location.zip

The logical decision was to rescue these exceptions in the ApplicationController itself and serve the generic 404 page. So initially, we had a simple rescue block:

rescue_from "ActionView::MissingTemplate" do |exception|
  respond_to do |format|
    format.any {
      render "error_pages/404",
        :status => :not_found
    }
  end
end

This kept causing a TemplateNotFound exception because even though we were trying to respond to any format, it was still expecting the 404 template to exist in a zip or xml format. Having a symlink as 404.xml.erb or 404.zip.erb also is a bad solution because the expectation of the format is cascading i.e. any views rendered within the 404 would also be expected to have that format, and generally thats a bad idea. So I decided to simply override the request format in this particular case and save myself the trouble. Hence:

rescue_from "ActionView::MissingTemplate" do |exception|
  request.format = :html
  render "error_pages/404",
    :status => :not_found
end

Some days ago Matt and I had to deploy a rails application. This was an application that both Matt and I had no idea existed about 2 days before we ended up deploying it so we were quite looking forward to it on a very rainy wednesday! (Why does it always rain when I am deploying???)

A day before Matt had tried to deploy the application to staging to see whether we could test it out before production got her hands on it, but the staging environment had not been puppetised for this particular app. When we realised that deployment to staging might not possible, we spoke to our resident friendly release manager Aaron and laid out several plans. The first action was for me to test the shi^H^H^H hell out of the app locally (with production data) as much as I could while Matt tried his best to puppetise staging.

Early wednesday morning, I managed to test the app completely and ensured that the changes some awesome developer *cough* had made worked. Matt had also finished his spike with staging but no goodness. So we both looked at each other and decided to deploy it, to production herself.
Four hours, a plate of sushi and a coffee later, the thing had been deployed and we had ensured that it worked in production and informed the relevant parties!

From this all, I have learnt a few things:

1. Even though we both knew nothing about the app, I ensured that Matt was involved in it from the very beginning, and it helped a great deal. Springing deployment surprises on OPS is not cool and helps no one, least of all you as a developer. JIRA and Zendesk are cool, but nothing, nothing will actually substitute going over and talking to your fellow OPS people.

2. Puppet. Puppet is cool. The fact that we could quickly spike things in staging and decide whether to deploy there or not was simply because puppet allowed us that level of automation. Invest of in such tools, whether they be puppet, chef or babushka

3. We did not panic and delay the release when we found out that we could not test it in staging. We sat with Aaron and figured out the risks of each scenario and associated rollbacks. We did as much testing as we could do before hand and then went ahead with the deployment. To quote my colleague Jon Eaves, “Fear is the mind Killer”.

Above all, it was great fun to work with Matt, and deploy something along the way :). This has made me realise that software development, and deployment, is amazingly rewarding when done with awesome people.

I am currently sitting in the foyer of the Jasper Hotel, sipping a cup of tea, thinking about the two sessions I have just had and the one I am waiting for. The sessions got kicked off by Obie Fernandez about the evolution of Rails 3. My first assumptions on listening were that I do not know why I want to know how Merb and Rails merged and who was involved and what was said to whom. But I was clearly in a minority. I put this down to the fact that I have not been as involved with the rails community as much as the majority of the people in the room.

Towards the latter half of the session, Obie began showing the new features in Rails 3 and I have to say that they do look very promising. I have not yet used Rails 3 myself (I began installing it in a separate gemset during the talk) but things like routing(in routes.rb), deploying(using rack), persistence handling and querying (using ActiveRecord etc have been made very very and easy to understand. I particularly like the lazy execution of DB queries and the subsequent chaining. I am told that upgrading from 2.X to 3 is a bit of a pain, but I guess I will find out.

The second session was delivered by Neal Ford about how he was involved a 3 year (and possibly ongoing) long project using Rails that is very enterprisey[sp?] in nature. It was interesting about the philosophy of tests should do but a lot of talk was bout the tools used. (A lot of them happened to be ThoughtWork tools 😉 )

One interesting point that did come up was that they had 15 pairs sometimes having one stand up and that the stand up was still quick! I would have loved to see how that was enforced, as I know that from first hand experience that that is not easy. They created things to make software development easy and they made life of people as easy as possible so that people could concentrate as much as they could on their core task.

But what I liked most of all is that they had 4 work day weeks. 🙂 10 hours a day, sure, but small price to pay for a 3 day long weekend.

I am currently waiting for the next session, which is titled “Why NoSQL” and I am really looking forward to it considering I am thinking of moving my personal projects over to Mongoid

I needed a table to store some text and its index in a list at which the text occured. So as part of my migration, I decided to make sure the schema did not add to my legacy database structure, but relationally associate it. So part of the schema involved specifying the ‘index’ column, which I defined as

CREATE TABLE `meow` (
`index` tinyint(3) unsigned NOT NULL DEFAULT 1,
......
) ENGINE=InnoDB

Now I thought I was safe as I had not used something like int(11), something unfortunately I have come across previously *shudder*. Off I go, happily plodding along with my model and code, till I actually needed to implement the association.

I wrote a simple spec test for it:

Cat.meows = Meow.new(:index => 2)
cat_meows = Cat.meows
cat_meows.should have(1).meow
cat_meows.first.should be_a_kind_of(Meow)

And then inside my model Cat, I had:

has_many :meows, :foreign_key => 'cat_id', :class_name => 'Meow'

Seems simple, doesn’t it! AHA! You fool! You thought you could do this and life would be easy and wonderful and the world would make sense!
Such naivete! Adorable!

When I ran the spec and started getting errors which interpreted the `index` as boolean, I was intrigued. Looking at the API, I find this:

By default, the MysqlAdapter will consider all columns of type tinyint(1) as boolean. If you wish to disable this emulation (which was the default behavior in versions 0.13.1 and earlier) you can add the following line to your application.rb file:

ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans = false

Now while the fix seems simple enough, I would like to point out that this is a very neat and elegant solution for a problem that simply should not have existed! Had Rails made the assumption about a `bit(1)` field, then I would have been fine. Had they made the assumption about `tinyint(1)`, even then I would not have complained. Even the MySQL docs list `tinyint(1)` only as a boolean. Anything else, is simply not a boolean. Rails however, treats all declarations of `tinyint` as booleans. Which is annoying! Not hard to fix, not complicated, but annoying.

Why couldn’t they make that assumption about the `bit` field ?