In memory delete from an rails Association - a counterpart to build 4

Posted by Tim Connor Tue, 17 Apr 2007 21:15:00 GMT

I don’t like how a lot of the association methods automatically go through to the DB. I like to be able to work with my objects in memory more, get them actually how I want, and then save to the DB. There are times that having instant DB saving go through can really mess with a object that is live on a site. For creation there is such a method: build. And for editing: an update won’t go through until you save it. There isn’t an obvious counterpart for deletion.

I found one by googling around for something else, and noticing people complaining about delete_if not working as they expected. delete_if does exactly what I want, operate on the collection without effecting the DB. Of course, this doesn’t do much good without a way to save it when you are ready. The easiest way I’ve come up with so far is to keep a copy of the initial ids array, and then compare to that later.


class Parent < ActiveRecord::Base
  has_many :children
  attr_accessor :initial_children_ids

  def commit_delete_if_children
    parent.connection.delete <<-SQL, "Delete_ifing children" 
      DELETE FROM children WHERE id IN ('#{(initial_children_ids - children_ids).join('\',\'')}')
    SQL
  end

  protected
  def after_initialize
    self.initial_children_ids = self.children_ids
  end
end

>> dad.children.delete_if { |child| child.id == 3}
>> dad.commit_delete_if_children
=> 1
>> dad.commit_delete_if_children
=> 0