Be sure where your methods are chained to…

I’ve just figured out a quite obscure bug in our app. It all started like this:

record.freeze.things # record is an ActiveRecord, and "things" is an association on that record.
TypeError: can't modify frozen object
	from (irb):2:in `instance_variable_set'
	from (irb):2

The code above shouldn’t crash, because ActiveRecord hast its own #freeze method, which will still allow access to the associations. But our record behaved as if Object#freeze had been called on it. What happend?

Continue reading

Factory Girls secret savings

We like to use FactoryGirl for our test setup. Unlike Rails’ fixtures, it will give you an individual setup for each tests, and thus preventing that tests have side effects on other tests. However, saving objects on each tests comes with a performance penalty.

For your specs, however, you’ll only need to call in many cases, creating an new object without saving it to the database. Only that if you have a factory like the following, the associated objects will always be saved:

Factory.define :project do |f|
  f.association :carrier, :factory => :organisation

That is, even if you call, Factory Girl will internally call Factory.create(:organisation), saving the associated object. If you don’t want that behaviour in your tests, build your objects “manually” in the tests.

Subclass this

In object-oriented languages there’s a nifty feature called code inheritance. People tend to think that this is a really cool ™ thing, since it allows you to quickly slab some new features onto a class whenever the need arises. In fact, there still seems to be a lot of folks who think that the whole point of object-orientation is to subclass a lot.

I’ve previously worked with Microsoft MFC, which was designed that way (but remember, that was back 1992) – as was the class hierarchy that makes your Unreal Tournament tick. I’ve seen object hierarchies spreading over 15 levels, and more.

The only problem with code written that way is that it sucks. A lot.

Continue reading