views:

79

answers:

3

Hi,

I have the following situation

class RecordA
  has_many :recordbs
end

class RecordB
  belongs_to :recorda
end

RecordA has many recordbs but only one of them may be an active recordb. I need something like myRecordA.active_recordb

If I add a new column like is_active to RecordB, then I have the potential problem of setting two records to is_active = true at the same time.

Which design pattern can I use?

Thanks!

+1  A: 

You can define a class method on RecordB for this:

class RecordB < ActiveRecord::Base
  def self.active
    first(:conditions => { :active => true }
  end
end
Ryan Bigg
+2  A: 

Let's change your example. There's a LectureRoom, with many People and only one Person can be the instructor.

It'd be much easier to just have an attribute in the LectureRoom to indicate which Person is the instructor. That way you don't need to change multiple People records in order to swap the instructor. You just need to update the LectureRoom record.

Jim
absolutely agreed.
Peter
+1  A: 

I would use a named scope to find the active lecturer.

class Person
  named_scope :currently_speaking, :conditions => {:active => true}
end

Then I would call that a lecturer in ClassRoom:

class ClassRoom
  def lecturer
    people.currently_speaking.first
  end
end

The real problem is making sure that when you activate someone else, they become the only active person. I might do that like this:

class Person
  belongs_to :class_room

  before_save :ensure_one_lecturer

  def activate!
    self.active = true
    save
  end

  def ensure_one_lecturer
    if self.active && changed.has_key?(:active)
      class_room.lecturer.update_attribute(:active, false)
    end
  end

end

This way everything is done in a transaction, it's only done if you've changed the active state, and should be pretty easily tested (I have not tested this).

BJ Clark
Also, I should add, you may need to use a lock on the people table when doing this or you could see a race condition when activating people.
BJ Clark