Ken Levine, creator of System Shock 2, talks to IGN about his forthcoming RPG Bioshock. Two choice quotations:

I’ve always said that, when we were working on Thief, I’d rather have a story element about the moss arrow then about some cult you never get involved with in the game or some god or something. That’s because I play with the moss arrow, it’s part of my game experience; I want to tie that into the story.


I think it’s all about making a world that’s believable. One that has an aesthetic point of view in which the player isn’t constantly bumping into the edge of thus pulls him out of the experience. It’s not about physics puzzles, it’s about having things behave the way I expect them to. Half-Life 2 uses physics puzzles really well; that’s not an issue. My response is not to create my own gravity gun. Our goal is to make this world in Rapture a real place.

Yes. Yes, yes, yes. More sharp, incisive, intelligent discussion in the full interview.

Sometimes, when you’re building a Rails application, you want to generate different relationships to the same model – or, rather, multiple relationships to multiple perspectives on a model. You can tell ActiveRecord to override the expected class name, but you can also use this technique to create “subsets” of classes for relationships, too. It’s worth remembering that ActiveRecord can generate these for you. By doing the query in the database, rather than filtering afterwards, your application will run faster.

As you can see from that explanation, I’m not exactly the greatest developer, so this is probably best explained with an example from life.

I’m currently working on a CMS – yawn yawn, I know. Anyhow, in this CMS, we have articles, and an Article has_many :comments. Obvious one-to-many relationship, fine. However, comments may or may not be spam, marked by the attribute is_spam. So whilst article.comments will return all the comments on a particular article, it’d be nice to have a class method that returns all the clean comments; article.clean_comments, for instance.

My first stab at this was to add the following method to the Article class:

def clean_comments
  output = []
  self.comments.each do |c|
    output << c unless c.is_spam

which is, I suppose, passable idiomatic Ruby, and which does the job; we build an output hash of objects unless the comment is spam. The problem is that if you have, say, an article with a thousand comments - of which 990 are spam, we end up having to generate 1000 objects from the database, and then filter them with Ruby. It'd be faster to select only 10 from the database in the first place, right?

We can do that by defining a new relationship. In our Article model, under has_many :comments, we can add this:

has_many :clean_comments,
         :class_name => 'Comment',
         :conditions => 'is_spam is null',
         :order => 'created_at'

Bingo. That extra has_many allows us to refer to article.clean_comments, and it'll do so directly from the database via SQL. This is a fairly simple example, and I do recommend looking up has_many and has_one (which has similar capabilities) in the Rails API documentation. There always seems to be more depth with Rails than you initially expect, so it's worth digging a little deeper - and you'll make your code leaner, quicker, and better as a result.