Asymmetric associations

February 14th, 2006

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Email < ActiveRecord::Base
  has_many :recipients
end

class Party < ActiveRecord::Base
  has_and_belongs_to_many :emails,
      :join_table => 'recipients'
end

class Recipient < ActiveRecord::Base
  belongs_to :email
  belongs_to :party

  def read!
    self.toggle!(:read)
  end
end
The above models give rise to the following very natural code:
1
2
3
4
5
6
7
8
9
>> fbos = Party.find_by_login('fbos')
=> #<Party:0x3c019d0 ...>
>> info = Email.create(:subject => 'Latest Schedule',
            :body => 'Group schedule: ...')
=> #<Email:0x3bece38 ...>
>> info.recipients.create(:party => fbos)
=> #<Recipient:0x3bccfd8 ...>
>> fbos.emails
=> [#<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
2
3
4
5
6
7
8
class Party < ActiveRecord::Base
  has_and_belongs_to_many :unread_emails,
      :join_table => 'recipients',
      :conditions => 'read = 0'
  has_and_belongs_to_many :read_emails,
      :join_table => 'recipients',
      :conditions => 'read = 1'
end

Please comment or send me an E-Mail at francois.beausoleil@gmail.com to tell me about your experiences with asymmetric relationships.

I just uploaded a new version of the HABTM Helper Plugin. No new features, except it now works…

There was a bug which would cause an error when the selected elements were not updated by the end-user. All the IDs were bunched together, instead of being separated by commas.

This is an artifact of the fact that the view helper was not built using behavioral driven development.

Anyway, it now all works, and is in production on two projects of mine.

Hope it helps someone !

I just wrote another plugin: habtm_helper_plugin. This plugin will generate HTML code to manage has_and_belongs_to_many relationships.

What does it look like ? See here:

HABTM generated manager

Release 0.1.0 is up for grabs, in one of four ways:
  • svn propset http://opensvn.csie.org/habtm_helper_plugin/tags/0.1.0 svn:externals vendor/plugins WARNING: Destructive if you already set other externals
  • script/plugin http://opensvn.csie.org/habtm_helper_plugin/tags/0.1.0
  • svn export http://opensvn.csie.org/habtm_helper_plugin/trunk vendor/plugins/habtm_helper/tags/0.1.0
  • Download habtm-helper-plugin-0.1.0.zip

Full documentation in source. If you want to know, the filter was developed using RSpec. I wrote a lenghty article on my experience using Behavioral Driven Design at Building a plugin on RSpec

The project is hosted on OpenSVN. The project and Trac wiki/bug database is available at the habtm_helper_plugin project home page.

 

Search

A picture of me

I am François Beausoleil, a Ruby on Rails coder. During the day, I work on XLsuite. At night, I am interested many things. Read my biography

Tags

(3) (1) (0) (2) (1) (1) (2) (2) (1) (2) (1) (2) (1) (2) (1) (1) (1) (1) (2) (14) (1) (1) (1) (1) (2) (1) (1) (2) (0) (1) (2) (1) (3) (1) (1) (1) (1) (1) (1) (0) (3) (2) (1) (2) (2) (1) (3) (2) (8) (8) (9) (12) (1) (1) (3) (1) (1) (1) (1) (1) (1) (2) (2) (2) (1) (1) (3) (1) (3) (1) (0) (23) (1) (1) (0) (1) (1) (1) (23) (25) (1) (1) (13) (1) (1) (2) (3) (1) (1) (4) (1) (2) (3) (0) (1) (7) (3) (1) (5) (5) (2) (2) (2) (4) (6) (7) (1) (0) (1) (1) (2) (2) (1) (4) (12) (2) (1) (2) (4) (1) (1) (1) (2) (8) (2) (3) (2) (2) (1) (3) (1) (1)

Links

Projects I work on

Categories

Archives