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:0×3c019d0 …>
3 >> info = Email.create(:subject => Latest Schedule,
4 :body => Group schedule: …)
5 => #<Email:0×3bece38 …>
6 >> info.recipients.create(:party => fbos)
7 => #<Recipient:0×3bccfd8 …>
8 >> fbos.emails
9 => [#<Email:0×3b80dc0 …>]

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 francois.beausoleil@gmail.com to tell me about your experiences with asymmetric relationships.

This article is obsolete because it uses features that were replaced many times over. If you want an HABTM selector widget, look at MultipleSelect by Daniel Rodríguez Troitiño.

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 !

This article is obsolete because it uses features that were replaced many times over. If you want an HABTM selector widget, look at MultipleSelect by Daniel Rodríguez Troitiño.

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

Your Host

A picture of me

I am François Beausoleil, a Ruby on Rails and Scala developer. During the day, I work on Seevibes, a platform to measure social interactions related to TV shows. At night, I am interested many things. Read my biography.

Top Tags

Books I read and recommend

Links

Projects I work on

Projects I worked on