New on edge: inferred foreign key name change

— July 17, 2007 at 01:58 PDT


Here's a change that has been a long time coming. (Really. The first time I heard DHH mention he wanted to do this was in March of 2006.) I liked it so much that I've been playing shepherd for it to make sure it happens. So if you're on edge, now is the time.

In 1.2.x and previous, the name of the foreign key of a belongs_to association is inferred to be the name of the association's class plus "_id". The class is inferred to be the camel-case equivalent of the association name, so in the simple case the foreign key ends up the same as the association name plus that "_id". For example: :line_item >> LineItem >> line_item_id. But if you explicitly set the class to something other than the default, the foreign key got inferred from the class instead of the association name. Example: :manager <> Employee >> employee_id.

Pre 2.0:

class Employee < ActiveRecord::Base
  belongs_to :manager, :class_name => "Employee", :foreign_key => "manager_id"
  has_many :employees, :foreign_key => "manager_id"
end

As of now (and thus in 2.0), when the class is explicitly set, the foreign key will be inferred from the association name instead of the class. For example: :manager <> Employee >> manager_id.

In edge/2.0:

class Employee < ActiveRecord::Base
  belongs_to :manager, :class_name => "Employee"
  has_many :employees, :foreign_key => "manager_id"
end

Why is this an improvement? Oh, it just saves a little typing.

class Article < ActiveRecord::Base
  belongs_to :creator, :class_name => "User"
  belongs_to :updater, :class_name => "User"
end

class User < ActiveRecord::Base
  has_many :creations, :class_name => "Article", :foreign_key => "creator_id"
  has_many :updates,   :class_name => "Article", :foreign_key => "updater_id"
end

Notice that you still need to be explicit about the foreign key name in the has_one or has_many associations. It would be a little nicer to be able to say something like :using => :creator in the has_many, but for now that's just a pipe dream.

6 commentsassociations, edge, rails

Comments
  1. Matt2007-07-17 02:42:20

    Nice. I've been tripped up by this before and always thought it was intuitive. I knew the change was coming, glad to see it in place!

  2. Sean2007-07-17 03:21:28

    Yeah, when I got those deprecation warnings, I would always say "DUH!" It sometimes even warns if you specify the foreign key.

  3. John Nunemaker2007-07-18 15:12:47

    Very, nice. I'm a big fan of this.

  4. Mike Stramba2007-07-25 18:38:36

    Josh,

    I'm commenting re: (since your comments have expired now for that article (any reason you don't have unlmited expiry dates for commenting ? .. but I digress)

    http://blog.hasmanythrough.com/2006/4/21/self-referential-through

    Even after perusing the Wikipedia article on digraphs, I still can't figure out how to use the code you posted.

    http://en.wikipedia.org/wiki/Graph%28mathematics%29#Directedgraph

    If you could post a brief console session or an example using a less "esoteric / math oriented" example for math dummies like me that would be great.

    Mike

  5. Joe Magan2007-07-31 09:50:16

    Thanks a lot. Now it will be more comfortable.

  6. Learning2007-09-08 11:00:43

    Hi Josh,

    I have read your article on http://blog.hasmanythrough.com/2006/05/06/through-gets-uniq.

    I wish to post a comment for the page, but when I click on "Leave a response". The comment form for entry is not displayed. Does this mean that that page is no longer accepting comments?

    I have a question, which I hope anyone who is able to help could assist me. Thanks.

    With reference to the example on http://blog.hasmanythrough.com/2006/05/06/through-gets-uniq:

    I have this scenario: Based on a book's id, I want to display all the contributors (who contribute to this book) with the respective role each of these contributors plays?

    Example: Book = Agile Web Development with Rails. List of Contributors:

    1. Dave, as Editor.
    2. Emma, as Proofreader. .. and so on.

Sorry, comments for this article are closed.