Habtm - stack too deep error

Hi all,

I am trying to create many-to-many relationship between models “Topic”
and “Category”

I am trying following in rails console which gives me exception.

t1 = Topic.new(:title => “t1”)
c1 = Category.new(:name => “c1”)
t1.categories << c1
t1.save
Gives Exception…

Am I doing something really wrong?

Thanks,
Siddharth

Here is my Topic model
class Topic < ActiveRecord::Base
has_and_belongs_to_many :categories,
:class_name => “Category”,
:join_table => “topics_categories”,
:association_foreign_key => “category_id”,
:foreign_key => “topic_id”,
:after_add => :add_topic_to_category,
:after_remove => :remove_topic_from_category

def add_topic_to_category(category)
  category.topics << self unless category.topics.include?(self)
end
def remove_topic_from_category(category)
  category.topics.delete(self) rescue nil
end

end

and Category
class Category < ActiveRecord::Base
has_and_belongs_to_many :topics,
:class_name => “Topic”,
:join_table => “topics_categories”,
:association_foreign_key => “topic_id”,
:foreign_key => “category_id”
end

and topics_categories table
create table topics_categories (
topic_id bigint,
category_id bigint
);

Full stack trace
Loading development environment.

t1 = Topic.new(:title => “t1”)
=> #<Topic:0xb766da88 @new_record=true,
@attributes={“created_on”=>nil, “num_comments”=>nil, “title”=>“t1”,
“updated_on”=>nil, “url”=>“”, “blocked”=>0, “description”=>“”,
“user_id”=>nil, “num_views”=>nil}>
c1 = Category.new(:name => “c1”)
=> #<Category:0xb7614cd0 @new_record=true, @attributes={“name”=>“c1”,
“blocked”=>0, “description”=>“”, “usage_count”=>nil}>
t1.categories << c1
=> [#<Category:0xb7614cd0 @topics=[#<Topic:0xb766da88
@categories=[…], @new_record=true, @attributes={“created_on”=>nil,
“num_comments”=>nil, “title”=>“t1”, “updated_on”=>nil, “url”=>“”,
“blocked”=>0, “description”=>“”, “user_id”=>nil, “num_views”=>nil}>],
@new_record=true, @attributes={“name”=>“c1”, “blocked”=>0,
“description”=>“”, “usage_count”=>nil}>]
t1.save
SystemStackError: stack level too deep
from
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/associations.rb:912:in
validate_associated_records_for_categories' from /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/validations.rb:802:in run_validations’
from
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/validations.rb:800:in
run_validations' from /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/validations.rb:764:in valid_without_callbacks’
from
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/callbacks.rb:310:in
valid?' from /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/associations.rb:918:in validate_associated_records_for_topics’
from
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/associations/association_proxy.rb:110:in
method_missing' from /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/associations/has_and_belongs_to_many_association.rb:81:in method_missing’
from
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/associations.rb:913:in
validate_associated_records_for_topics' from /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/validations.rb:802:in run_validations’
from
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/validations.rb:800:in
run_validations' from /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/validations.rb:764:in valid_without_callbacks’
from
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/callbacks.rb:310:in
valid?' from /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/associations.rb:918:in validate_associated_records_for_categories’
from
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/associations/association_proxy.rb:110:in
method_missing' from /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/associations/has_and_belongs_to_many_association.rb:81:in method_missing’
… 2796 levels…
from
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/callbacks.rb:310:in
valid?' from /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/associations.rb:918:in validate_associated_records_for_categories’
from
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/associations/association_proxy.rb:110:in
method_missing' from /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/associations/has_and_belongs_to_many_association.rb:81:in method_missing’
from
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/associations.rb:913:in
validate_associated_records_for_categories' from /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/validations.rb:802:in run_validations’
from
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/validations.rb:800:in
run_validations' from /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/validations.rb:764:in valid_without_callbacks’
from
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/callbacks.rb:310:in
valid?' from /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/validations.rb:735:in save_without_transactions’
from
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/transactions.rb:126:in
save' from /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/connection_adapters/abstract/database_statements.rb:51:in transaction’
from
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/transactions.rb:91:in
transaction' from /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/transactions.rb:118:in transaction’
from
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/transactions.rb:126:in
`save’
from (irb):4>>

-|[Siddharth] [S] [Karandikar]|-
www.paahijen.com - Applications in Indian Languages!

Siddharth Karandikar wrote:

I am trying to create many-to-many relationship between models “Topic”
and “Category”

Check to ensure that your model file is not being required twice. I have
had this before when the habtm macro is defined twice by accident
because the model was being required twice.

Eric

On 5/22/07, Eric A. [email protected] wrote:

Siddharth Karandikar wrote:

I am trying to create many-to-many relationship between models “Topic”
and “Category”

Check to ensure that your model file is not being required twice. I have
had this before when the habtm macro is defined twice by accident
because the model was being required twice.

Thanks Eric for reply.

I far as I know, Rails handles all the “requires” part, so how should
we add a check there?
Is this rails console specific issue?

  • Siddharth

Eric

-|[Siddharth] [S] [Karandikar]|-
www.paahijen.com - Applications in Indian Languages!

Siddharth Karandikar | Flickr

here is your problem:

from
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/associations.rb:913:in
`validate_associated_records_for_topics’

