from elixir import *
from sqlalchemy import func
+### Utility function(s)
+
+def indent_comments(comments):
+ """Given a list of comment objects, returns the same comments (and changes
+ them in-place) with an `indent` property set on each comment. This
+ indicates how deeply nested each comment is, relative to the first comment.
+ The first comment's indent level is 0.
+
+ The comments must be a complete subtree, ordered by their `left` property.
+ """
+
+ last_comment = None
+ indent = 0
+ right_ancestry = []
+ for comment in comments:
+ # If this comment is a child of the last, bump the nesting level
+ if last_comment and comment.left < last_comment.right:
+ indent = indent + 1
+ # Remember current ancestory relevant to the root
+ right_ancestry.append(last_comment)
+
+ # On the other hand, for every nesting level this comment may have just
+ # broken out of, back out a level
+ for i in xrange(len(right_ancestry) - 1, -1, -1):
+ if comment.left > right_ancestry[i].right:
+ indent = indent - 1
+ right_ancestry.pop(i)
+
+ # Cache parent comment
+ if len(right_ancestry):
+ comment._parent = right_ancestry[-1]
+
+ comment.indent = indent
+
+ last_comment = comment
+
+ return comments
+
+
+### Usual database classes
+
class Discussion(Entity):
"""Represents a collection of comments attached to some other object."""
count = Field(Integer)
self.discussion.count += 1
if parent:
- # Parent comment given. Add this comment just before the parent's
- # right side...
- self.left = parent.right
- self.right = parent.right + 1
-
- # ...then adjust all rightward comments accordingly
+ # Parent comment given.
+ parent_right = parent.right
+ # Shift every left/right ahead by two to make room for the new
+ # comment's left/right
+ Comment.query.filter(Comment.discussion == self.discussion) \
+ .filter(Comment.left >= parent_right) \
+ .update({ Comment.left: Comment.left + 2 })
Comment.query.filter(Comment.discussion == self.discussion) \
- .filter(Comment.right > parent.right) \
- .update({ Comment.left: Comment.left + 2,
- Comment.right: Comment.right + 2 })
+ .filter(Comment.right >= parent_right) \
+ .update({ Comment.right: Comment.right + 2 })
- # And, finally, update the parent's right endpoint
- parent.right += 2
+ # Then stick the new comment in the right place
+ self.left = parent_right
+ self.right = parent_right + 1
else:
query = session.query(func.max(Comment.right)) \
else:
self.left = max_right + 1
self.right = max_right + 2
+