Archive for September, 2007

Models, Migrations and the Fourth Dimension (or how to sync the lot together)

Wednesday, September 26th, 2007


Migrations are great. Not perfect but pretty damn good. Certainly better than my previous experiences of handling databases (grab the structure from dev, compare it to qa and then construct a script to move from one to the other – if you are lucky with a tool like Sql Compare, if you’re not then by hand).

But there is a hidden time bomb in there. You see, when you are writing your migration you, your migration and your models are at a particular point in time. But when you deploy your application your migration and your models are at different moments in time. Confused?

Let’s run through an example. It’s August 2007 and your production application is on migration version 12. Your model files, dated August 2007, have lots of nice (unit-tested) validations all set up and ready to go. Fast forward to October 2007. Your production application is still on migration 12 but your development version is on migration 18. Your subversion repository contains a load of model files dated October 2007. It’s time to deploy. You type cap deploy_with_migrations and the migrations fall over at the data insert script, number 13 (unlucky eh?).

So what’s going on?

The thing to remember is that when you are writing the code, the migration and the model are in sync. But when you come to deploy the code they no longer are. cap deploy_with_migrations grabs the October model files out of svn and then runs the migrations one at a time (after inspecting schema_info) – starting with migration 11, then 12, then 13 then BOOM! The problem is that migration 13 is dated September 2007 and is expecting the models from September 2007. But svn has just faithfully grabbed the models from October. If migration 17 adds a new field and the October model has a validation that enforces a rule on that new field – when migration 13 tries to instantiate and save an instance of that class, the (future) validation rule fires and fails. As the field does not yet exist.

So how do we solve this?

It’s a bit of a hack but we can rely on Ruby’s dynamic nature. Just stick a dummy class declaration at the top of your migration file whenever you need to do data inserts.

class MyModel < ActiveRecord::Base

end

class MyMigration13 < ActiveRecord::Migration   def self.up    MyModel.create :field => 'value'  end  def self.down    ...  endend

When MyModel.create is called, it is using your “locally” defined ActiveRecord::Base descendant and not the one in app/models – meaning that whatever validations you have applied (in the future) do not apply. Of course this also means you can screw up the data – but, hey, nobody’s perfect!

Polar bears by Marja Flick-Buijs on stock.xchng

Ruby, Rails, PHP, CDBaby, Digg and Link Baiting

Wednesday, September 26th, 2007

James Hoskins makes a good point, on the North West Ruby User Group mailing list, about the recent Rails to PHP switch.

This my friends is what seo’ers call link bait. Notice the nice digg friendly title with a low number at the beginning followed by a lovely language war headline? Story goes up four days ago, story submitted to digg 3 days ago, look here:

http://digg.com/programming/7_Reasons_I_Switched_Back_to_PHP_After_2_Years_on_Rails_2

Story also forms basis for article at the register:

http://www.regdeveloper.co.uk/2007/09/25/ruby_rails_scripting_project_failure_2_0/

O’Reilly is going to push a whole load of ads on the back of this – plus all the link love – and CD Baby is going to get a whole lot of exposure.

Online marketing, you have to love it.

Why you should use PHP instead of Rails

Sunday, September 23rd, 2007

or why Jeremy Kemper joined 37Signals.

Ok. All that being said, I’m looking forward to using Rails some day when I start a brand new project from scratch, with Rails in mind from the beginning.
But I hope that this reaches someone somewhere thinking, “God our old code is ugly. If we only threw it all away and did it all over in Rails, it’d be so much easier!”

The advantage of testing first

Saturday, September 22nd, 2007

I really like Test-Driven Development. Think about what you need to write, write a test (that fails), then make it pass. Repeat. Refactor.

Obviously, the major benefit is that further down the line you can be sure that what you are writing today won’t break what you (or someone else) wrote six months ago. The tests also serve as a type of documentation (why is that method on the invoice class so complicated? let’s simplify – oh, that test fails – it appears you can’t allow the invoice value to be less than £3 on a Wednesday) – especially if you are using RSpec.

But one advantage, that I feel is often overlooked, is because you are starting from the point of view of a user of your code, your method names and parameters are automatically designed from the user’s perspective, not the implementor’s perspective.

One of my favourite examples is

dave.hit nail, :on => :head, :with => hammer.

This makes your method definition look like

def hit target, options  place = options[:on] || :head  object = options[:with]  ...end

In other words the method definition does not reflect how the caller would actually use your method. If you started from the method definition you would probably come up with

def hit target, place, object
...
end

This makes much more sense from the implementers point of view, but our call becomes

dave.hit nail, :head, hammer

which is slightly less readable from the point of view of someone examining the call in six months time. And those tiny annoyances add up without the reader realising it, till they are tired, the last few lines of code didn’t really sink in and they think fondly back to that other chunk of code that was a joy to read. “Why can’t all code read like that?” they think.

Well, it takes a switch of perspective – one that test-driven development encourages and most other “methodologies” don’t even acknowledge.

Excellent overview of security in Rails

Saturday, September 22nd, 2007

(via the Rails weblog): QuarkRuby

Geekup Leeds

Friday, September 21st, 2007

A bit late but I went to Geekup Leeds on Wednesday. A good night – an excellent presentation from James Holden on integrating SMS and MMS with web-sites, a chat with Dave Verwer about IronRuby and JRuby and a crazed loon nicking drinks and sitting on people’s knees. What more could you want?

Well, somehow I managed to volunteer myself to do a 20/20 talk on Rails – that’s twenty slides, each lasting twenty seconds.

So see you next month!

iPhone piePhone

Tuesday, September 18th, 2007

I don’t mind the £269.

I do mind the £35/month.

Especially when for that £35 you don’t get much data access (O2 doesn’t have much of an EDGE network) or the ability to use your own songs as ring-tones.

My contract is due in February – so we’ll see what happens …

Testing for Unix commands on the path in Ruby

Sunday, September 16th, 2007

Recently we needed to run some tests against our application. However, the application shells out and uses a couple of Unix commands to do some of its work – commands that were not installed on my dev box at the time. Rather than ignoring failing tests (something, like ignoring warnings, I find really hard to do) I thought I should alter the tests to only run if the Unix command was present. After some discussion with Peter he came up with the following syntax:

using :some_command do   some_workend

Pretty nice – if some_command is available then the block is executed, otherwise nothing happens.

(By the way, the code below is (c) 2007 Rahoul Baruah and is available under the LGPL and is not the same as the code that actually made it into our application. [Legal stuff over])

require 'open3'

module UnixTools

  def using command    raise "USING: you must supply a block when calling using" unless block_given? 

    installed = false    Open.popen3("which #{command.to_s}") do | stdin, stdout, stderr |      line = stdout.readline.chomp      expression = Regexp.new "(.)*no #{command.to_s} in(.)*"      installed = !expression.match line    end

    return (installed ? yield : false)  end

end

Stick this in a file called “unix_tools.rb” in your lib folder, make sure which is on your path and use!

One caveat – Peter started getting EOFs – because he was using the version of which that came with Fink. which on OSX returns “no COMMAND in $PATH”, which on CentOS returns “/usr/bin/which: no COMMAND in $PATH” but which in Fink returns EOF. As soon as he switched to /usr/bin/which it worked fine. YMMV, as ever.

Rails is not a silver bullet

Sunday, September 2nd, 2007

Ruby on Rails won’t make you a better coder.
Ruby on Rails won’t deliver a bug-free project.
Ruby on Rails won’t ship your release on time.
Ruby on Rails is not a silver bullet.

I love Ruby on Rails.

I can work faster, more reliably, using “cool” technologies like Unix and Macs and get more done with less grief than any other technology I have ever used.

But Rails is not a silver bullet.

It is still possible to screw things up. Ugly code, buggy sites, slow applications. Rails may make it easy to do things the “right way” but old habits die hard.

