views:

22

answers:

2

Quick question (I think). I have users, and I would like to allow them to send messages to one another. My question is, should I have a user table, a message table, and a users to messages join table, or should I just store to_user_id and from_user_id in the messages table. If the latter, what would the association look like for that? Can you even reference a 'local' key for an association?

+2  A: 

You can do that with a couple of simple has_many associations. Since it's self-referential, you'll need to override some of the Rails magic to make it work.

class User < ActiveRecord::Base
  has_many :sent_messages, :class_name => 'Message', :foreign_key => 'sender_id'
  has_many :received_messages, :class_name => 'Message', :foreign_key => 'recipient_id'
end

class Message < ActiveRecord::Base
  belongs_to :sender, :class_name => 'User'
  belongs_to :recipient, :class_name => 'User'
end

Rails doesn't have a cleaner way to doing self-referential associations that I know of.

Adam Lassek
this does work correctly, thank you i will be implementing it. i am still curious as to whether this is the railsiest way to do this?
re5et
also, if there were a different key than sender_id and recipient_id that you wanted to reference in Message, is there some fancy tricky way to define a "local" key?
re5et
@re5et Yes, that would be `:primary_key`
Adam Lassek
A: 

I think the latter sounds fine. This is just off the top of my head but I know AR's associations have options like this...

class Message < ActiveRecord::Base
  belongs_to :sender, :class_name => :user, :foreign_key => :from_user_id
  belongs_to :recipient, :class_name => :user, :foreign_key => :to_user_id
  #...
end

class User < ActiveRecord::Base
  has_many :received_messages, :class_name => :message, :foreign_key => :to_user_id
  has_many :sent_messages, :class_name => :message, :foreign_key => :from_user_id
end
centipedefarmer
the belongs_to associations in Message here won't work, right? Those keys are not foreign, but are local to Message.
re5et