diff options
author | Murray Steele <muz@h-lame.com> | 2011-03-11 12:02:49 +0000 |
---|---|---|
committer | Aaron Patterson <aaron.patterson@gmail.com> | 2011-03-23 14:45:21 -0700 |
commit | 54c963c89b81cfc4fd7dcad6779e41c85d1180ce (patch) | |
tree | bf7697b0b1899a6fd22cf72f762ae7a9724b7209 /activerecord/lib/active_record/associations | |
parent | 8ee81d21fb103be31adb8e0dcde8ed8f5e90a798 (diff) | |
download | rails-54c963c89b81cfc4fd7dcad6779e41c85d1180ce.tar.gz rails-54c963c89b81cfc4fd7dcad6779e41c85d1180ce.tar.bz2 rails-54c963c89b81cfc4fd7dcad6779e41c85d1180ce.zip |
Make clearing of HABTM join table contents happen in an after_destory callback.
The old method of redefining destroy meant that clearing the HABTM join table would happen as long as the call to destroy succeeded. Which meant if there was a before_destroy that stopped the instance being destroyed using normal means (returning false, raising ActiveRecord::Rollback) rather than exceptional means the join table would be cleared even though the instance wasn't destroyed. Doing it in an after_destroy hook avoids this and has the advantage of happening inside the DB transaction too.
Diffstat (limited to 'activerecord/lib/active_record/associations')
-rw-r--r-- | activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb | 24 |
1 files changed, 12 insertions, 12 deletions
diff --git a/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb b/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb index e40b32826a..4b48757da7 100644 --- a/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb +++ b/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb @@ -7,24 +7,24 @@ module ActiveRecord::Associations::Builder def build reflection = super check_validity(reflection) - redefine_destroy + define_after_destroy_method reflection end private - def redefine_destroy - # Don't use a before_destroy callback since users' before_destroy - # callbacks will be executed after the association is wiped out. + def define_after_destroy_method name = self.name - model.send(:include, Module.new { - class_eval <<-RUBY, __FILE__, __LINE__ + 1 - def destroy # def destroy - super # super - #{name}.clear # posts.clear - end # end - RUBY - }) + model.send(:class_eval, <<-eoruby, __FILE__, __LINE__ + 1) + def #{after_destroy_method_name} + association(#{name.to_sym.inspect}).delete_all + end + eoruby + model.after_destroy after_destroy_method_name + end + + def after_destroy_method_name + "has_and_belongs_to_many_after_destroy_for_#{name}" end # TODO: These checks should probably be moved into the Reflection, and we should not be |