Skip to content

Instantly share code, notes, and snippets.

@reddyonrails
Forked from Loupi/nested-redis.rb
Created November 6, 2019 17:59
Show Gist options
  • Save reddyonrails/e7decf3ca2104fb0062d8a8d69a39c23 to your computer and use it in GitHub Desktop.
Save reddyonrails/e7decf3ca2104fb0062d8a8d69a39c23 to your computer and use it in GitHub Desktop.
Redis Nested Comments in Ruby
require 'redis'
require 'securerandom'
require 'json'
class CommentsRepository
def initialize
@redis = Redis.new
end
def save itemId, comment, parentId = nil
now = Time.now.utc.to_i
id = @redis.incr 1
comment = {id: id, comment: comment, time: now}
childsOfKey = parentId ? subCommentsKey(parentId) : commentsKey(itemId)
@redis.multi do |multi|
@redis.del jsonKey itemId
@redis.hmset commentKey(id), comment.map{|k,v| [k,v]}.flatten(1)
@redis.zadd childsOfKey, now, id
end
id
end
def get id
jsonId = jsonKey id
jsonComments = @redis.get jsonId
if jsonComments
JSON.parse jsonComments
else
comments = multiFetch commentsKey id
@redis.set jsonId, comments.to_json
comments
end
end
def leaf id
comment = @redis.hgetall commentKey id
comment['comments'] = multiFetch subCommentsKey id
comment
end
def delete comment, parentId, itemId, isMainThread = true
innerDelete comment, parentId, isMainThread
@redis.del jsonKey itemId
end
private
def multiFetch key
commentIds = @redis.zrange key, 0, -1
comments = @redis.multi do |multi|
commentIds.map { |id| multi.hgetall(commentKey id)}
end
processComments comments
end
def processComments comments
comments.each do |comment|
subCommentsId = subCommentsKey comment['id']
if @redis.zcard(subCommentsId) > 0
comment['comments'] = multiFetch subCommentsId
end
end
end
def innerDelete comment, parentId, isMainThread
if comment.kind_of? Array
comment.each {|c| innerDelete c, parentId, isMainThread}
else
id = comment['id']
comments = comment['comments']
childsKey = isMainThread ? commentsKey(parentId) : subCommentsKey(parentId)
@redis.del commentKey id
@redis.zrem childsKey, id
innerDelete comments, id, false if comments
end
end
def jsonKey id
"comment:#{id}:json"
end
def commentKey id
"comment:#{id}"
end
def commentsKey id
"comments:#{id}"
end
def subCommentsKey id
"comment:#{id}:sub"
end
end
def printComments comments, tabs = 0
comments.each do |comment|
tabs.times { putc "\t" }
puts "#{comment['comment']}"
if comment['comments']
printComments comment['comments'], tabs + 1
end
end
end
def saveDummy cr, id
tree = cr.save id, 'Tree'
root = cr.save id, 'Root', tree
trunk = cr.save id, 'Trunk', tree
branch = cr.save id, 'Branch', trunk
leaf = cr.save id, 'Leaf', branch
top = cr.save id, 'Top', tree
end
command = ARGV[0]
id = ARGV[1]
cr = CommentsRepository.new
case command
when 's'
saveDummy cr, id
when 'p'
printComments cr.get id
when 'l'
printComments [cr.leaf(id)]
when 'd'
cr.delete cr.get(id), id, id
when 'r'
cr.delete cr.leaf(ARGV[2]), ARGV[3], id, false
when 'j'
puts cr.get(id).to_json
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment