IdolHands.com :: Days in the Life of an Alpha Geek
I'm in the midst of refactoring an application, and I split one of my models into subclasses using single table inheritance. The model in question uses better_nested_set, and I was surprised to find my tests failing when I made the STI switch.
The issue came down to one of scoping, and there was no clear way out of the woods.
I won't go into the specifics of my models, but I'll provide an example that demonstrates the problem.
Create a base class (let's call it Category:
# category.rb
class Category < ActiveRecord::Base
acts_as_nested_set
end
Now define your subclasses:
# foo_category.rb
class FooCategory < Category
end
and
# bar_category.rb
class BarCategory < Category
end
Hop on over to script/console, and do the following:
>> (0..4).each{|i| FooCategory.create(:name => "foo_#{i}")}
=> 0..4
>> FooCategory.count
=> 5
>> (0..4).each{|i| BarCategory.create(:name => "bar_#{i}")}
=> 0..4
>> BarCategory.count
=> 5
Everything looks good so far. But now try invoking a Better Nested Set method from the context of one of the subclasses, and you get something very unexpected:
>> FooCategory.roots.size
=> 10
>> BarCategory.roots.size
=> 10
Things got even worse when I tried to chain .roots onto a named_scope:
>> FooCategory.published.size
=> 0
>> FooCategory.published.roots.size
=> 10
Note that the number remained the same regardless of the output of the named scope; even when none of the FooCategory objects had the published attribute set to true, I would get the same count from the chained roots method.
I tried various options in the :scope arguments in the acts_as_nested_set declaration before I arrived at the perfect solution. Here's what you need to do. In Terminal, navigate to the root of your Rails application. Then type the following:
rm -rf vendor/plugins/better_nested_set
script/plugin install git://github.com/collectiveidea/awesome_nested_set.git
Brandon Keeper's awesome_nested_set plugin is a drop-in replacement for better_nested_set that just works. After installing it, I didn't have to change any code at all to make things work as expected. All my tests passed the first time around. Thanks, Brandon!