Permalink
Browse files

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.
  • Loading branch information...
1 parent 2f30cdc commit 5d43977c7c76a76adfffdafa3de2e739216dab81 @h-lame h-lame committed with tenderlove Mar 11, 2011
Showing with 12 additions and 10 deletions.
  1. +12 −10 activerecord/lib/active_record/associations.rb
@@ -1411,16 +1411,7 @@ def has_and_belongs_to_many(association_id, options = {}, &extension)
reflection = create_has_and_belongs_to_many_reflection(association_id, options, &extension)
collection_accessor_methods(reflection, HasAndBelongsToManyAssociation)
- # Don't use a before_destroy callback since users' before_destroy
- # callbacks will be executed after the association is wiped out.
- include Module.new {
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
- def destroy # def destroy
- super # super
- #{reflection.name}.clear # posts.clear
- end # end
- RUBY
- }
+ configure_after_destroy_method_for_has_and_belongs_to_many(reflection)
add_association_callbacks(reflection.name, options)
end
@@ -1714,6 +1705,17 @@ def #{method_name}
end
end
+ def configure_after_destroy_method_for_has_and_belongs_to_many(reflection)
+ method_name = :"has_and_belongs_to_many_after_destroy_for_#{reflection.name}"
+ class_eval <<-eoruby, __FILE__, __LINE__ + 1
+ def #{method_name}
+ association = #{reflection.name}
+ association.delete_all if association
+ end
+ eoruby
+ after_destroy method_name
+ end
+
def delete_all_has_many_dependencies(record, reflection_name, association_class, dependent_conditions)
association_class.delete_all(dependent_conditions)
end

0 comments on commit 5d43977

Please sign in to comment.