Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get previous / next item in tree #62

Open
jmuheim opened this issue Feb 21, 2017 · 10 comments
Open

Get previous / next item in tree #62

jmuheim opened this issue Feb 21, 2017 · 10 comments

Comments

@jmuheim
Copy link

jmuheim commented Feb 21, 2017

Is there already a method for finding the previous or next item in the tree?

@felixbuenemann
Copy link
Collaborator

What would be the previous or next item in the tree?

@jmuheim
Copy link
Author

jmuheim commented Feb 21, 2017

In the "flat" full tree (walk_tree), the previous and next.

@felixbuenemann
Copy link
Collaborator

felixbuenemann commented Feb 21, 2017

The walk_tree method yields to a block, so how would you use previous/next in that context?

@jmuheim
Copy link
Author

jmuheim commented Feb 21, 2017

I don't mean one should use walk_tree for that, I only want to show what I'm meaning.

So in the flat view:

  • A
    • AA
    • AB
  • B
  • C
    • CA
    • CB

When doing AA.previous it would be A. When doing AA.next it would be AB. When doing C.previous it would be B, when doing C.next it would be CA.

You know what I mean?

@felixbuenemann
Copy link
Collaborator

What would be an example use case for such a functionality?

@felixbuenemann
Copy link
Collaborator

Btw. you could model the next case with an enumerator on top of walk_tree:

enum = Enumerator.new do |y|
  Foo.walk_tree do |node, _|
    y << node
  end
end
# Get next tree node:
enum.next

@jmuheim
Copy link
Author

jmuheim commented Feb 22, 2017

Use case: I have a small CMS which has a tree hierarchy of pages. I'd like users to be able to browse through all available pages using "Previous" and "Next" links.

@felixbuenemann
Copy link
Collaborator

That would be much more efficient and easier to achieve with a nested set, because your previous node would be current_node.lft - 1 and the next node would be current_node.rgt + 1 assuming depth first traversal.

There's a popular gem awesome_nested_set which implements nested sets.

It should be fairly easy to migrate to awsome_nested_set by adding an indexed lft and rgt integer column to your db and calling the gems Model.rebuild! method to populate the new columns.

@jmuheim
Copy link
Author

jmuheim commented Feb 22, 2017

Thanks for this useful hint. Still, I already use your gem, and I have to stick to it for several reasons. How would you implement a previous/next feature? I doesn't need to be very fancy.

@felixbuenemann
Copy link
Collaborator

There isn't really a straight-forward way to do this.

The first problem you will have is that there isn't really a defined order of nodes, so if you have a parent node a, and child nodes b, c, d the database can choose any order to return unless you also add an order column.

If you have established a stable node order, you would have to check the position of the current node within self_and_siblings.

For the previous case you would chose either the preceding node or if it is already the first sibling node go to the parent.

For the next case go to the first child node of the current node or next node in the siblings or if the current node is already the last position go to the next sibling of the parent.

This will be much more complex to write and much slower than woking with a nested set, so what are the reasons you need to stick with acts_as_tree?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants