Ruby Forum Ruby on Rails > habtm recursion via destroy_without_callbacks

Posted by Eric Soderberg (soderic)
on 31.12.2005 17:45
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:in `destroy_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.
Posted by M Daggett (Guest)
on 02.01.2006 01:33
(Received via mailing list)
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 Soderberg <soderic@earthlink.net> 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
> Rails@lists.rubyonrails.org
> http://lists.rubyonrails.org/mailman/listinfo/rails
>


--
Posted by M Daggett (Guest)
on 02.01.2006 23:45
(Received via mailing list)
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 <heavysixer@gmail.com> 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
> > Rails@lists.rubyonrails.org
> > http://lists.rubyonrails.org/mailman/listinfo/rails
> >
>
>
> --
> --------------------------------------------------------------------
> I am Mark Daggett and I approve this message.
>


--
Posted by Brian Green (Guest)
on 03.01.2006 04:21
(Received via mailing list)
Hi Eric, I'm running into the same problem. Could you provide a little 
more
detail on your workaround? Thanks,

Brian
Posted by Eric Soderberg (soderic)
on 03.01.2006 05:53
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 Green wrote:
> Hi Eric, I'm running into the same problem. Could you provide a little 
> more
> detail on your workaround? Thanks,
> 
> Brian
Posted by Brian Green (Guest)
on 03.01.2006 06:55
(Received via mailing list)
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
Posted by Bryan Corey (Guest)
on 24.05.2006 18:27
(Received via mailing list)
> >
> > 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:in `destroy_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.