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
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.
@workshops = Workshop.find :all, :include=>[:offering, :enrollments],
:conditions=>["enrollments.user_id = ? and enrollments.withdrew = ?", self.id, false]
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.