puttering around with Symfony

Wednesday, January 23rd, 2008

On advice from Nate, I'm taking Symfony for a spin (using the stable version 1, not the under-development 1.1), reimplementing the aforementioned contact management application. Here's what I'm noticing:

  • Somewhat like Rails, there's DB-independent schema definition! Big win here. Among other things, this lets you develop in SQLite and deploy in MySQL, which is a nice pattern. Rails' awesome migrations aren't here, so it's not as useful and flexible a system, but it's better than nothing for getting up & running.
  • One big difference from Rails that's clear right away: rather than building code dynamically based on the DB schema, thousands of lines of getters / setters / etc. are generated by the symfony command line tool. Makes sense for PHP, but it's a clunkier development experience.
  • There's testing built in! It's a bit of a PITA to do things like create a test database, and all the pieces for testing your models aren't there right away, but still better than CakePHP. The aforementioned missing piece is available as a plugin. There doesn't seem to be a straightforward way to get the propel-insert-sql task to run on alternate environments, so one must create the db on their own. I'm using SQLite, which is great, but my local environment somehow ended up with PHP having SQLite 2.8 while my command line is version 3 (macports at fault? what a step backwards from Ubuntu...). One port install sqlite2 later, and you can do sqlite data/test.db < data/sql/lib.model.schema.sql
  • No console, which makes the tests even more essential, so it does seem to be worth the pain of getting them working.

Side note -- already, on the basis of the previous post, I'm seeing a surprising amount of traffic from searches on CakePHP, Symfony, and REST. Clearly I'm not the only one looking for this kind of thing.

First thoughts on CakePHP from a Rails perspective

Friday, December 14th, 2007

I have a new project coming up that seems like a great fit for Ruby on Rails, particularly the RESTful interfaces that have gone in over the last year. However, the typical questions about using Rails apply here: I'm not sure how well the project's hosting environment will support Rails, and collaborators aren't as familiar with it. Thus, it seemed like it might be worth another look at options on the PHP side of things. I keep hearing that CakePHP is Rails-inspired and has many of the same advantages, so today I've taken the stable version (1.1.8.5850) for a spin, letting the Cake manual's blog tutorial get me started. Here's what I've noticed about CakePHP development as practiced in the tutorial -- maybe there's better ways to do things & the tutorial just isn't mentioning them?

  • No migrations; you have to generate the DDL on your own, both initially and for any subsequent modifications. Also, no model or controller generators. It's definitely nicer to just do script/generate scaffold post title:string body:text; rake db:migrate and be off to the races -- from Rails 1.2 on, those races include the whole REST business. To be fair, there is a one off reference to 'bake' scripts in the CakePHP manual, but no pointers on what those are, or where they live, and the website isn't much clearer.
  • No TDD. Woah. That's, like, half the advantage of Rails -- automated testing is right there in your face, and is firmly entrenched in the community.
  • PHP code is not quite as elegant as Ruby. For example, generating a link to delete a post looks like this: $html->link('Delete', "/posts/delete/{$post['Post'][id']}", null, 'Are you sure?' ). Can you spot the syntax error? Probably you can, but it took me a good few minutes. The Rails equivalent would be
    link_to "Delete", { :action => "delete", :id => @post.id }, :confirm => "Are you sure?", :method => :delete
  • A lack of the experiences baked into Rails. For example, after the Google Web Accelerator fiasco, it became common practice to make all links to destructive actions happen via POST, which can be done via link_to's :method parameter. Compare to the GET-powered delete link above, straight from the Cake tutorial.
  • I miss my vim & rails integration, which makes creating and navigating the various files a breeze. (Glad I went to the trouble of making that a link, as it got me re-reading the plugin's about page, and I saw the parts about partial extraction and migration inversion, neither of which I'd noticed before)

On the upside, using CakePHP sure beats writing a CRUD-heavy PHP application from scratch. One of my current projects, a completely custom contact management application, would be in much better shape if it were using CakePHP instead of the project-specific ORM I cobbled together -- I'm going to have to give conversion of that project to CakePHP some serious thought.

But is CakePHP a DSL for the web in the sense that Rails is? Not yet.

some snags along the way to rails 2.0 PR

Thursday, October 4th, 2007

Update: Looks like I would have done well to wait a day before upgrading to the 2.0 preview.

I'm giving the Rails 2.0 Preview Release a spin, and finding that upgrading an existing 1.2.3 app is not totally seamless. Hitches I've run into so far:

  • Ran into the missing active_resource issue, discussed at kopongo.com.
  • A bunch of tests failed due to the oddity described (and patched) in ticket 9525.
  • My nested resource routes all broke. Before if you had urls like http://example.com/posts/1/comments you'd get routes like comments_path. Now, you don't; you get post_comments_path. I did find the new `rake routes` output awfully helpful for debugging this one.

Not too bad for a fairly big version jump. Other than the aforementioned annoyances, it's too early for me to say much about the improvements in 2.0. I certainly do like the prettier RESTful URLs, and the prospect of a working debugger was a big motivator.

Deploying my first rails app

Wednesday, January 10th, 2007

I've been working on a little Ruby on Rails application on and off for a few weeks, and finally have enough together that it made sense to deploy it somewhere other than my laptop. It ended up taking all day; here are some of the high and lowlights, in chronological order.

  • When building ruby from source on my Breezy xen slice, I ended up with no zip lib. Gotta download a way old version that says it's obsolete. This is just one reason why package managers are worth having; too bad there isn't an acceptable versions of ruby in Breezy. I did blow a few hours trying to upgrade to Edgy yesterday, but bad Xen things happened so I'm stuck on Breezy for now.
  • Capistrano needs ruby's openssl lib, which is part of the core, but if you don't have the ssl dev libraries around, it doesn't get built. So, rebuild ruby and that part worked.
  • I've been using sqlite for development and though it would be nice for production, too, so I had to install libsqlite3-dev & the sqlite3-ruby gem. Started to think about making it work with Capistrano, via ideas here. But even when the permissions all seem to work ( as in the user running the app can write to the file with the sqlite3 command line tool ) rails is only able to read from it - pukes with a generic error when it tries to write. So, mysql it is. Thanks to migrations, switching from sqlite to mysql only took a minute. Cool.
  • Not so clear on how capistrano knows what user to run things as - this seems like the main reference, but I'm having trouble finding everything I need in there. Probably need to dig around in the source.
  • This app isn't running on its own domain, and I had an unpleasant time with RAILS_RELATIVE_URL_ROOT & lighttpd. I'm running rails 1.2 RC 2 and haven't had a chance to dig around the changelogs to see if there are relevant changes in there that would explain the headaches, which are that it only seems to work if you set it in routes.rb as discussed here. That's lame because you can't just have it for production then. A better approach seems to be just doing it in lighttpd except that the app doesn't then write urls correctly.
  • Thanks to this lighttpd configuration guide for pointing out that alias.url needs to be set as well for the public/ directory to be properly served in this kind of configuration.

In retrospect, I probably would have been better off taking easier paths with a few things - running the app on its own subdomain, and going right to mysql both would have saved me some trouble. There still would have been a number of annoyances but that's par for the course deploying software. Definitely not as much fun as writing the actual application.