# Site Navigation With Polymorphic Has Many Through

**URL:** <https://www.ruby-forum.com/t/site-navigation-with-polymorphic-has-many-through/189167>\
**Category:** Rails\
**Created:** [May 25, 2010, 9:30pm UTC](https://www.ruby-forum.com/t/site-navigation-with-polymorphic-has-many-through/189167 "2010-05-25T21:30:55Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![jcain](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/3d9bf3/32.png) [@jcain](https://www.ruby-forum.com/u/jcain)\
**Post date:** [May 25, 2010, 9:30pm UTC](https://www.ruby-forum.com/t/site-navigation-with-polymorphic-has-many-through/189167/1 "2010-05-25T21:30:55Z")

</div>

Hi, seem to keep running into a wall here. I can’t find any resources on  
site navigation that can deal with any model being in the nav, allow  
nesting, and can dynamically update.

So I thought about it for a while, and decided on a MenuItems class,  
which  
contained the position of the child in relation to it’s siblings, where  
the  
parent and the child were polymorphic. Then a given childable object can  
find it’s parentable by going through the menu\_items table.

I want my nav to be able to do things like this:  
–Category1  
----SubCategory1  
------Product1  
------Product2  
----Product3  
–Category2  
----Product4  
–Page1  
–Page2  
–Page3

This is the current setup:

MODELS

class MenuItem \< ActiveRecord::Base  
belongs\_to :childable , :polymorphic =\> true  
belongs\_to :parentable , :polymorphic =\> true

acts\_as\_list :scope =\> :parentable\_id  
end

class Category \< ActiveRecord::Base  
has\_one :parent\_menu\_item , :as =\> :parentable , :class\_name =\>  
‘MenuItem’  
has\_many :child\_menu\_items , :as =\> :childable , :class\_name =\>  
‘MenuItem’

has\_one :parentable , :through =\> :parent\_menu\_item  
has\_many :childables , :through =\> :child\_menu\_items  
end

class SubCategory \< ActiveRecord::Base  
has\_many :child\_menu\_items , :as =\> :childable , :class\_name =\>  
‘MenuItem’  
has\_one :parent\_menu\_item , :as =\> :parentable , :class\_name =\>  
‘MenuItem’

has\_one :parent , :through =\> :parent\_menu\_item  
has\_many :children , :through =\> :child\_menu\_items  
end

class Page \< ActiveRecord::Base  
has\_one :parent\_menu\_item , :as =\> :parentable , :class\_name =\>  
‘MenuItem’  
has\_one :parent , :through =\> :parent\_menu\_item  
end

SCHEMA:  
ActiveRecord::Schema.define(:version =\> 20100525184637) do

create\_table “categories”, :force =\> true do |t|  
t.datetime “created\_at”, :null =\> false  
t.datetime “updated\_at”, :null =\> false  
end

create\_table “menu\_items”, :force =\> true do |t|  
t.integer “position”, :null =\> false  
t.integer “parentable\_id”, :null =\> false  
t.string “parentable\_type”, :null =\> false  
t.integer “childable\_id”, :null =\> false  
t.string “childable\_class”, :null =\> false  
t.datetime “created\_at”, :null =\> false  
t.datetime “updated\_at”, :null =\> false  
end

create\_table “pages”, :force =\> true do |t|  
t.datetime “created\_at”, :null =\> false  
t.datetime “updated\_at”, :null =\> false  
end

create\_table “sub\_categories”, :force =\> true do |t|  
t.datetime “created\_at”, :null =\> false  
t.datetime “updated\_at”, :null =\> false  
end

end

I have had a lot of trouble with it, this is the best I’ve gotten so  
far,  
but I am still getting the error:  
ActiveRecord::HasManyThroughAssociationPolymorphicError: Cannot have a  
has\_many :through association ‘Category#childables’ on the polymorphic  
object ‘Childable#childable’.

Is there a way to make this work? Is there a better way to do this?

---

<div class="post-metadata">

**Author:** ![jcain](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/3d9bf3/32.png) [@jcain](https://www.ruby-forum.com/u/jcain)\
**Post date:** [May 26, 2010, 10:22am UTC](https://www.ruby-forum.com/t/site-navigation-with-polymorphic-has-many-through/189167/2 "2010-05-26T10:22:57Z")

</div>

Josh,  
We’re doing something similar, except that instead of using childable  
and parentable, we’re using awesome\_nested\_set. It enables you to  
have sub\_categories within sub\_categories, etc., and its interface is  
pretty intuitive and efficient:

[http://wiki.github.com/collectiveidea/awesome\_nested\_set/awesome-nested-set-cheat-sheet](http://wiki.github.com/collectiveidea/awesome_nested_set/awesome-nested-set-cheat-sheet)

Tilde E.

---

<div class="post-metadata">

**Author:** ![jcain](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/3d9bf3/32.png) [@jcain](https://www.ruby-forum.com/u/jcain)\
**Post date:** [May 26, 2010, 11:50am UTC](https://www.ruby-forum.com/t/site-navigation-with-polymorphic-has-many-through/189167/3 "2010-05-26T11:50:46Z")

</div>

On Wed, May 26, 2010 at 3:09 AM, Tilde E. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> Tilde E.  
> the
> 
> > ----Product4  
> > belongs\_to :parentable , :polymorphic =\> true  
> > has\_one :parentable , :through =\> :parent\_menu\_item  
> > has\_many :children , :through =\> :child\_menu\_items
> > 
> > ```
> > t.string "childable_class", :null => false
> > t.datetime "created_at", :null => false
> > 
> > ```
> 
> [http://groups.google.com/group/rubyonrails-talk?hl=en](http://groups.google.com/group/rubyonrails-talk?hl=en).

I appreciate the suggestion, I had previously used awesomer nested set  
on a  
project. I had two issues with it. The first was that the reason for  
using  
it was so that you could query for any level of children with one db  
query,  
but when I then went to ask each element for it’s children, I found that  
it  
was re-querying, so this purpose was unrealized. (possibly this  
behaviour  
has been resolved?)

The way to get around it was to transform the results into something  
usable,  
ie hashes of hashes, or arrays of arrays, etc. But this was not provided  
by  
the plugin, and coupled a lot of code. In the end, I spent about 8 hours  
writing a method that would iterate through the results one time,  
accepting  
lambdas for what to do before entering a deeper level, after leaving it,  
and  
what should be done to display a single element. It got pretty ugly, and  
may  
have been an example of premature optimization, probably caching would  
have  
made the large number of database queries irrelevant, but the real  
reason I  
had to do that at all was to mimic a tree like structure, which is what  
a  
many to many association already provides.

So I don’t really see much benefit to the nested sets data structure.  
Also,  
I’m not sure how well it integrates with polymorphism. In my case,  
Categories and SubCategories will have different attributes, and Pages  
will  
be drastically different than either of these. They all need to be in  
the  
navigation. In my previous attempt, I queried for each object that the  
menu  
item was representing, but again, that seems inefficient. To be fair,  
though, when I tried last, i was still very new to Ruby and Rails.

I thought a polymorphic has\_many :through would keep things clean, give  
me  
the tree structure I need for creating nested

 in my html, and dry  
up  
the associations between elements. Of course, it doesn’t have the  
inherent  
ordering that nested sets do, which is why I also have acts\_as\_list  
positions on the join table.

At present, I’m probably going to give this plugin a try:  
[http://github.com/fauna/has\_many\_polymorphs/tree/bcd9626411c9d0658ab527f1e6a0d0622e4f6e15](http://github.com/fauna/has_many_polymorphs/tree/bcd9626411c9d0658ab527f1e6a0d0622e4f6e15)

If it goes well, I’ll report back here.  
If my above statements represented an incorrect assessment, please  
correct  
me.  
If there is some obvious solution that I am missing, please guide me to  
it.

-Josh
