Archive for September, 2007

September 15th, 2007

My troubles with many-to-many

by Tim Cull

New version of MyStats!. In this version, when you add new people to your group, they actually get an email asking them to sign up. Also, there are many other usability improvements.

So, a long time ago I promised to describe a problem I was having with a many-to-many relationship. You’ll need to strap on your seatbelt, because this one takes some explanation…

I’ve got this many-to-many relationship from a RegisteredUser to a Person that basically says “this registered user is allowed to report the status of these people.” Why do I have different classes for a registered user and a plain, old person? Because I want registered users to be able to keep track of other people who aren’t necessarily users of my application (like, say, my 18 month old daughter). You can think of RegisteredUser as a specialization of Person and, in fact, if I were doing things over again I would have made that literally so (my failure here will become important).

So anyway, I wanted to make this relationship bi-directional, so that for each member of this:

a_registered_user.authorized_reportees

the following would be true:

a_person.authorized_reporters.include?(a_registered_user)

Sounds pretty easy, right? I just had to model it like this:

class RegisteredUser < ActiveRecord::Base
  belongs_to :person
  has_and_belongs_to_many :authorized_reportees, :class_name => 'Person',
        :join_table => 'authorized_reporters'
end

class Person < ActiveRecord::Base
  has_and_belongs_to_many :authorized_reporters, :class_name =>'RegisteredUser',
        :join_table => 'authorized_reporters'
  has_one :registered_user
end

Turns out that didn’t work and it all hinges (I think) on the fact that I’ve got two relationships between RegisteredUser and Person:
1. RegisteredUser.person/Person.registered_user which is where RegisteredUser acts as a specialization of Person, and
2. RegisteredUser.authorized_reportees/Person.authorized_reporters which is the many-to-many.

With this setup, what would you predict the first name in this code is? The first name of “@person” or the first name of “reporter”?:

for reporter in @person.authorized_reporters
	reporter.person.first_name
end

What I meant it to be was the first name of “reporter” but through the magic that is ActiveRecord what it ended up being was the first name of “@person”. I still don’t know why, but I do know that once I changed the code to this, I got what I wanted:

class RegisteredUser < ActiveRecord::Base
  belongs_to :person
  has_and_belongs_to_many :authorized_reportees, :class_name => 'Person',
        :join_table => 'authorized_reporters',
        :foreign_key => 'authorized_registered_user_id',
        :association_foreign_key => 'authorized_person_id'
end

class Person < ActiveRecord::Base
  has_and_belongs_to_many :authorized_reporters, :class_name =>'RegisteredUser',
        :join_table => 'authorized_reporters',
        :foreign_key => 'authorized_person_id',
        :association_foreign_key => 'authorized_registered_user_id'
  has_one :registered_user
end

I had to explicitly specify the foreign keys and change the names of the database columns from person_id to authorized_person_id. Then everything worked fine. Go figure.

September 4th, 2007

An Explained Absence

by Tim Cull

So my wife’s work was sponsoring a contest to create a Facebook application that promotes their brand in some way. We dragged our feet for a long time and then, at the last minute, decided to create the killer facebook app of the century. I highly encourage you to try it out–otherwise you won’t know what you’re missing.

Seriously, though, we thought of the idea on Tuesday and by Thursday night after a few caffeine-fueled evenings (and early mornings) we had a fully working app. The api is killer and it’s a great platform to spin a quick app on to make a few bucks. The best part is, you instantly get access to a user base of 30 million and counting. No wonder the Wall Street Journal today called it such a promising platform.

So check out my app and add it to your profile. Did I say please? Also, check out the Facebook developer kit. The documentation is pretty spotty, but the API itself is so simple that you can get away with just reading the source code yourself.