Ultimately, what you need, more than anything, is a pervasive set of automated tests. And it’s easier to have a pervasive set of tests if you write them before you write your code.

Why is this important?

Tests give you confidence that the code you just wrote, over here, does not break the code you wrote last month, over there.
Tests give you confidence that the complex, interactive web page that you wrote does not break when you decide to change the way that it works.
Tests give you the ability to go back and tidy up that code that was written at 4:59 on a Friday afternoon – turning it from ugly to beautiful.
Tests become a living, breathing specification of your client’s requirements. Why oh why did we write that code that way? To make sure that “test_customer_order_value_must_not_be_negative” always passes.

So, if you’re just starting out with Rails, please bite the (silver) bullet and write those tests, unit, functional and, if necessary, integration. It may seem to slow you down today but you will not regret it tomorrow.

How to choose a supplier for your new web-site

Sunday, September 2nd, 2007

Need a web-site but don’t have the technical knowledge to do it yourself?

Choosing a supplier can be a daunting task. How can you trust the techie guy when you don’t know your PHP from your RSS? Just what is the difference between a designer and a developer? Are you being overcharged? What exactly does that word on the invoice mean?

Firstly, it helps if you have some idea what you want. What is the goal of your site? Is it to let people know you exist? Is it to boost sales? Is it a portfolio of your work? A good designer should tailor their designs to meet these criteria.

Who is going to be visiting your site? Where do you want them to go? If you’re wanting an online store, which set of pages does your typical customer have to navigate to place an order. It can be useful to draw up a quick flowchart of how you see your “average” visitor moving through the site. In theory, this can give your designer an idea of how many pages you need and what needs to be on each one. However, be prepared for this to change. A decent designer will also know what works and what doesn’t and should be able to modify your ideas accordingly (of course, explaining why these changes are needed).

The flowchart plus a few ideas on the goals, design and layout should be more than enough for the designer to prepare a quote. Watch out if the quote is simply a price – if so, ask for a detailed breakdown. There are two reasons for this – firstly it forces the designer to think through exactly what needs to be done; secondly, it gives you the opportunity to question any of the items you are not sure about. If you are not satisfied with their explanation of what an item is then just walk away. Most problems with web design and software development stem from miscommunication and misunderstanding. If they cannot express what needs to be done in terms that you can understand, at this early stage, you can be sure that there will be problems down the line.

Next, you need to ask how they will deal with changes to the specification or design. This is because you can be absolutely sure that changes will be required at some point – when you see the final layout you decide that you want it a different shade of green, or they may come across some unforeseen technical problem that mandates a change of tack. No matter what the cause it will happen and your supplier needs to be able to deal with it – preferably without adding a zero onto the price!

Then, ask how the project will be delivered. Will you sit there, twiddling your thumbs until, magically, X weeks later, you see the finished article (and then decide upon that different shade of green)? Or do they break the project down into “milestones” giving you the opportunity to comment and feed back early in the process (when changes are easier and cheaper to make)? This also links to another important point – when do they pay the bill? Is it a deposit up-front and the rest on completion? Or staged payments, linked to each milestone? And what is the sign-off process – how do you and they agree on that what was delivered is what was required?

Lastly, what happens after completion? If you want changes making, do they charge an hourly rate or do they charge a percentage per year as a “support fee”? Do they host the site and charge annually for that as well? And, this one is vital, who owns the source code (the computer code that makes up your site)? If they own it and you decide to switch suppliers for whatever reason, your new supplier will have to start from scratch. If you own it, your new supplier may (or may not) be able to use it as a starting point (depending upon the technologies used, the competence of the initial supplier in writing the code and the competence of the new supplier in reading the code).

As for technology, don’t let anyone bamboozle you. Most web technologies (ASP, ASP.Net, PHP, Python, Perl, Ruby on Rails) are all much of a muchness. I prefer Ruby on Rails – it has a number of benefits to me – however, the benefit to you should be reflected in a lower quote and smoother project delivery. Beyond that, you shouldn’t need to care.

Of course, the easiest way is to contact 3hv.