Sunday, January 6, 2008

Reinventing Rails

These holidays, I was busy developing spendwrite.com. The idea behind spendwrite is a community driven website where users share their experiences about the various places they visit in their town, like restaurants, coffee shops, dentists or shopping malls etc. Everyone reviews the outlets and rates them, so one can easily find the best of places around them.

In the process of development, I learned that it requires a lot of courage and patience to develop a web application. It also requires foresight.

To start with, I chose PHP as the language. Though I love the Ruby on Rails framework, I didn't choose it because its painfully slow. What I intended was, a functionality similar to the one offered by RoR framework, without a real framework in place.

MVC is the leading architecture used by modern frameworks. Rails is no exception, and so many other frameworks use it. So I decided to have an MVC architecture for my website.

I'd learned a lot about MVC and wrote little applications using Rails as well. But the advantage of using MVC was not entirely clear to me before I developed spendwrite.com.

To begin with, I had vague ideas only. I created four directories, like Rails does, called 'models', 'views', 'controllers' and 'helpers'. To be true to MVC, a templating engine was required to play the role of 'views'. Enter Smarty, the templating engine we all know and love. With its caching abilities, it was clearly better than any other templating engines available for php.

Initially, I was creating a model for each table in my database. But as I wrote more code, I found out that much of the code to the models are common. Thats where ActiveRecord component of RoR clicked to my mind. ActiveRecord has a basic CRUD code same for all models. On top of that, individual models define their own methods.

So, I did the same. I carefully wrote CRUD functions, and made this code common to all models. This modular approach was fruitful. Models were tidy now, and the code was easier to manage and debug. Once the CRUD is solid, the models work flawlessly.

Controllers. I must confess, that the habit of writing all-code-in-one-file doesn't go overnight. I wrote a lot of code in controllers, which I shouldn't have. For example, the code for validating user input. Though I had defined helpers like validate_numericality_of and validate_minlength_of etc. in a helpers file, yet writing validation logic in controllers didn't make sense. It took some time for me to realize that validation actually belongs to models, and not to controllers.

Code rearrangement followed. By having all the validation done in models, you relieve controllers of the repetitious job.

For authorization, I'd love to implement something like before_filter in Rails. Since I really couldn't find equivalent, I wrote a model for authorization, and every controller must call a method must_authorize(); if it wants so.

As I write more and more code, I come to realise the beauty of MVC. If you follow the MVC principles strictly, you write less code and error free code. And I also realize how beautifully Rails has implemented MVC architecture.

Rails is no doubt the most productive framework available today for web development. The more you don't use Rails, the more you realize it. :-P

Learning by experimenting is the best way to learn. And while I do, I find myself reinventing Rails. Any coincidence?

2 comments:

tuxdna said...

a great article indeed.
does your CRUD implementation support Migrations ( in RoR ) too?

Kazim Zaidi said...

No. I found no easy way to support them by writing code. And I didn't feel the need to.

If you look carefully, Rails migrations are just version-numbered pieces of up/down code. You can easily keep track of your database migrations by making individual .sql files for up/down versions.

However, I didn't find that suitable. With MySQL, the best way to add new fields is to build the table again, and insert the data back. Its not very cumbersome, and I'm happy with it.