Habtm recursion via destroy_without_callbacks


#1

I am having a problem with two models that each have a HABTM
relationship to the other. For example:

CREATE TABLE people (id INT, name TEXT);
CREATE TABLE teams (id INT, name TEXT);
CREATE TABLE people_teams (person_id INT, team_id INT);

The person model has:

has_and_belongs_to_many :teams

And the team model has:

has_and_belongs_to_many :people

The trouble comes when trying to destroy something, I end up with a
recursive stack sequence that looks something like:

(eval):7:in destroy_without_habtm_shim_for_teams' (eval):9:indestroy_without_habtm_shim_for_teams’
(eval):9:in `destroy_without_callbacks’

This appears to be due to something in associations.rb where the
association array is cleared as part of destroying the record. What
appears to be happening is that when person.rb is loaded, its HABTM
causes team.rb to be loaded which ends up reloading person.rb? I’ve
added some instrumentation that shows that the
destroy_without_habtm_shim_for_teams method ends up being added twice.
This causes recursion when the record is destroyed. I’ve worked around
this by embedding this method aliasing inside an “unless
method_defined?()” to prevent the recursive situation. However, I’m
suspecting that I’m missing something else obvious.

I am using activerecord 1.13.2 and rails 1.0.0.


#2

I am having the same problem. I think that it has something to do with
mysql. As of yet, I have no solutions for the problem.

On 12/31/05, Eric S. removed_email_address@domain.invalid wrote:


suspecting that I’m missing something else obvious.

I am using activerecord 1.13.2 and rails 1.0.0.


Posted via http://www.ruby-forum.com/.


Rails mailing list
removed_email_address@domain.invalid
http://lists.rubyonrails.org/mailman/listinfo/rails


#3

There is also a post about this on railsweenie
http://rails.techno-weenie.net/question/2005/12/23/how_to_destroy_from_model_unit_tests_for_has_and_belongs_to_many

On 1/1/06, M Daggett removed_email_address@domain.invalid wrote:

CREATE TABLE people_teams (person_id INT, team_id INT);
recursive stack sequence that looks something like:
added some instrumentation that shows that the


Rails mailing list
removed_email_address@domain.invalid
http://lists.rubyonrails.org/mailman/listinfo/rails

I am Mark Daggett and I approve this message.


#4

Brian,

I changed the implementation of has_and_belongs_to_many() in
associations.rb
(gems/1.8/gems/activerecord-1.13.2/lib/active_record/associations.rb) to
check for the existence of the shim method:

    # Don't use a before_destroy callback since users' 

before_destroy
# callbacks will be executed after the association is wiped out.
old_method =
“destroy_without_habtm_shim_for_#{association_name}”
unless method_defined?(old_method) # !!!
class_eval <<-end_eval
alias_method :#{old_method}, :destroy_without_callbacks
def destroy_without_callbacks
#{association_name}.clear
#{old_method}
end
end_eval
end # !!!

I added the two lines with ‘# !!!’.

This feels more like a band-aid than a fix since I would expect this
has_and_belongs_to_many call to not occur twice to begin with. Just
haven’t had time track it down further yet.

Eric

Brian G. wrote:

Hi Eric, I’m running into the same problem. Could you provide a little
more
detail on your workaround? Thanks,

Brian


#5

Hi Eric, I’m running into the same problem. Could you provide a little
more
detail on your workaround? Thanks,

Brian


#6

The trouble comes when trying to destroy something, I end up with a
recursive stack sequence that looks something like:

(eval):7:in destroy_without_habtm_shim_for_teams' (eval):9:indestroy_without_habtm_shim_for_teams’
(eval):9:in `destroy_without_callbacks’

I am using activerecord 1.13.2 and rails 1.0.0.

The problem is rails 1.0. It’s been documented in a bug ticket. Upgrade
to 1.1.2
to fix the issue.

I got my issue fixed yet now I still can’t do destroy via unit or
functional
tests without getting the same issue again.


#7

Thanks, Eric, I’ll try this out. (Band-aid, perhaps, but if it works…)

Looks like this: http://dev.rubyonrails.org/ticket/3175 might be the
same
issue?

Brian