Jonas Arklint
2007-Jul-23 15:37 UTC
[Betternestedset-talk] Display whole tree without requesting db for each node
Hi! I?m wondering how I display the whole tree without having to request the db each time I use @node.level. Thanks! /Jonas
Jean-Christophe Michel
2007-Jul-23 21:01 UTC
[Betternestedset-talk] Display whole tree without requesting db for each node
Hi, Le 23 juil. 07 ? 17:37, Jonas Arklint a ?crit :> I?m wondering how I display the whole tree without having to > request the > db each time I use @node.level.You have to cache the level in db, or simply compute it in code after you read your tree part. Jean-Christophe Michel -- symetrie.com Better Nested Set for rails: http://opensource.symetrie.com/trac/better_nested_set
Tekin Suleyman
2007-Jul-24 16:05 UTC
[Betternestedset-talk] Display whole tree without requesting dbfor each node
This is something I''ve wondered also as it more or less cancels out any speed gain from getting the full set in one query. Does betternestedset provide the hooks to cache the level? Alternatively, the parent_id could theoretically be used to calculate levels from a full set. -----Original Message----- From: betternestedset-talk-bounces at rubyforge.org [mailto:betternestedset-talk-bounces at rubyforge.org] On Behalf Of Jean-Christophe Michel Sent: 23 July 2007 22:02 To: betternestedset-talk at rubyforge.org Subject: Re: [Betternestedset-talk] Display whole tree without requesting dbfor each node Hi, Le 23 juil. 07 ? 17:37, Jonas Arklint a ?crit :> I?m wondering how I display the whole tree without having to > request the > db each time I use @node.level.You have to cache the level in db, or simply compute it in code after you read your tree part. Jean-Christophe Michel -- symetrie.com Better Nested Set for rails: http://opensource.symetrie.com/trac/better_nested_set _______________________________________________ Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org http://rubyforge.org/mailman/listinfo/betternestedset-talk
Mikel Lindsaar
2007-Jul-24 23:19 UTC
[Betternestedset-talk] Display whole tree without requesting dbfor each node
If you have this as an ongoing requirement, a "simple" solution might be storing the level in the model itself in an after save call back. It''s a bit of a hack, but you can only move the nodes through update calls anyway... so it might work. Then you have it automagically as an instance method. Regards Mikel On 7/25/07, Tekin Suleyman <tekin at raid.nu> wrote:> > This is something I''ve wondered also as it more or less cancels out any > speed gain from getting the full set in one query. Does betternestedset > provide the hooks to cache the level? Alternatively, the parent_id could > theoretically be used to calculate levels from a full set. > > > > -----Original Message----- > From: betternestedset-talk-bounces at rubyforge.org > [mailto:betternestedset-talk-bounces at rubyforge.org] On Behalf Of > Jean-Christophe Michel > Sent: 23 July 2007 22:02 > To: betternestedset-talk at rubyforge.org > Subject: Re: [Betternestedset-talk] Display whole tree without > requesting dbfor each node > > > Hi, > > Le 23 juil. 07 ? 17:37, Jonas Arklint a ?crit : > > I?m wondering how I display the whole tree without having to > > request the > > db each time I use @node.level. > > You have to cache the level in db, or simply compute it in code after > you read your tree part. > > Jean-Christophe Michel > -- > symetrie.com > > Better Nested Set for rails: > http://opensource.symetrie.com/trac/better_nested_set > > > _______________________________________________ > Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/betternestedset-talk > > _______________________________________________ > Betternestedset-talk mailing list > Betternestedset-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/betternestedset-talk >
Tekin Suleyman
2007-Jul-26 12:40 UTC
[Betternestedset-talk] Display whole tree without requestingdbfor each node
Why didn''t I think of that! I''ll give it a try. -----Original Message----- From: betternestedset-talk-bounces at rubyforge.org [mailto:betternestedset-talk-bounces at rubyforge.org] On Behalf Of Mikel Lindsaar Sent: 25 July 2007 00:20 To: betternestedset-talk at rubyforge.org Subject: Re: [Betternestedset-talk] Display whole tree without requestingdbfor each node If you have this as an ongoing requirement, a "simple" solution might be storing the level in the model itself in an after save call back. It''s a bit of a hack, but you can only move the nodes through update calls anyway... so it might work. Then you have it automagically as an instance method. Regards Mikel On 7/25/07, Tekin Suleyman <tekin at raid.nu> wrote:> > This is something I''ve wondered also as it more or less cancels out > any speed gain from getting the full set in one query. Does > betternestedset provide the hooks to cache the level? Alternatively, > the parent_id could theoretically be used to calculate levels from a > full set. > > > > -----Original Message----- > From: betternestedset-talk-bounces at rubyforge.org > [mailto:betternestedset-talk-bounces at rubyforge.org] On Behalf Of > Jean-Christophe Michel > Sent: 23 July 2007 22:02 > To: betternestedset-talk at rubyforge.org > Subject: Re: [Betternestedset-talk] Display whole tree without > requesting dbfor each node > > > Hi, > > Le 23 juil. 07 ? 17:37, Jonas Arklint a ?crit : > > I?m wondering how I display the whole tree without having to request> > the db each time I use @node.level. > > You have to cache the level in db, or simply compute it in code after > you read your tree part. > > Jean-Christophe Michel > -- > symetrie.com > > Better Nested Set for rails: > http://opensource.symetrie.com/trac/better_nested_set > > > _______________________________________________ > Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/betternestedset-talk > > _______________________________________________ > Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/betternestedset-talk >_______________________________________________ Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org http://rubyforge.org/mailman/listinfo/betternestedset-talk
Jonas Arklint
2007-Aug-06 08:29 UTC
[Betternestedset-talk] Display whole tree without requestingdbfor each node
I?m a littlebit confused. But how do i accomplish that? Storing level inside db that is. Tekin Suleyman skrev:> Why didn''t I think of that! I''ll give it a try. > > -----Original Message----- > From: betternestedset-talk-bounces at rubyforge.org > [mailto:betternestedset-talk-bounces at rubyforge.org] On Behalf Of Mikel > Lindsaar > Sent: 25 July 2007 00:20 > To: betternestedset-talk at rubyforge.org > Subject: Re: [Betternestedset-talk] Display whole tree without > requestingdbfor each node > > > If you have this as an ongoing requirement, a "simple" solution might be > storing the level in the model itself in an after save call back. > > It''s a bit of a hack, but you can only move the nodes through update > calls anyway... so it might work. Then you have it automagically as an > instance method. > > Regards > > Mikel > > On 7/25/07, Tekin Suleyman <tekin at raid.nu> wrote: > >> This is something I''ve wondered also as it more or less cancels out >> any speed gain from getting the full set in one query. Does >> betternestedset provide the hooks to cache the level? Alternatively, >> the parent_id could theoretically be used to calculate levels from a >> full set. >> >> >> >> -----Original Message----- >> From: betternestedset-talk-bounces at rubyforge.org >> [mailto:betternestedset-talk-bounces at rubyforge.org] On Behalf Of >> Jean-Christophe Michel >> Sent: 23 July 2007 22:02 >> To: betternestedset-talk at rubyforge.org >> Subject: Re: [Betternestedset-talk] Display whole tree without >> requesting dbfor each node >> >> >> Hi, >> >> Le 23 juil. 07 ? 17:37, Jonas Arklint a ?crit : >> >>> I?m wondering how I display the whole tree without having to request >>> > > >>> the db each time I use @node.level. >>> >> You have to cache the level in db, or simply compute it in code after >> you read your tree part. >> >> Jean-Christophe Michel >> -- >> symetrie.com >> >> Better Nested Set for rails: >> http://opensource.symetrie.com/trac/better_nested_set >> >> >> _______________________________________________ >> Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org >> http://rubyforge.org/mailman/listinfo/betternestedset-talk >> >> _______________________________________________ >> Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org >> http://rubyforge.org/mailman/listinfo/betternestedset-talk >> >> > _______________________________________________ > Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/betternestedset-talk > > _______________________________________________ > Betternestedset-talk mailing list > Betternestedset-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/betternestedset-talk > >
Tekin Suleyman
2007-Aug-06 13:03 UTC
[Betternestedset-talk] Display whole tree without requestingdbfor each node
This isn''t actually as straight forward as it might seem. It can''t be done in an after_save call back as you end up in an infinite loop. I thought you might be able to do it in a before_save, something like: before_save :cache_level alias_method :old_level, :level def level() self.level_cache; end private def cache_level self.level_cache = self.old_level End And make sure you have a column in your table called level_cache. Now, when you call object.level, it won''t make a db call to calculate the level, it will simply return the level_cache attribute. But I''m now not convinced it will exhibit correct behaviour - if old_cache is called before the object is updated, it will cache the current and not the new level, right? Any thoughts? Tekin -----Original Message----- From: betternestedset-talk-bounces at rubyforge.org [mailto:betternestedset-talk-bounces at rubyforge.org] On Behalf Of Jonas Arklint Sent: 06 August 2007 09:29 To: betternestedset-talk at rubyforge.org Subject: Re: [Betternestedset-talk] Display whole tree without requestingdbfor each node I?m a littlebit confused. But how do i accomplish that? Storing level inside db that is. Tekin Suleyman skrev:> Why didn''t I think of that! I''ll give it a try. > > -----Original Message----- > From: betternestedset-talk-bounces at rubyforge.org > [mailto:betternestedset-talk-bounces at rubyforge.org] On Behalf Of Mikel> Lindsaar > Sent: 25 July 2007 00:20 > To: betternestedset-talk at rubyforge.org > Subject: Re: [Betternestedset-talk] Display whole tree without > requestingdbfor each node > > > If you have this as an ongoing requirement, a "simple" solution might > be storing the level in the model itself in an after save call back. > > It''s a bit of a hack, but you can only move the nodes through update > calls anyway... so it might work. Then you have it automagically as > an instance method. > > Regards > > Mikel > > On 7/25/07, Tekin Suleyman <tekin at raid.nu> wrote: > >> This is something I''ve wondered also as it more or less cancels out >> any speed gain from getting the full set in one query. Does >> betternestedset provide the hooks to cache the level? Alternatively, >> the parent_id could theoretically be used to calculate levels from a >> full set. >> >> >> >> -----Original Message----- >> From: betternestedset-talk-bounces at rubyforge.org >> [mailto:betternestedset-talk-bounces at rubyforge.org] On Behalf Of >> Jean-Christophe Michel >> Sent: 23 July 2007 22:02 >> To: betternestedset-talk at rubyforge.org >> Subject: Re: [Betternestedset-talk] Display whole tree without >> requesting dbfor each node >> >> >> Hi, >> >> Le 23 juil. 07 ? 17:37, Jonas Arklint a ?crit : >> >>> I?m wondering how I display the whole tree without having to request >>> > > >>> the db each time I use @node.level. >>> >> You have to cache the level in db, or simply compute it in code after >> you read your tree part. >> >> Jean-Christophe Michel >> -- >> symetrie.com >> >> Better Nested Set for rails: >> http://opensource.symetrie.com/trac/better_nested_set >> >> >> _______________________________________________ >> Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org >> http://rubyforge.org/mailman/listinfo/betternestedset-talk >> >> _______________________________________________ >> Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org >> http://rubyforge.org/mailman/listinfo/betternestedset-talk >> >> > _______________________________________________ > Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/betternestedset-talk > > _______________________________________________ > Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/betternestedset-talk > >_______________________________________________ Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org http://rubyforge.org/mailman/listinfo/betternestedset-talk
Brian Sheehan
2007-Aug-10 10:58 UTC
[Betternestedset-talk] Display whole tree without requestingdbfor each node
I wrote an iterator that iterates through the nested set in a pre-order traversal, yielding each node, it''s level, and the relative level of the next node. It can be used to print out ordered lists of the set using only one db access. Here it is: # traverse {|current_node, level, relative_level_of_next| block } # # Iterates through the nodes in the nested set rooted at the receiver, in a pre-order # traversal. For each node visited, it yields that node, its level, and the relative level # of the next node to be visited. The values returned by successive block executions are # accumulated (in an array by default) and returned at the end # # The receiver always has a level of 0. # # If relative_level_of_next is 1, the next node is guaranteed to be the first (i.e. leftmost) child # of the current node # If it is 0, the next node is the next sibling of the the current node # Otherwise, relative level is a negative integer, indicating how many levels above the current node # the next node is def traverse(accum = []) level = 0 pre_order_array = full_set (pre_order_array.size - 1).times do |i| curr_node = pre_order_array[i] next_node = pre_order_array[i + 1] distance = next_node.lft - curr_node.lft relative_level_of_next = -1 * (distance - 2) accum << yield(curr_node, level, relative_level_of_next) level += relative_level_of_next end # Last node is handled differently to the rest: since there is no next node, # the relative_level_of_next is the number of levels back up to the root level relative_level_of_next = - 1 * (pre_order_array.first.rgt - pre_order_array.last.rgt) accum << yield(pre_order_array.last, level, relative_level_of_next) end Hope it helps. Brian On 8/6/07, Tekin Suleyman <tekin at raid.nu> wrote:> > This isn''t actually as straight forward as it might seem. It can''t be > done in an after_save call back as you end up in an infinite loop. I > thought you might be able to do it in a before_save, something like: > > before_save :cache_level > alias_method :old_level, :level > def level() self.level_cache; end > > private > def cache_level > self.level_cache = self.old_level > End > > And make sure you have a column in your table called level_cache. Now, > when you call object.level, it won''t make a db call to calculate the > level, it will simply return the level_cache attribute. > > But I''m now not convinced it will exhibit correct behaviour - if > old_cache is called before the object is updated, it will cache the > current and not the new level, right? > > Any thoughts? > > Tekin > > > > -----Original Message----- > From: betternestedset-talk-bounces at rubyforge.org > [mailto:betternestedset-talk-bounces at rubyforge.org] On Behalf Of Jonas > Arklint > Sent: 06 August 2007 09:29 > To: betternestedset-talk at rubyforge.org > Subject: Re: [Betternestedset-talk] Display whole tree without > requestingdbfor each node > > > I?m a littlebit confused. But how do i accomplish that? Storing level > inside db that is. > > Tekin Suleyman skrev: > > Why didn''t I think of that! I''ll give it a try. > > > > -----Original Message----- > > From: betternestedset-talk-bounces at rubyforge.org > > [mailto:betternestedset-talk-bounces at rubyforge.org] On Behalf Of Mikel > > > Lindsaar > > Sent: 25 July 2007 00:20 > > To: betternestedset-talk at rubyforge.org > > Subject: Re: [Betternestedset-talk] Display whole tree without > > requestingdbfor each node > > > > > > If you have this as an ongoing requirement, a "simple" solution might > > be storing the level in the model itself in an after save call back. > > > > It''s a bit of a hack, but you can only move the nodes through update > > calls anyway... so it might work. Then you have it automagically as > > an instance method. > > > > Regards > > > > Mikel > > > > On 7/25/07, Tekin Suleyman <tekin at raid.nu> wrote: > > > >> This is something I''ve wondered also as it more or less cancels out > >> any speed gain from getting the full set in one query. Does > >> betternestedset provide the hooks to cache the level? Alternatively, > >> the parent_id could theoretically be used to calculate levels from a > >> full set. > >> > >> > >> > >> -----Original Message----- > >> From: betternestedset-talk-bounces at rubyforge.org > >> [mailto:betternestedset-talk-bounces at rubyforge.org] On Behalf Of > >> Jean-Christophe Michel > >> Sent: 23 July 2007 22:02 > >> To: betternestedset-talk at rubyforge.org > >> Subject: Re: [Betternestedset-talk] Display whole tree without > >> requesting dbfor each node > >> > >> > >> Hi, > >> > >> Le 23 juil. 07 ? 17:37, Jonas Arklint a ?crit : > >> > >>> I?m wondering how I display the whole tree without having to request > >>> > > > > > >>> the db each time I use @node.level. > >>> > >> You have to cache the level in db, or simply compute it in code after > >> you read your tree part. > >> > >> Jean-Christophe Michel > >> -- > >> symetrie.com > >> > >> Better Nested Set for rails: > >> http://opensource.symetrie.com/trac/better_nested_set > >> > >> > >> _______________________________________________ > >> Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org > >> http://rubyforge.org/mailman/listinfo/betternestedset-talk > >> > >> _______________________________________________ > >> Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org > >> http://rubyforge.org/mailman/listinfo/betternestedset-talk > >> > >> > > _______________________________________________ > > Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org > > http://rubyforge.org/mailman/listinfo/betternestedset-talk > > > > _______________________________________________ > > Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org > > http://rubyforge.org/mailman/listinfo/betternestedset-talk > > > > > > _______________________________________________ > Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/betternestedset-talk > > _______________________________________________ > Betternestedset-talk mailing list > Betternestedset-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/betternestedset-talk >
Tekin Suleyman
2007-Aug-10 11:12 UTC
[Betternestedset-talk] Display whole tree withoutrequestingdbfor each node
Cheers, that looks fantastic! I''ll give it a shot and report back. Tekin -----Original Message----- From: betternestedset-talk-bounces at rubyforge.org [mailto:betternestedset-talk-bounces at rubyforge.org] On Behalf Of Brian Sheehan Sent: 10 August 2007 11:58 To: betternestedset-talk at rubyforge.org Subject: Re: [Betternestedset-talk] Display whole tree withoutrequestingdbfor each node I wrote an iterator that iterates through the nested set in a pre-order traversal, yielding each node, it''s level, and the relative level of the next node. It can be used to print out ordered lists of the set using only one db access. Here it is: # traverse {|current_node, level, relative_level_of_next| block } # # Iterates through the nodes in the nested set rooted at the receiver, in a pre-order # traversal. For each node visited, it yields that node, its level, and the relative level # of the next node to be visited. The values returned by successive block executions are # accumulated (in an array by default) and returned at the end # # The receiver always has a level of 0. # # If relative_level_of_next is 1, the next node is guaranteed to be the first (i.e. leftmost) child # of the current node # If it is 0, the next node is the next sibling of the the current node # Otherwise, relative level is a negative integer, indicating how many levels above the current node # the next node is def traverse(accum = []) level = 0 pre_order_array = full_set (pre_order_array.size - 1).times do |i| curr_node = pre_order_array[i] next_node = pre_order_array[i + 1] distance = next_node.lft - curr_node.lft relative_level_of_next = -1 * (distance - 2) accum << yield(curr_node, level, relative_level_of_next) level += relative_level_of_next end # Last node is handled differently to the rest: since there is no next node, # the relative_level_of_next is the number of levels back up to the root level relative_level_of_next = - 1 * (pre_order_array.first.rgt - pre_order_array.last.rgt) accum << yield(pre_order_array.last, level, relative_level_of_next) end Hope it helps. Brian On 8/6/07, Tekin Suleyman <tekin at raid.nu> wrote:> > This isn''t actually as straight forward as it might seem. It can''t be > done in an after_save call back as you end up in an infinite loop. I > thought you might be able to do it in a before_save, something like: > > before_save :cache_level > alias_method :old_level, :level > def level() self.level_cache; end > > private > def cache_level > self.level_cache = self.old_level > End > > And make sure you have a column in your table called level_cache. Now,> when you call object.level, it won''t make a db call to calculate the > level, it will simply return the level_cache attribute. > > But I''m now not convinced it will exhibit correct behaviour - if > old_cache is called before the object is updated, it will cache the > current and not the new level, right? > > Any thoughts? > > Tekin > > > > -----Original Message----- > From: betternestedset-talk-bounces at rubyforge.org > [mailto:betternestedset-talk-bounces at rubyforge.org] On Behalf Of Jonas> Arklint > Sent: 06 August 2007 09:29 > To: betternestedset-talk at rubyforge.org > Subject: Re: [Betternestedset-talk] Display whole tree without > requestingdbfor each node > > > I?m a littlebit confused. But how do i accomplish that? Storing level > inside db that is. > > Tekin Suleyman skrev: > > Why didn''t I think of that! I''ll give it a try. > > > > -----Original Message----- > > From: betternestedset-talk-bounces at rubyforge.org > > [mailto:betternestedset-talk-bounces at rubyforge.org] On Behalf Of > > Mikel > > > Lindsaar > > Sent: 25 July 2007 00:20 > > To: betternestedset-talk at rubyforge.org > > Subject: Re: [Betternestedset-talk] Display whole tree without > > requestingdbfor each node > > > > > > If you have this as an ongoing requirement, a "simple" solution > > might be storing the level in the model itself in an after save call> > back. > > > > It''s a bit of a hack, but you can only move the nodes through update> > calls anyway... so it might work. Then you have it automagically as> > an instance method. > > > > Regards > > > > Mikel > > > > On 7/25/07, Tekin Suleyman <tekin at raid.nu> wrote: > > > >> This is something I''ve wondered also as it more or less cancels out> >> any speed gain from getting the full set in one query. Does > >> betternestedset provide the hooks to cache the level? > >> Alternatively, the parent_id could theoretically be used to > >> calculate levels from a full set. > >> > >> > >> > >> -----Original Message----- > >> From: betternestedset-talk-bounces at rubyforge.org > >> [mailto:betternestedset-talk-bounces at rubyforge.org] On Behalf Of > >> Jean-Christophe Michel > >> Sent: 23 July 2007 22:02 > >> To: betternestedset-talk at rubyforge.org > >> Subject: Re: [Betternestedset-talk] Display whole tree without > >> requesting dbfor each node > >> > >> > >> Hi, > >> > >> Le 23 juil. 07 ? 17:37, Jonas Arklint a ?crit : > >> > >>> I?m wondering how I display the whole tree without having to > >>> request > >>> > > > > > >>> the db each time I use @node.level. > >>> > >> You have to cache the level in db, or simply compute it in code > >> after you read your tree part. > >> > >> Jean-Christophe Michel > >> -- > >> symetrie.com > >> > >> Better Nested Set for rails: > >> http://opensource.symetrie.com/trac/better_nested_set > >> > >> > >> _______________________________________________ > >> Betternestedset-talk mailing list > >> Betternestedset-talk at rubyforge.org > >> http://rubyforge.org/mailman/listinfo/betternestedset-talk > >> > >> _______________________________________________ > >> Betternestedset-talk mailing list > >> Betternestedset-talk at rubyforge.org > >> http://rubyforge.org/mailman/listinfo/betternestedset-talk > >> > >> > > _______________________________________________ > > Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org > > http://rubyforge.org/mailman/listinfo/betternestedset-talk > > > > _______________________________________________ > > Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org > > http://rubyforge.org/mailman/listinfo/betternestedset-talk > > > > > > _______________________________________________ > Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/betternestedset-talk > > _______________________________________________ > Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/betternestedset-talk >_______________________________________________ Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org http://rubyforge.org/mailman/listinfo/betternestedset-talk
Tekin Suleyman
2007-Aug-10 13:07 UTC
[Betternestedset-talk] Display whole tree withoutrequestingdbfor each node
Works a treat! I modified it slightly as I have several roots and want the whole thing traversed: I made it a class method and instead of full_set it calls complete_set. Thanks Brian, very handy indeed. Tekin -----Original Message----- From: betternestedset-talk-bounces at rubyforge.org [mailto:betternestedset-talk-bounces at rubyforge.org] On Behalf Of Brian Sheehan Sent: 10 August 2007 11:58 To: betternestedset-talk at rubyforge.org Subject: Re: [Betternestedset-talk] Display whole tree withoutrequestingdbfor each node I wrote an iterator that iterates through the nested set in a pre-order traversal, yielding each node, it''s level, and the relative level of the next node. It can be used to print out ordered lists of the set using only one db access. Here it is: # traverse {|current_node, level, relative_level_of_next| block } # # Iterates through the nodes in the nested set rooted at the receiver, in a pre-order # traversal. For each node visited, it yields that node, its level, and the relative level # of the next node to be visited. The values returned by successive block executions are # accumulated (in an array by default) and returned at the end # # The receiver always has a level of 0. # # If relative_level_of_next is 1, the next node is guaranteed to be the first (i.e. leftmost) child # of the current node # If it is 0, the next node is the next sibling of the the current node # Otherwise, relative level is a negative integer, indicating how many levels above the current node # the next node is def traverse(accum = []) level = 0 pre_order_array = full_set (pre_order_array.size - 1).times do |i| curr_node = pre_order_array[i] next_node = pre_order_array[i + 1] distance = next_node.lft - curr_node.lft relative_level_of_next = -1 * (distance - 2) accum << yield(curr_node, level, relative_level_of_next) level += relative_level_of_next end # Last node is handled differently to the rest: since there is no next node, # the relative_level_of_next is the number of levels back up to the root level relative_level_of_next = - 1 * (pre_order_array.first.rgt - pre_order_array.last.rgt) accum << yield(pre_order_array.last, level, relative_level_of_next) end Hope it helps. Brian On 8/6/07, Tekin Suleyman <tekin at raid.nu> wrote:> > This isn''t actually as straight forward as it might seem. It can''t be > done in an after_save call back as you end up in an infinite loop. I > thought you might be able to do it in a before_save, something like: > > before_save :cache_level > alias_method :old_level, :level > def level() self.level_cache; end > > private > def cache_level > self.level_cache = self.old_level > End > > And make sure you have a column in your table called level_cache. Now,> when you call object.level, it won''t make a db call to calculate the > level, it will simply return the level_cache attribute. > > But I''m now not convinced it will exhibit correct behaviour - if > old_cache is called before the object is updated, it will cache the > current and not the new level, right? > > Any thoughts? > > Tekin > > > > -----Original Message----- > From: betternestedset-talk-bounces at rubyforge.org > [mailto:betternestedset-talk-bounces at rubyforge.org] On Behalf Of Jonas> Arklint > Sent: 06 August 2007 09:29 > To: betternestedset-talk at rubyforge.org > Subject: Re: [Betternestedset-talk] Display whole tree without > requestingdbfor each node > > > I?m a littlebit confused. But how do i accomplish that? Storing level > inside db that is. > > Tekin Suleyman skrev: > > Why didn''t I think of that! I''ll give it a try. > > > > -----Original Message----- > > From: betternestedset-talk-bounces at rubyforge.org > > [mailto:betternestedset-talk-bounces at rubyforge.org] On Behalf Of > > Mikel > > > Lindsaar > > Sent: 25 July 2007 00:20 > > To: betternestedset-talk at rubyforge.org > > Subject: Re: [Betternestedset-talk] Display whole tree without > > requestingdbfor each node > > > > > > If you have this as an ongoing requirement, a "simple" solution > > might be storing the level in the model itself in an after save call> > back. > > > > It''s a bit of a hack, but you can only move the nodes through update> > calls anyway... so it might work. Then you have it automagically as> > an instance method. > > > > Regards > > > > Mikel > > > > On 7/25/07, Tekin Suleyman <tekin at raid.nu> wrote: > > > >> This is something I''ve wondered also as it more or less cancels out> >> any speed gain from getting the full set in one query. Does > >> betternestedset provide the hooks to cache the level? > >> Alternatively, the parent_id could theoretically be used to > >> calculate levels from a full set. > >> > >> > >> > >> -----Original Message----- > >> From: betternestedset-talk-bounces at rubyforge.org > >> [mailto:betternestedset-talk-bounces at rubyforge.org] On Behalf Of > >> Jean-Christophe Michel > >> Sent: 23 July 2007 22:02 > >> To: betternestedset-talk at rubyforge.org > >> Subject: Re: [Betternestedset-talk] Display whole tree without > >> requesting dbfor each node > >> > >> > >> Hi, > >> > >> Le 23 juil. 07 ? 17:37, Jonas Arklint a ?crit : > >> > >>> I?m wondering how I display the whole tree without having to > >>> request > >>> > > > > > >>> the db each time I use @node.level. > >>> > >> You have to cache the level in db, or simply compute it in code > >> after you read your tree part. > >> > >> Jean-Christophe Michel > >> -- > >> symetrie.com > >> > >> Better Nested Set for rails: > >> http://opensource.symetrie.com/trac/better_nested_set > >> > >> > >> _______________________________________________ > >> Betternestedset-talk mailing list > >> Betternestedset-talk at rubyforge.org > >> http://rubyforge.org/mailman/listinfo/betternestedset-talk > >> > >> _______________________________________________ > >> Betternestedset-talk mailing list > >> Betternestedset-talk at rubyforge.org > >> http://rubyforge.org/mailman/listinfo/betternestedset-talk > >> > >> > > _______________________________________________ > > Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org > > http://rubyforge.org/mailman/listinfo/betternestedset-talk > > > > _______________________________________________ > > Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org > > http://rubyforge.org/mailman/listinfo/betternestedset-talk > > > > > > _______________________________________________ > Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/betternestedset-talk > > _______________________________________________ > Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/betternestedset-talk >_______________________________________________ Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org http://rubyforge.org/mailman/listinfo/betternestedset-talk -------------- next part -------------- A non-text attachment was scrubbed... Name: add_traverse_function.patch Type: application/octet-stream Size: 22991 bytes Desc: not available Url : http://rubyforge.org/pipermail/betternestedset-talk/attachments/20070810/e3db03f2/attachment-0001.obj
Brian Sheehan
2007-Aug-10 15:23 UTC
[Betternestedset-talk] Display whole tree withoutrequestingdbfor each node
Glad to hear it. I haven''t done much testing on that method, so post back if you run into any issues. thanks for the patch, Brian On 8/10/07, Tekin Suleyman <tekin at raid.nu> wrote:> Works a treat! > > I modified it slightly as I have several roots and want the whole thing > traversed: I made it a class method and instead of full_set it calls > complete_set. > Thanks Brian, very handy indeed. > > Tekin > > -----Original Message----- > From: betternestedset-talk-bounces at rubyforge.org > [mailto:betternestedset-talk-bounces at rubyforge.org] On Behalf Of Brian > Sheehan > Sent: 10 August 2007 11:58 > To: betternestedset-talk at rubyforge.org > Subject: Re: [Betternestedset-talk] Display whole tree > withoutrequestingdbfor each node > > > I wrote an iterator that iterates through the nested set in a pre-order > traversal, yielding each node, it''s level, and the relative level of the > next node. It can be used to print out ordered lists of the set using > only one db access. Here it is: > > # traverse {|current_node, level, relative_level_of_next| block } > # > # Iterates through the nodes in the nested set rooted at the receiver, > in a pre-order > # traversal. For each node visited, it yields that node, its level, > and the relative level > # of the next node to be visited. The values returned by successive > block executions are > # accumulated (in an array by default) and returned at the end > # > # The receiver always has a level of 0. > # > # If relative_level_of_next is 1, the next node is guaranteed to be > the first (i.e. leftmost) child > # of the current node > # If it is 0, the next node is the next sibling of the the current > node > # Otherwise, relative level is a negative integer, indicating how many > levels above the current node > # the next node is > def traverse(accum = []) > level = 0 > pre_order_array = full_set > (pre_order_array.size - 1).times do |i| > curr_node = pre_order_array[i] > next_node = pre_order_array[i + 1] > distance = next_node.lft - curr_node.lft > relative_level_of_next = -1 * (distance - 2) > accum << yield(curr_node, level, relative_level_of_next) > level += relative_level_of_next > end > # Last node is handled differently to the rest: since there is no > next node, > # the relative_level_of_next is the number of levels back up to the > root level > relative_level_of_next = - 1 * (pre_order_array.first.rgt - > pre_order_array.last.rgt) > accum << yield(pre_order_array.last, level, relative_level_of_next) > end > > Hope it helps. > > Brian > > On 8/6/07, Tekin Suleyman <tekin at raid.nu> wrote: > > > > This isn''t actually as straight forward as it might seem. It can''t be > > done in an after_save call back as you end up in an infinite loop. I > > thought you might be able to do it in a before_save, something like: > > > > before_save :cache_level > > alias_method :old_level, :level > > def level() self.level_cache; end > > > > private > > def cache_level > > self.level_cache = self.old_level > > End > > > > And make sure you have a column in your table called level_cache. Now, > > > when you call object.level, it won''t make a db call to calculate the > > level, it will simply return the level_cache attribute. > > > > But I''m now not convinced it will exhibit correct behaviour - if > > old_cache is called before the object is updated, it will cache the > > current and not the new level, right? > > > > Any thoughts? > > > > Tekin > > > > > > > > -----Original Message----- > > From: betternestedset-talk-bounces at rubyforge.org > > [mailto:betternestedset-talk-bounces at rubyforge.org] On Behalf Of Jonas > > > Arklint > > Sent: 06 August 2007 09:29 > > To: betternestedset-talk at rubyforge.org > > Subject: Re: [Betternestedset-talk] Display whole tree without > > requestingdbfor each node > > > > > > I?m a littlebit confused. But how do i accomplish that? Storing level > > inside db that is. > > > > Tekin Suleyman skrev: > > > Why didn''t I think of that! I''ll give it a try. > > > > > > -----Original Message----- > > > From: betternestedset-talk-bounces at rubyforge.org > > > [mailto:betternestedset-talk-bounces at rubyforge.org] On Behalf Of > > > Mikel > > > > > Lindsaar > > > Sent: 25 July 2007 00:20 > > > To: betternestedset-talk at rubyforge.org > > > Subject: Re: [Betternestedset-talk] Display whole tree without > > > requestingdbfor each node > > > > > > > > > If you have this as an ongoing requirement, a "simple" solution > > > might be storing the level in the model itself in an after save call > > > > back. > > > > > > It''s a bit of a hack, but you can only move the nodes through update > > > > calls anyway... so it might work. Then you have it automagically as > > > > an instance method. > > > > > > Regards > > > > > > Mikel > > > > > > On 7/25/07, Tekin Suleyman <tekin at raid.nu> wrote: > > > > > >> This is something I''ve wondered also as it more or less cancels out > > > >> any speed gain from getting the full set in one query. Does > > >> betternestedset provide the hooks to cache the level? > > >> Alternatively, the parent_id could theoretically be used to > > >> calculate levels from a full set. > > >> > > >> > > >> > > >> -----Original Message----- > > >> From: betternestedset-talk-bounces at rubyforge.org > > >> [mailto:betternestedset-talk-bounces at rubyforge.org] On Behalf Of > > >> Jean-Christophe Michel > > >> Sent: 23 July 2007 22:02 > > >> To: betternestedset-talk at rubyforge.org > > >> Subject: Re: [Betternestedset-talk] Display whole tree without > > >> requesting dbfor each node > > >> > > >> > > >> Hi, > > >> > > >> Le 23 juil. 07 ? 17:37, Jonas Arklint a ?crit : > > >> > > >>> I?m wondering how I display the whole tree without having to > > >>> request > > >>> > > > > > > > > >>> the db each time I use @node.level. > > >>> > > >> You have to cache the level in db, or simply compute it in code > > >> after you read your tree part. > > >> > > >> Jean-Christophe Michel > > >> -- > > >> symetrie.com > > >> > > >> Better Nested Set for rails: > > >> http://opensource.symetrie.com/trac/better_nested_set > > >> > > >> > > >> _______________________________________________ > > >> Betternestedset-talk mailing list > > >> Betternestedset-talk at rubyforge.org > > >> http://rubyforge.org/mailman/listinfo/betternestedset-talk > > >> > > >> _______________________________________________ > > >> Betternestedset-talk mailing list > > >> Betternestedset-talk at rubyforge.org > > >> http://rubyforge.org/mailman/listinfo/betternestedset-talk > > >> > > >> > > > _______________________________________________ > > > Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org > > > http://rubyforge.org/mailman/listinfo/betternestedset-talk > > > > > > _______________________________________________ > > > Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org > > > http://rubyforge.org/mailman/listinfo/betternestedset-talk > > > > > > > > > > _______________________________________________ > > Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org > > http://rubyforge.org/mailman/listinfo/betternestedset-talk > > > > _______________________________________________ > > Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org > > http://rubyforge.org/mailman/listinfo/betternestedset-talk > > > _______________________________________________ > Betternestedset-talk mailing list Betternestedset-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/betternestedset-talk > > _______________________________________________ > Betternestedset-talk mailing list > Betternestedset-talk at rubyforge.org > http://rubyforge.org/mailman/listinfo/betternestedset-talk > > >