Mark Gilbert's Blog

Science and technology, served light and fluffy.

Join me, and together we’ll rule… – ActiveRecord and Attributes on Join Classes

I mentioned a couple of weeks ago that other than one notable exception, I was loving Castle ActiveRecord.  That one exception is today’s topic.  I say this is an exception to the statement “I love Castle ActiveRecord” only because I fought with this issue for several weeks* before I figured it out.

Originally, I had two tables – Book and Contributor.  These were joined in a many-to-many relationship in a table called BookContributor.  The first version of BookContributor was purely a join table and therefore only contained keys to the other two.  The Book class had a property called Contributors that had the HasAndBelongsToMany() attribute on it, just as it is shown in this example.  That allowed me to add new contributors to a book using something like “MyBook.Contributors.Add(MyNewContributor)”.  And everything was peachy.

The application that uses these classes shows contributors (authors, editors, etc.) in a list box.  Up to this point they were shown in the order that they were added to the list (I was sorting on the primary key of the BookContributor table).  Now, I wanted to allow the user to rearrange the contributors in any arbitrary way.  That meant I needed to add a field to BookContributor called “SortOrder”.  I added the field, and then hit my first roadblock.  Ok, THE roadblock.

ActiveRecord had been doing a fine job managing the contents of the BookContributor table.  Saying MyBook.Contributors.Add(MyNewContributor) would create the record in BookContributor for me, and wire the up the foreign keys just right.  Now, I wanted to be able to manage the SortOrder field in the join table, so saying MyBook.Contributors.Add(MyNewContributor) wouldn’t cut it anymore.  Since SortOrder was a property of the join table and not the Contributor record itself, I also couldn’t set a property on the MyNewContributor object before invoking the Add method.

I did a search for variations on “ActiveRecord join table property” to find a way to set SortOrder.  One of the most promising posts I found was the ActiveRecord online documentation page for the HasAndBelongsToMany attribute, referenced above.  There is a section titled “Attributes on the Association Table”, which sounded like what I wanted to do.  Their approach was to define an ActiveRecord class based on the join table.  Up to this point I hadn’t needed to do that – ActiveRecord was able to manage the contents of the join table purely from the relationship I had defined between the Book and Contributor classes.

What this post wasn’t clear on, however, was how the Post and Category classes (to use their examples) needed to be adjusted to refer to the new PostCategory class.  After rereading this page several times over, and doing some additional digging on the Internet, I concluded that the Post and Category classes really didn’t refer to the PostCategory class at all.  Attaching a Category to a Post (or conversely, adding a Post to a category) doesn’t set the PostCategory.ArbitraryValue database field.  If you wanted to do anything with ArbitraryValue, you’d have to do it using the PostCategory class.

This is basically the solution I ultimately arrived at.  I would create a class for BookContributor, and instead of saying MyBook.Contributors.Add(MyNewContributor), I would so something like the following:

Dim MyBook As Book
Dim MyContributor As Contributor
Dim NewBC As BookContributor

’ Load up the MyBook and MyContributor objects here

NewBC = New BookContributor
NewBC.Book = MyBook
NewBC.Contributor = MyContributor
NewBC.SortOrder = 2
NewBC.Save()

It’s not nearly as clean as MyBook.Contributors.Add(MyContributor), but it gets the job done.  Additionally, the Contributors property on the Book class still gets populated behind the scenes which allows me to sort on the new SortOrder field, so the only real change from what I had in place before is the process of adding new ones.

* Several weeks averaging roughly 30 minutes per day.  I had a lot going on that month.

Advertisements

January 21, 2010 - Posted by | Castle ActiveRecord, Visual Studio/.NET

1 Comment

  1. Thanks for the information! I was trying to work out how to properly do this. Their documentation on HasAndBelongsToMany is pretty bad.

    Comment by Daniel15 | September 9, 2010


Sorry, the comment form is closed at this time.

%d bloggers like this: