I have a menu, that is hierarchical and stored according to nested set model. i want to do this to have each "level" ordered alphabetically, like this: -country --Andorra --Belgium --Norway --Sweden -food --English --Swedish --Thai In the example Country and Food must be ordered alphabetically, inside country those countries must be ordered alphabetically and the cuisines within food must be ordered alphabetically. Is that possible? Hope for help! -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
marek wrote:> I have a menu, that is hierarchical and stored according to nested set > model. i want to do this to have each "level" ordered alphabetically, > like this: > > -country > --Andorra > --Belgium > --Norway > --Sweden > -food > --English > --Swedish > --Thai > > In the example Country and Food must be ordered alphabetically, inside > country those countries must be ordered alphabetically and the cuisines > within food must be ordered alphabetically. > > Is that possible? > > Hope for help!It depends a bit on how you are storing the menu items. If they are all in one multi-dimensional array, try this: a = [["4","3","2","1"],["2","3","1"]] => [["4","3","2","1"],["2","3","1"]] a.collect{|x| x.sort} => [["1","2","3","4"],["1","2","3"]] -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Andrew Skegg wrote:> marek wrote: >> I have a menu, that is hierarchical and stored according to nested set >> model. i want to do this to have each "level" ordered alphabetically, >> like this: >> >> -country >> --Andorra >> --Belgium >> --Norway >> --Sweden >> -food >> --English >> --Swedish >> --Thai >> >> In the example Country and Food must be ordered alphabetically, inside >> country those countries must be ordered alphabetically and the cuisines >> within food must be ordered alphabetically. >> >> Is that possible? >> >> Hope for help! > > It depends a bit on how you are storing the menu items. > > If they are all in one multi-dimensional array, try this: > > a = [["4","3","2","1"],["2","3","1"]] > => [["4","3","2","1"],["2","3","1"]] > a.collect{|x| x.sort} > => [["1","2","3","4"],["1","2","3"]]i''m storing it with create the category and then add it to a root or parent category so i have for example root -country --andorra --norway --belgium -food --thai --english i retrieve all them (to use with a select) with Category.find(:all, :order => "lft").map{|category| ["-" * category.depth + category.name, category.id]} and i have something like: [["root", 4], ["-contry", 5], ["--andorra", 7], ["--norway", 11], ["--belgium", 12], ["-food",14], ["--thai", 15], ["--english", 18]] how can i get them, like your example, in a multidimensional array? -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
cover wrote:> and i have something like: [["root", 4], ["-contry", 5], ["--andorra", > 7], ["--norway", 11], ["--belgium", 12], ["-food",14], ["--thai", 15], > ["--english", 18]] > how can i get them, like your example, in a multidimensional array?Your function is returning an array comprised of 2 dimensional arrays (the formatted menu item and the id). This make it a little tricky to sort it at this point so I would sort it at creation. Get the database to do it for you: Category.find(:all, :order => "lft, depth, name" ).map{|category| ["-" * category.depth + category.name, category.id]} Note: you will have to tweak this depending on the schema. I would also push this to a method of the Model to clean up you Controller/View and make it available to other Controllers. -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Andrew Skegg wrote:> Get the database to do it for you: > > Category.find(:all, > :order => "lft, depth, name" > ).map{|category| > ["-" * category.depth + > category.name, > category.id]} >The result it''s the same :( i think because it first order all by lft (that is a unique value), and then by other (but never happen because there aren''t lft equals).. :( -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
marek wrote:> i think because it first order all by lft (that is a unique value), and > then by other (but never happen because there aren''t lft equals).. :(Yep - that would kill it. Let''s try again - Can you post an example output from: Category.find(:all, :order => "lft") -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Andrew Skegg wrote:> Yep - that would kill it. Let''s try again - Can you post an example > output from: > > Category.find(:all, :order => "lft")[["root", 4], ["-contry", 5], ["--andorra", 7], ["--norway", 11], ["--belgium", 12], ["-food",14], ["--thai", 15], ["--english", 18], ["Yorkshire Pudding", 19], ["Fish and chips", 20]] this is what i get now :) i''m thinking about that maybe it''s also possible order them when i insert it into the db (with add_child), so i''ll have in the db something ordered and with right lft, so i can just find(:all), without order them on each request -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
marek wrote:> Andrew Skegg wrote: >> Yep - that would kill it. Let''s try again - Can you post an example >> output from: >> >> Category.find(:all, :order => "lft") > > [["root", 4], ["-contry", 5], ["--andorra", 7], ["--norway", 11], > ["--belgium", 12], ["-food",14], ["--thai", 15], ["--english", 18], > ["Yorkshire Pudding", 19], ["Fish and chips", 20]] > this is what i get now :) > i''m thinking about that maybe it''s also possible order them when i > insert it into the db (with add_child), so i''ll have in the db something > ordered and with right lft, so i can just find(:all), without order them > on each requestops, forget something the right one is (directly from the console): [["root", 4], ["-contry", 5], ["--andorra", 7], ["--norway", 11], ["--belgium", 12], ["-food",14], ["--thai", 15], ["--english", 18], ["---Yorkshire Pudding", 19], ["---Fish and chips", 20]] -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
How about just : Category.find(:all, :order => "depth, name") .map{|category| ["-" * category.depth + category.name, category.id]} Something that still is not clear to me - are the "-"''s stored in the database? The console result you pasted suggests yes, but the code above seems to be adding it. There must be a way for the database to do this for us, but without the schema is is difficult to build the correct SQL query. -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Andrew Skegg wrote:> How about just : > > Category.find(:all, :order => "depth, name") > .map{|category| ["-" * category.depth + category.name, category.id]} > > Something that still is not clear to me - are the "-"''s stored in the > database? The console result you pasted suggests yes, but the code > above seems to be adding it. > > There must be a way for the database to do this for us, but without the > schema is is difficult to build the correct SQL query.it doesn''t work because it order all by depth and the by name, so it lost the hierarchy...the result is: [["root", 4], ["-contry", 5], ["-food",14], ["--andorra", 7], ["--belgium", 12], ["--english", 18], ["--norway", 11], ["--thai", 15], ["---Fish and chips", 20], ["---Yorkshire Pudding", 19]] that isn''t right the "-" aren''t stored in the db, they''re calculated in the map -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Hey, the problem everyone seems to be having here is forgetting that this is a recursive data structure. Assuming each category has a parent_id field, and assuming that root categories have a parent_id which is nil, this should work: in category.rb: def self.options_for_select(records = nil) records ||= find(:all, :order => ''name ASC'') records_by_parent = records.group_by(&:parent_id) collector = lambda do |memo, category| memo << [''*'' * category.depth + category.name, category.id] Array(records_by_parent[category.id]).inject(memo, &collector) end records_by_parent[nil].inject([], &collector) end Regards, Trevor On 18-Jan-07, at 8:22 AM, daniel wrote:> > Andrew Skegg wrote: >> How about just : >> Category.find(:all, :order => "depth, name") >> .map{|category| ["-" * category.depth + category.name, >> category.id]} >> Something that still is not clear to me - are the "-"''s stored in >> the database? The console result you pasted suggests yes, but the >> code above seems to be adding it. >> There must be a way for the database to do this for us, but >> without the schema is is difficult to build the correct SQL query. > > it doesn''t work because it order all by depth and the by name, so > it lost the hierarchy...the result is: > [["root", 4], ["-contry", 5], ["-food",14], ["--andorra", 7], ["-- > belgium", 12], ["--english", 18], ["--norway", 11], ["--thai", 15], > ["---Fish and chips", 20], ["---Yorkshire Pudding", 19]] > that isn''t right > > the "-" aren''t stored in the db, they''re calculated in the map > > -- > Posted via http://www.ruby-forum.com/. > >--~--~---------~--~----~------------~-------~--~----~ 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 rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
daniel wrote:> it doesn''t work because it order all by depth and the by name, so it > lost the hierarchy...the result is: > [["root", 4], ["-contry", 5], ["-food",14], ["--andorra", 7], > ["--belgium", 12], ["--english", 18], ["--norway", 11], ["--thai", 15], > ["---Fish and chips", 20], ["---Yorkshire Pudding", 19]] > that isn''t right > > the "-" aren''t stored in the db, they''re calculated in the mapas daniel said... :) thanks trevor, i''ll try... root parent_id is 0, but i think it''s not a problem change it to nil :) -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Hey, if the parent_id for your root(s) is 0 then you don''t have to alter records in your database, just change the last line of the method I gave you to this: records_by_parent[0].inject([], &collector) Trevor On 18-Jan-07, at 12:07 PM, marek wrote:> > daniel wrote: >> it doesn''t work because it order all by depth and the by name, so >> it lost the hierarchy...the result is: >> [["root", 4], ["-contry", 5], ["-food",14], ["--andorra", 7], ["-- >> belgium", 12], ["--english", 18], ["--norway", 11], ["--thai", >> 15], ["---Fish and chips", 20], ["---Yorkshire Pudding", 19]] >> that isn''t right >> the "-" aren''t stored in the db, they''re calculated in the map > > as daniel said... :) > > thanks trevor, i''ll try... root parent_id is 0, but i think it''s > not a problem change it to nil :) > > -- > Posted via http://www.ruby-forum.com/. > >--~--~---------~--~----~------------~-------~--~----~ 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 rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Trevor Squires wrote:> def self.options_for_select(records = nil) > records ||= find(:all, :order => ''name ASC'') > records_by_parent = records.group_by(&:parent_id) > > collector = lambda do |memo, category| > memo << [''*'' * category.depth + category.name, category.id] > Array(records_by_parent[category.id]).inject(memo, &collector) > end > > records_by_parent[nil].inject([], &collector) > endPerfect :) but just one thing, about performance...if there''re a lot of people that are loading the page i think it''ll be a problem, what do you think? i think that it''s better order them when are inserted into the db (also because it''s done just once, or eventually not so much frequently), so it''s possible to get all the list order just by one select and no operations, instead of order all for each request -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Hey, see below: On 18-Jan-07, at 12:35 PM, marek wrote:> > Trevor Squires wrote: >> def self.options_for_select(records = nil) >> records ||= find(:all, :order => ''name ASC'') >> records_by_parent = records.group_by(&:parent_id) >> collector = lambda do |memo, category| >> memo << [''*'' * category.depth + category.name, category.id] >> Array(records_by_parent[category.id]).inject(memo, &collector) >> end >> records_by_parent[nil].inject([], &collector) >> end > > > Perfect :) > but just one thing, about performance...if there''re a lot of people > that are loading the page i think it''ll be a problem, what do you > think? > i think that it''s better order them when are inserted into the db > (also because it''s done just once, or eventually not so much > frequently), so it''s possible to get all the list order just by one > select and no operations, instead of order all for each requestI prefer not to speculate on whether it''ll be a performance ''problem'' - performance is something that can really only be determined by measuring on relevant hardware with relevant tests. There''s often knee-jerk reactions to your question (which are often right) such as "use fragment caching". However, my attitude is: if you can figure out a way to hyper-optimize it today, you can certainly figure out how to hyper-optimize the day a real issue emerges to prove *this* is the best place to spend your time trying to speed things up. If it works and it''s not a screaming obvious performance issue (like 10 second page load times) then just move on, you''re done and you''ve probably got better things to do. Oh, and if you really can''t let it go and you just *have* to try and optimize this... then just "use fragment caching" :-) Trevor --~--~---------~--~----~------------~-------~--~----~ 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 rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Trevor Squires wrote:> Hey, > > the problem everyone seems to be having here is forgetting that this > is a recursive data structure. > > Assuming each category has a parent_id field, and assuming that root > categories have a parent_id which is nil, this should work: > > in category.rb: > > def self.options_for_select(records = nil) > records ||= find(:all, :order => ''name ASC'') > records_by_parent = records.group_by(&:parent_id) > > collector = lambda do |memo, category| > memo << [''*'' * category.depth + category.name, category.id] > Array(records_by_parent[category.id]).inject(memo, &collector) > end > > records_by_parent[nil].inject([], &collector) > end > > Regards, > TrevorNice! While I can follow the code, there are a few concepts I have never seen before. Every time I think I get it, I lose it again. In time I will master this ruby-foo move - thanks for expanding my knowledge :) -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---