Here’s another gotcha that I ran into that’s kind of an edge case in Rails. So I’m documenting it, so that the rest of you can go about your business of building great apps, instead of scratching your heads. So what was I doing? I wanted a self-referential join table with rich associations for an “acts_as_friendable” plugin I was writing.
I made table in database as follows:
create_table "friendships", :force => true do |t|
t.column "owner_id", :integer, :null => false
t.column "friend_id", :integer, :null => false
In the model, put:
class Friendship < ActiveRecord::Base
belongs_to :owner, :class_name => "User", :foreign_key => :owner_id
belongs_to :friend, :class_name => "User", :foreign_key => :friend_id
Then in the table that you want to act as friendable, you put:
class User < ActiveRecord::Base
And that’s it. you can now access friends() and friendships() of a person.
However, it doesn’t work when you try to push the association through, like:
user = User.find(1)
friend = User.find(2)
user.friends << friend
It will fail complain about how “user_id” doesn’t exist in any of the tables. I was scratching my head for a good 2 hours before I figured that it wasn’t actually me this time. I think the << method doesn't correctly use the foreign keys correctly when they're non-standard like this. According to #6466 ([PATCH] fix for has_many :through push and delete with legacy/non-standard foreign_keys), this doesn’t work, until a patch is written for it. I’m not as familiar with the Rails code base as I should be. This is probably a good chance to get started looking at it…unless someone else fixes it first…
As a workaround, I simply used the Friendship ActiveRecord object directly to create the association. I’ll have to override the method in the plugin so that it allows correct use of << for my specific case. Tip!