Associations and caching

Posted by Brian in Rails, snacks (April 2nd, 2007)

Sometimes I just do dumb things when I write code. The way I look at it, every mistake I make is a chance to learn something new.

I’ve got a system with workshops, presenters, enrollments, and more. It’s a fairly complex system that has a lot of relationships. If you peek into my User model, you’ll see some things like this:


class User < ActiveRecord::Base has_many :presenterships has_many :troubleshooterships has_many :enrollments has_many :presentations, :through=>:presenterships, :source=>:workshop
has_many :troubleshoots, :through=>:troubleshooterships, :source=>:workshop
has_many :workshops, :through=>:enrollments
end

....
end

This post Turn finders into associations and get caching for free got me thinking about my code a bit so I decided to take a second look. When I did, I saw this method:


#Returns all of the workshops for which this user is enrolled.
def workshops_enrolled
@workshops = Workshop.find :all, :include=>[:offering, :enrollments],
:conditions=>["enrollments.user_id = ? and enrollments.withdrew = ?", self.id, false]
end

I added this method because I wanted to make sure I only showed associations where the user did not withdraw. (I’m recording withdrawls from a workshop instead of removing the association between the user and the workshop.)

Darn it… that’s just not right. While that works, I lose the ability to cache, and it’s also exactly what an association is for. Refactored, it now looks like this:


has_many :workshops_enrolled, :source=>:workshop, :include=>[:offering, :enrollments],
:through => :enrollments, :conditions=>["enrollments.withdrew = ?", false]

Since it’s a has_many :through, it needs to have the :source option defined so Rails knows what the parent class is.

Fun stuff, this Rails.

Comments are closed.

Sorry, the comment form is closed at this time.