内容比较丑陋,算是个抛砖引玉吧,如果不是新手,就走开吧。 最近发现 rc 的源代码的资料比较高,网上搜了一遍,也没有发现类似面向新手的分析性文章。
redis 使用 计数器
topicController:
@topic.hits.incr(1)
Topic
include Redis::Objects
counter :hits, :default => 0
end
消息系统: 采用 faye: 参考资料: http://railscasts.com/episodes/260-messaging-with-faye?view=asciicast
当用户 A 回复用户 B 的评论时,rc 会使用消息系统将该回复通知到用户 B: 1 当 create 一个新的 Reply 时,会调用 Reply 的回调方法:after_create
class Reply
after_create do
Reply.delay.send_topic_reply_notification(self.id)
end
2 创建 Notification::TopicReply
def self.send_topic_reply_notification(reply_id)
reply = Reply.find_by_id(reply_id)
return if reply.blank?
topic = reply.topic
return if topic.blank?
# 给发帖人发回帖通知
if reply.user_id != topic.user_id && !reply.mentioned_user_ids.include?(topic.user_id)
Notification::TopicReply.create :user_id => topic.user_id, :reply_id => reply.id
reply.notified_user_ids << topic.user_id
end
# 给关注者发通知
topic.follower_ids.each do |uid|
# 排除同一个回复过程中已经提醒过的人
next if reply.notified_user_ids.include?(uid)
# 排除回帖人
next if uid == reply.user_id
Notification::TopicReply.create :user_id => uid, :reply_id => reply.id
end
true
end
3 Notification::TopicReply 的基类是 Notification::Base
class Notification::TopicReply < Notification::Base
belongs_to :reply
delegate :body, :to => :reply, :prefix => true, :allow_nil => true
def notify_hash
return "" if self.reply.blank?
{
:title => "关注的话题有了新回复:",
:content => self.reply_body[0,30],
:content_path => self.content_path
}
end
def content_path
return "" if self.reply.blank?
url_helpers.topic_path(self.reply.topic_id)
end
end
4Notification::Base 的 create 方法有个回调:realtime_push_to_client,在该回调里会将通知广播出去 Notification::Base
after_create :realtime_push_to_client
def realtime_push_to_client
if self.user
hash = self.notify_hash
hash[:count] = self.user.notifications.unread.count
FayeClient.send("/notifications_count/#{self.user.temp_access_token}", hash)
end
end
class FayeClient
def self.send(channel, params)
Thread.new {
params[:token] = Setting.faye_token
message = {:channel => channel, :data => params}
uri = URI.parse(Setting.faye_server)
Net::HTTP.post_form(uri, :message => message.to_json)
}
end
end
5 客户端接受到上面的通知后:
initNotificationSubscribe : () ->
faye = new Faye.Client(FAYE_SERVER_URL)
notification_subscription = faye.subscribe "/notifications_count/#{CURRENT_USER_ACCESS_TOKEN}",(json) ->
span = $("#user_notifications_count span")
new_title = $(document).attr("title").replace(/\(\d+\) /,'')
if json.count > 0
span.addClass("badge-error")
new_title = "(#{json.count}) #{new_title}"
url = App.fixUrlDash("#{ROOT_URL}#{json.content_path}")
console.log url
$.notifier.notify("",json.title,json.content,url)
else
span.removeClass("badge-error")
span.text(json.count)
$(document).attr("title", new_title)
true