from
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.4/lib/active_record/associations.rb:913:in
`validate_associated_records_for_categories’

from this i assume you left out the validations from your models in
your post as this suggests you have validates_associated :topics in
your Category model and validates_associated :categories in your Topic
model.

this is a big no-no as is causes exactly what you are experiencing, an
infinite validation loop. when you save your topic it tries to
validate the associated category which then tries to validate the
associated topic which then tries to validate the associated category
and so on.

On 5/22/07, Chris H. [email protected] wrote:

from this i assume you left out the validations from your models in
your post as this suggests you have validates_associated :topics in
your Category model and validates_associated :categories in your Topic
model.

this is a big no-no as is causes exactly what you are experiencing, an
infinite validation loop. when you save your topic it tries to
validate the associated category which then tries to validate the
associated topic which then tries to validate the associated category
and so on.

Thanks Chris for pointing out the real cause. It has to be because of
infinite loop.
But if you see the model classes that I have posted in my first mail,
those doesn’t contain any of these “validates_associated” methods. So
rails is trying to do this validations on its own.

Now the question is, how to tell rails not to validate for these things?

  • सिद्धार्थ [Siddharth]
    [written using www.paahijen.com]
  • Siddharth
    -|[Siddharth] [S] [Karandikar]|-
    www.paahijen.com - Applications in Indian Languages!

Siddharth Karandikar | Flickr

-|[Siddharth] [S] [Karandikar]|-
www.paahijen.com - Applications in Indian Languages!

Siddharth Karandikar | Flickr

Shit,

You really over complicated this.

rename your table to categories_topics and

class Topic < ActiveRecord::Base
has_and_belongs_to_many :categories,
:class_name => “Category”,
:join_table => “topics_categories”,
:association_foreign_key => “category_id”,
:foreign_key => “topic_id”,
:after_add => :add_topic_to_category,
:after_remove => :remove_topic_from_category

becomes

class Topic < ActiveRecord::Base
has_and_belongs_to_many :categories
end

do the same for Category
now run your tests

============================================================

the association was over explicit
rails is based on conformity so you don’t need to configure everything.

On 5/23/07, Keynan P. [email protected] wrote:

:join_table => "topics_categories",
:association_foreign_key => "category_id",
:foreign_key => "topic_id",
:after_add => :add_topic_to_category,
:after_remove => :remove_topic_from_category

becomes

class Topic < ActiveRecord::Base
has_and_belongs_to_many :categories
end

Thanks for showing me the simpler version. But I doubt this will solve
the “stack too deep” issue.

  • Siddharth

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

  • सिद्धार्थ [Siddharth]
    [written using www.paahijen.com] - Applications in Indian Languages!

Siddharth Karandikar | Flickr

I agree with Keynan on this, although I probably would have said it
differently. :slight_smile:

might I suggest that you remove the :after_add callback from the habtm
and see what happens? I don’t see a need to have that callback
because the relationship will exist because you just added it.
doesn’t matter if you create the relationship via Topic or Category,
it’s still the same relationship. same goes for your after_remove
callback. you’d just be trying to remove the relationship you just
removed.

So my suggestion is this

Category < ActiveRecord::Base
has_and_belongs_to_many :topics,
# this line not necessary if you name join table
“categories_topics”
:join_table => “topics_categories”,
:uniq => true
end

Topic < ActiveRecord::Base
has_and_belongs_to_many :categories,
# this line not necessary if you name join table
“categories_topics”
:join_table => “topics_categories”,
:uniq => true
end

try this out and see what happens

Cool. That works!

Hmm … then I need to see why that’s been done in one of the rails
recipes chapter. :slight_smile:
Anyways, thanks guys.

  • Siddharth

On 5/23/07, Chris H. [email protected] wrote:

Topic < ActiveRecord::Base

On 5/23/07, Keynan P. [email protected] wrote:

:join_table => "topics_categories",

  • सिद्धार्थ [Siddharth]
    [written using www.paahijen.com] - Applications in Indian Languages!

Siddharth Karandikar | Flickr