On Wed, May 26, 2010 at 3:09 AM, Tilde Equals <[email protected]> wrote:

> 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
>
>
> Tilde Equals
>
>
> On May 25, 12:29 pm, Josh Cheek <[email protected]> wrote:
> > 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?
>
> --
> You received this message because you are subscribed to the Google Groups
> "Ruby on Rails: Talk" group.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected]<rubyonrails-talk%[email protected]>
> .
> For more options, visit this group at
> 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 <ul> 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

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

-- 
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Talk" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-talk?hl=en.

Reply via email to