41

How do you remove a HABTM associated item without deleting the item itself?

For example, say I have 3 Students that are in a Science class together. How do I remove the Science objects from the StudentsClasses table without deleting the actual Science reference? I'm guessing that Student.Classes.first.delete isn't a good idea.

I'm using JavaScript with drag-and-drop for adding and removing, not check boxes. Any thoughts?

Makoto
  • 104,088
  • 27
  • 192
  • 230
humble_coder
  • 2,777
  • 7
  • 34
  • 46

2 Answers2

61

I tend to use has_many :through, but have you tried

student.classes.delete(science)

I think needing to have the target object, not just the ID, is a limitation of HABTM (since the join table is abstracted away for your convenience). If you use has_many :through you can operate directly on the join table (since you get a Model) and that lets you optimize this sort of thing into fewer queries.

def leave_class(class_id)
  ClassMembership.delete(:all, :conditions => ["student_id = ? and class_id = ?", self.id, class_id)
end

If you want the simplicity of HABTM you need to use

student.classes.delete(Class.find 2)

Also, calling a model "Class" is a really bad idea. Use a name that isn't part of the core of Ruby!

Sauce McBoss
  • 6,567
  • 3
  • 20
  • 22
Michael Sofaer
  • 2,927
  • 24
  • 18
  • Well the way it is currently set up, I must use params[:class_id] to perform Class.find_by_id then use the found class to do that. It would be nice if I could just say "Student.class_ids.remove[2]". – humble_coder Jul 07 '09 at 03:57
  • That's the sort of think you need has_many :through for. Updated the answer to reflect that. – Michael Sofaer Jul 07 '09 at 04:33
0

If you want to delete multiple associated items you can use * and write:

student.classes.delete(*classes_array)
GEkk
  • 1,336
  • 11
  • 20