Problems with destroy and relationships

Hi all,

I am running into problems with my model relationships and

destroying them. In particular:

class Campaign < ActiveRecord::Base
has_and_belongs_to_many :tags
has_and_belongs_to_many :geographies

class Tag < ActiveRecord::Base
has_and_belongs_to_many :campaigns

class Geographies < ActiveRecord::Base
has_and_belongs_to_many :campaigns

class TagController < ApplicationController

def destroy

tag = Tag.find(:first, :conditions => [“id = ?”,params[:id]])
tag.connection.delete(“DELETE FROM campaigns_tags WHERE tag_id =
'”"’") if tag.connection.execute(“SELECT * FROM
campaigns_tags WHERE tag_id = '”"’")
tag.connection.delete(“DELETE FROM spotprofile_taggings WHERE
tag_id = '”"’") if tag.connection.execute(“SELECT * FROM
spotprofile_taggings WHERE tag_id = '”"’")
redirect_to session[:back_page]

So, I have a symmetric habtm relationship between campaigns and tags,
and campaigns and geographies. Why, when I attempt to “really”
destroy the tag in the next to last line of the controller, do I get
this stack trace?

A SystemStackError occurred in tag#destroy:

stack level too deep
associations/association_proxy.rb:123:in `load_target’


associations/association_proxy.rb:123:in load_target' /usr/lib64/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/ associations/association_collection.rb:104:inlength’
associations/association_collection.rb:64:in clear' (eval):3:indestroy_without_habtm_shim_for_geographies’
(eval):4:in destroy_without_habtm_shim_for_geographies' (eval):4:indestroy_without_callbacks’
callbacks.rb:332:in destroy_without_transactions' /usr/lib64/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/ transactions.rb:122:indestroy’
transaction' /usr/lib64/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/ transactions.rb:91:intransaction’
transactions.rb:118:in transaction' /usr/lib64/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/ transactions.rb:122:indestroy’
associations/association_proxy.rb:110:in send' /usr/lib64/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/ associations/association_proxy.rb:110:inmethod_missing’
destroy' /usr/lib64/ruby/gems/1.8/gems/actionpack-1.12.5/lib/ action_controller/base.rb:941:insend’
[the rest is mongrel and other stuff]

The question is actually two-fold here: 1) How do I get into the
campaigns destroy controller when I have already removed the links in
the habtm table? For that matter, how am I getting there period…
shouldn’t the model’s destroy method be the one called for cascading
destroys? 2) Why am I running into stack overflow errors. Should
there not be a symmetric habtm relationship there? If so how do I
determine which table should habtm? Furthermore, this only happens
sometimes when I destroy a campaign explicitly… sometimes the
destroy works.

try has_many :through as an alternative…

2007/3/6, Clever N. [email protected]:

I’m curious about something. I swear everywhere I look habtm is being
taken out to the shed. Why is that? habtm is a perfectly valid
relation and yet it seems like everyone is always suggesting
has_many :through like it’s a fix all. has_many :through is a very
clever habtm that appears only in situations where you have a class
that has two belongs_to relationships to other classes that also wish
to have a has_many relationship between them. I find myself with
situations using habtm almost exclusively. I’m wondering if I’m just
not doing a good job of modeling by not seeing this extra join model
that should be appearing everywhere I have a habtm or is everyone
else just looking for a way to use the new shiny object?

So to help answer the original question, first off I’d ask why you’re
manually executing all that deletion SQL? If you want to delete a tag
or campaign or whatever, just destroy it. Rails will delete the entry
in the habtm join table for you automatically. If you need to delete
a few of them and have it be atomic put the destroy calls in a
transaction. Use the methods that AR gives you instead of managing it
all yourself. You’re fighting with it instead of letting it help you :slight_smile:

Hope that helps,