In Rails, there are no requirements that both sides of an association be symmetric. In fact, I often find it useful to have asymmetric relationships.
For example, I’m building a mass-mailer. I have parties (people), emails and recipients. Emails are habtm with regards to parties. Since my join table contains other fields besides the two foreign keys, I need a real model for it.
Examine the following code:
1 class Email < ActiveRecord::Base 2 has_many :recipients 3 end 4 5 class Party < ActiveRecord::Base 6 has_and_belongs_to_many :emails, 7 :join_table => 'recipients' 8 end 9 10 class Recipient < ActiveRecord::Base 11 belongs_to :email 12 belongs_to :party 13 14 def read! 15 self.toggle!(:read) 16 end 17 end
The above models give rise to the following very natural code:
1 >> fbos = Party.find_by_login('fbos') 2 => #<Party:0x3c019d0 ...> 3 >> info = Email.create(:subject => 'Latest Schedule', 4 :body => 'Group schedule: ...') 5 => #<Email:0x3bece38 ...> 6 >> info.recipients.create(:party => fbos) 7 => #<Recipient:0x3bccfd8 ...> 8 >> fbos.emails 9 => [#<Email:0x3b80dc0 ...>]
If access to read or unread E-Mail is needed, the habtm association can be declared more than once, with conditions that discriminate between the different states:
1 class Party < ActiveRecord::Base 2 has_and_belongs_to_many :unread_emails, 3 :join_table => 'recipients', 4 :conditions => 'read = 0' 5 has_and_belongs_to_many :read_emails, 6 :join_table => 'recipients', 7 :conditions => 'read = 1' 8 end
Please comment or send me an E-Mail at firstname.lastname@example.org to tell me about your experiences with asymmetric relationships.