Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Extrac mention logic to Mongoid::Mentionable.

  • Loading branch information...
commit 9ced01427a402232c0bdfa36bc3d515f6eb8ce4c 1 parent 2eb4aee
@chloerei chloerei authored
View
10 app/controllers/topics_controller.rb
@@ -57,9 +57,11 @@ def show
@node = @topic.node
@replies = @topic.replies.without_body.asc(:_id).all.includes(:user).reject { |r| r.user.blank? }
if current_user
- current_user.read_topic(@topic)
- # TODO: 此处导致每次查看帖子都会执行 update 需要改进
- current_user.notifications.where(:reply_id.in => @replies.map(&:id), :read => false).update_all(:read => true)
+ unless current_user.topic_read?(@topic)
+ current_user.notifications.unread.any_of({:mentionable_type => 'Reply', :mentionable_id.in => @replies.map(&:id)},
+ {:reply_id.in => @replies.map(&:id)}).update_all(:read => true)
+ current_user.read_topic(@topic)
+ end
end
set_seo_meta("#{@topic.title} » #{t("menu.topics")}")
drop_breadcrumb("#{@node.name}", node_topics_path(@node.id))
@@ -129,7 +131,7 @@ def destroy
@topic.destroy_by(current_user)
redirect_to(topics_path, :notice => t("topics.delete_topic_success"))
end
-
+
def favorite
if params[:type] == "unfavorite"
current_user.unfavorite_topic(params[:id])
View
40 app/models/mongoid/mentionable.rb
@@ -0,0 +1,40 @@
+module Mongoid
+ module Mentionable
+ extend ActiveSupport::Concern
+ included do
+ field :mentioned_user_ids, :type => Array, :default => []
+ before_save :extract_mentioned_users
+ after_create :send_mention_notification
+ has_many :notification_mentions, :as => :mentionable, :class_name => 'Notification::Mention'
+ end
+
+ def mentioned_users
+ User.where(:_id.in => mentioned_user_ids)
+ end
+
+ def mentioned_user_logins
+ # 用于作为缓存 key
+ ids_md5 = Digest::MD5.hexdigest(self.mentioned_user_ids.to_s)
+ Rails.cache.fetch("#{self.class.name.downcase}:#{self.id}:mentioned_user_logins:#{ids_md5}") do
+ User.where(:_id.in => self.mentioned_user_ids).only(:login).map(&:login)
+ end
+ end
+
+ def extract_mentioned_users
+ logins = body.scan(/@(\w{3,20})/).flatten
+ if logins.any?
+ self.mentioned_user_ids = User.where(:login => /^(#{logins.join('|')})$/i, :_id.ne => user.id).limit(5).only(:_id).map(&:_id).to_a
+ end
+ end
+
+ def no_mention_users
+ [user]
+ end
+
+ def send_mention_notification
+ (mentioned_users - no_mention_users).each do |user|
+ Notification::Mention.create :user => user, :mentionable => self
+ end
+ end
+ end
+end
View
2  app/models/notification/base.rb
@@ -7,6 +7,8 @@ class Notification::Base
field :read, :default => false
+ index :read
+
scope :unread, where(:read => false)
belongs_to :user
View
2  app/models/notification/mention.rb
@@ -1,3 +1,3 @@
class Notification::Mention < Notification::Base
- belongs_to :reply
+ belongs_to :mentionable, :polymorphic => true
end
View
27 app/models/reply.rb
@@ -7,12 +7,12 @@ class Reply
include Mongoid::CounterCache
include Mongoid::SoftDelete
include Mongoid::MarkdownBody
+ include Mongoid::Mentionable
field :body
field :body_html
field :source
field :message_id
- field :mentioned_user_ids, :type => Array, :default => []
belongs_to :user, :inverse_of => :replies
belongs_to :topic, :inverse_of => :replies
@@ -41,29 +41,7 @@ def update_parent_topic_updated_at
end
end
- before_save :extract_mentioned_users
- def extract_mentioned_users
- logins = body.scan(/@(\w{3,20})/).flatten
- if logins.any?
- self.mentioned_user_ids = User.where(:login => /^(#{logins.join('|')})$/i, :_id.ne => user.id).limit(5).only(:_id).map(&:_id).to_a
- end
- end
-
- def mentioned_user_logins
- # 用于作为缓存 key
- ids_md5 = Digest::MD5.hexdigest(self.mentioned_user_ids.to_s)
- Rails.cache.fetch("reply:#{self.id}:mentioned_user_logins:#{ids_md5}") do
- User.where(:_id.in => self.mentioned_user_ids).only(:login).map(&:login)
- end
- end
-
- after_create :send_mention_notification, :send_topic_reply_notification
- def send_mention_notification
- self.mentioned_user_ids.each do |user_id|
- Notification::Mention.create :user_id => user_id, :reply => self
- end
- end
-
+ after_create :send_topic_reply_notification
def send_topic_reply_notification
if self.user != topic.user && !mentioned_user_ids.include?(topic.user_id)
Notification::TopicReply.create :user => topic.user, :reply => self
@@ -73,5 +51,6 @@ def send_topic_reply_notification
def destroy
super
notifications.delete_all
+ notification_mentions.delete_all
end
end
View
51 app/views/notifications/notification/_mention.html.erb
@@ -1,25 +1,30 @@
<%
- reply = notification.reply
- topic = reply.topic
+ case notification.mentionable
+ when Reply
%>
-<td class="face">
- <%= user_avatar_tag(reply.user, :normal) %>
-</td>
-<td>
- <h3>
- <span class="user">
- <%= user_name_tag(reply.user) %>
- </span>
- 在
- <%= render_topic_title(topic) %>
- 提及你:
- <% if !notification.read? %>
- <span class="new label warning">新</span>
- <% end %>
- </h3>
- <%- if reply.present? -%>
- <div class="body md_body">
- <%= raw reply.body_html %>
- </div>
- <%- end -%>
-</td>
+ <%
+ reply = notification.mentionable
+ topic = reply.topic
+ %>
+ <td class="face">
+ <%= user_avatar_tag(reply.user, :normal) %>
+ </td>
+ <td>
+ <h3>
+ <span class="user">
+ <%= user_name_tag(reply.user) %>
+ </span>
+ 在
+ <%= render_topic_title(topic) %>
+ 提及你:
+ <% if !notification.read? %>
+ <span class="new label warning">新</span>
+ <% end %>
+ </h3>
+ <%- if reply.present? -%>
+ <div class="body md_body">
+ <%= raw reply.body_html %>
+ </div>
+ <%- end -%>
+ </td>
+<% end %>
View
19 db/migrate/20120422061501_reply_mention_to_mentionable.rb
@@ -0,0 +1,19 @@
+class ReplyMentionToMentionable < Mongoid::Migration
+ def self.up
+ Notification::Mention.where(:reply_id.ne => nil).each do |mention|
+ mention[:mentionable_id] = mention["reply_id"]
+ mention[:mentionable_type] = 'Reply'
+ mention.save
+ mention.unset :reply_id
+ end
+ end
+
+ def self.down
+ Notification::Mention.where(:reply_id => nil).each do |mention|
+ mention["reply_id"] = mention["mentionable_id"]
+ mention.save
+ mention.unset :mentionable_id
+ mention.unset :mentionable_type
+ end
+ end
+end
View
6 spec/controllers/notifications_controller_spec.rb
@@ -5,7 +5,7 @@
describe "#index" do
it "should show notifications" do
sign_in user
- Factory :notification_mention, :user => user
+ Factory :notification_mention, :user => user, :mentionable => Factory(:reply)
Factory :notification_topic_reply, :user => user
get :index
response.should render_template(:index)
@@ -15,7 +15,7 @@
describe "#destroy" do
it "should destroy notification" do
sign_in user
- notification = Factory :notification_mention, :user => user
+ notification = Factory :notification_mention, :user => user, :mentionable => Factory(:reply)
lambda do
delete :destroy, :id => notification
@@ -26,7 +26,7 @@
describe "#mark_all_as_read" do
it "should mark all as read" do
sign_in user
- 3.times{ Factory :notification_mention, :user => user }
+ 3.times{ Factory :notification_mention, :user => user, :mentionable => Factory(:reply) }
put :mark_all_as_read
user.notifications.unread.count.should == 0
View
4 spec/controllers/topics_controller_spec.rb
@@ -89,10 +89,10 @@
describe "#show" do
it "should clear user mention notification when show topic" do
- notification = Factory :notification_mention
+ notification = Factory :notification_mention, :mentionable => Factory(:reply)
sign_in notification.user
lambda do
- get :show, :id => notification.reply.topic
+ get :show, :id => notification.mentionable.topic
end.should change(notification.user.notifications.unread, :count)
end
View
1  spec/factories/notification_mentions.rb
@@ -1,5 +1,4 @@
FactoryGirl.define do
factory :notification_mention, :class => Notification::Mention, :parent => :notification_base do
- association :reply
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.