« Using a Single Development Database For all Rails Applications | Main | Publishing My Rails Plugins »

Auto-Generate Foreign-Key Constraints in Rails

Listen to this articleListen to this article

I literally just lobbed into my hotel room in Oslo after 30+ hours in transit. (I left home @ 12:30pm on Monday 15th and arrived here @ 21:30 on Tuesday 16th Melbourne time.) It's my first time in Scandinavia and so far I'm loving it. The people are friendly (and *ahem* rather attractive I must say) and I'm hanging out to try some scandinavian beer!

So anyways, after resisting the temptation to turn on my laptop, I finally caved and whipped up a little bit of code to auto-generate foreign-key relationships for migration scripts:

module ActiveRecord
  module ConnectionAdapters
    class ColumnDefinition
      alias nofk_to_sql :to_sql
      def to_sql
        name.to_s =~ /(.*)_id$/ ? "#{nofk_to_sql} REFERENCES #{Migrator.proper_table_name($1)} (id)" : nofk_to_sql
      end
      alias to_s :to_sql
    end
  end
end

The code assumes that if you have a column named customer_id in say an orders table, then you want a foreign key to the id column in the customers table. That doesn't handle situations where you have multiple foreign keys to the same table but...meh...I don't have models that sophisticated yet so bite me :)

Just looking back on it now, it was so trivial to implement that there is more syntactic noise than actual code. Hmmmm.

Update: the plugin is now available in downloadable form and supports a :references option for multiple columns or columns that aren't named for the table they reference.

Comments

I haven't yet played with this, but I'll throw out the idea that perhaps you can add another parameter to the column method allowing you to specify how to resolve the foreign key, perhaps something like this:

table.column :from_user_id, :integer, :treat_fkey_as => 'user_id'
table.column :to_user_id, :integer, :treat_fkey_as => 'user_id'

OK, I'm trying to play with it now but I can't figure out how to load it. I created a plug-in for it and require'd it from environment.rb, but it seems that file isn't loaded for rake'ing migrations. Please explain how to apply this change. Thanks.

Ok, so I was lazy and didn't publish it as a plugin. I'm doing that now and will upload it shortly. Now that I've had 12+ hours sleep :)

The plugin is now available in downloadable form from: http://www.redhillonrails.org/

Post a comment