My personal site has been through a number of transitions. It was initially a flat/traditional/simple PHP based site with a custom ORM layer. Then I decided that I spent longer maintaining the site and wanted to blog more so I changed to using Serendipity. After a while of still not writing many posts and not updating Serendipity for a while my site got hacked. I'd always advised my clients of the risks of using open source software - that you have to keep it updated otherwise a security vulnerability found in the software means you are one evil mind and a google search away from being hacked - and then ignored that advice myself.
Therefore I decided as I was learning/using Symfony at my contract at the time that it would be a good experiment to write it in Symfony. I was very pleased with the site, I relatively quickly got up a blog, tagging and quick links system with a Lucene based search system, RSS feeds, Flickr photos and Google Sitemap generation. The site did fairly well when I posted but I still posted infrequently.
After a while, I realised that the best use of the site wasn't in blogging (although I still plan to blog more and want to make a commitment to blogging once per week - we'll see how I do on that goal) but in using it as a test bed for developing new functionality/playing with the framework. After my previous article on Why I think Ruby on Rails is an ideal web development environment,I recently developed two sites in Ruby on Rails (one small not yet launched, another medium - but I'm the last man in an outsourcing chain the end client doesn't know about so can't name it) I decided to rewrite it again in Ruby on Rails so that I'd enjoy working with it again (as you can tell my spare time is limited so I'd like to do it in a language I actively enjoy rather than just one that pays the bills).
It's been an interesting experiment. It's hard to get direct comparisons as some of the initial build time was coming up with the look and feel, conversion to HTML/CSS and refining how features would work. Also it's hard to get comparisons of lines of code as there are certainly things I'd have done differently if I restarted it now in Symfony. But there are some useful lessons I learnt...
I counted the lines of code very simply by finding the files in certain folders and piping them in to 'wc -l'. I did this for both the Symfony version and the Rails version. Rails has a built in command to get a count of the lines of code 'rake stats' but I didn't use that as it excludes blank lines and comments (and that wouldn't be a fair comparison). I hadn't written any automated tests for either site (although it's next on my todo list for the Rails version) so that wasn't an issue, I didn't include any externally plugins in either count nor the generated Base classes for the Symfony site.
The final figures are: Symfony 2607 lines and Rails 1067 lines. As I said in the introduction this isn't as direct a comparison as I'd like as there are things I'd do different in Symfony, but I do think it's quite indicative that Rails is a lot more concise to get great functionality using features such as Dynamic Finders and Named Scopes.
The original site took about 4 weeks to build (about 2 evenings per week, 1 evening at the weekend of 3-4 hours each) and the rebuild took 3 evenings. However, this isn't as indicative of how quickly a rebuild in Symfony could be done - as I said a lot of the initial build was in putting together this (admittedly ropey) design and considering how features should work.
The next question for me was "OK, so Rails felt faster to build the site, smaller codebase for the same functionality, but Rails can't scale so how fast is it?". Now, I know there's a difference between scaling and speed so please don't bother pointing this out. At the end of the day my personal site will always likely be on my single machine so I'm just interested in how many pages per second the server can process.
A quick Apache benchmark gave me figures of 1.43 requests/second for the Symfony version and 1.08 for the Rails version. To be honest, I didn't build the site for speed so I wasn't bothered about the performance drop - the performance is acceptable. Then I had a thought, the old Symfony component for latest pictures from Flickr was cached for a few hours but I hadn't done any caching for the Rails version. A quick retest showed a much more respectable 13.41 requests/second - nearly 10x faster than the Symfony version!! We've had some performance problems with Symfony at my current contract, but I wasn't aware it was that much slower than competing frameworks.
As a side note: I've very recently added comments to the site, haven't optimised it at all and it's now dropped down to 7.31 requests/second but I'm aiming to add some optimisations in there and see if I can easily get it above 10 req/s again.
Symfony applications have an enforced structure necessitated really through working in an MVC style. However, beyond that there isn't much information out there on coding style and how to do things "the Symfony way" to the same extent as there is on Rails. Rails is well known to be opinionated software - the framework works better if you follow certain conventions (e.g. plural table names, singular model names, RESTful controllers, etc) and because of this it has a much bigger community eschewing their opinion on the right way of writing code in Rails.
This is a good thing and a bad thing - personally I see nothing wrong with the code "for object in collection" as opposed to "collection.each do |object|" but at least they have an opinion. For some easy learning of some of the Rails community's opinions on MVC and code structuring such as Jamis Buck's important article Fat Model, Skinny Controller watch the videos by the Rails Envy guys called MVC Public Service Announcements. There are also resources such as PeepCode.com's Rails Code Review document which gives a lot of style pointers.
Reading a lot of information about how Rails code "should" look helped a lot in the learning process and I feel like I've a)come out with a better finished site and b)learnt a lot that benefits me in my day job as a Symfony developer.
The obvious question from one of my points above during the lines of code comparison must be "why the hell haven't you got automated tests for your Rails version? That's near criminally negligent!". Well, the short answer is that I wanted to get the Rails conversion done as quickly as possible. I wanted to add comments to the site as I never bothered in the first build and didn't want to waste the time adding them to the Symfony version when I knew I was rewriting it.
So, now I've got the new site up, with comments and now social network sharing - my number one job is to go back and write automated tests. I've been considering using RSpec or Shoulda, but at the end of the day I've used normal Test::Unit for my previous two Rails projects and it served me well.
One thing I would like to recommend is Autotest from the ZenTest gem. This basically is a daemon that runs in the background and automatically reruns your tests as related files change (e.g. change a model or a fixture file and your unit tests for that model will rerun) and then pops up a Growl notification (on Macs) that lets you know if they passed or fail. It's like continuous testing on a local machine as you make each change.
The old Symfony based site was pushed up using Unison over SSH. This worked relatively well and I didn't really have anything better. Now I'm using the best deployment software on the planet - Capistrano. I have it set to deploy from git on my server, run any database migrations and restart ferret on each deployment. I'm hosting using Apache2 with Phusion Passenger.
That was always my concern when I first started looking in to Rails - the whole proxy to mongrels configuration mess. Now, with Passenger it really is easy and a quick touch of a file (which Capistrano does for me) quickly tells it to reread all the files on a new release.
Well, as you can probably guess I'm very happy with the new site code. I added comments over (realistically) two evenings, including Ajax uploading of the comment, a sprinkling of jQuery to make this show/hide/change and Akismet to give them a first pass at checking for spam. On the whole, I've found it a very enjoyable experience. One of the best parts has been converting my code from PHP to Rails line-by-line and then working out what the more Rails-way of doing things is and refactoring it.
When adding functionality I'm finding it much easier to reread the code as Ruby has a much more readable syntax where you tend to chain methods together rather than nest them (in fact this is very jQuery-like - I've got a future post coming up about jQuery and why I like it so much).
Overall I'd rate it a great success. What are your thoughts on PHP, Symfony and Rails? Have you converted a site from PHP to Rails (or vice versa even)?
Let me know in the comments.