diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index 98f453424..5569ec165 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -17,17 +17,25 @@ class MessagesController < ApplicationController @page = params[:page] || 1 @page_size = params[:page_size] || 15 - sort = params[:sort] || 0 + sort = params[:sort].to_i == 1 ? 'asc' : 'desc' sort_type = params[:sort_type] || 'time' - sort = sort.to_i - sort_type = sort_type.strip - @messages = @board.messages.root_nodes.by_keywords(params[:search]).includes(:praise_treads, :author, :children) - @messages = @messages.ordered(sort: sort, sort_type: sort_type) - @messages = sort_by_all_replies(sort, sort_type, @messages) + messages = @board.messages.root_nodes.by_keywords(params[:search]) - @messages = sort_by_sticky(@messages) - @messages = Kaminari.paginate_array(@messages).page(@page).per(@page_size) + messages = messages.order('(sticky = 1) DESC') # 置顶 + + messages = + case sort_type + when 'time' then messages.reorder("created_on #{sort}") + when 'hot' then messages.reorder("descendants_count #{sort}") + else messages.reorder("created_on #{sort}") + end + + messages = messages.includes(:author) + @messages = Kaminari.paginate_array(messages).page(@page).per(@page_size) + + ids = @messages.map(&:id) + @praises_count_map = Message.where(root_id: ids).group(:root_id).sum(:praises_count) end def reply_list @@ -43,33 +51,16 @@ class MessagesController < ApplicationController def reply return normal_status(2, "回复内容不能为空") if params[:content].blank? - begin - @reply = Message.create!(board: @message.board, - author: current_user, - parent: @message, - message_detail_attributes: { + @reply = Message.create!(board: @message.board, root: @message.root, author: current_user, parent: @message, + message_detail_attributes: { content: params[:content] - } - ) - rescue Exception => e - uid_logger_error(e.message) - tip_exception(e.message) - raise ActiveRecord::Rollback - end + }) end def sticky_top return normal_status(403, "您没有权限进行该操作") unless current_user.teacher_of_course?(@message.board.course) - ActiveRecord::Base.transaction do - begin - @message.update_attributes(:sticky => @message.sticky == 1 ? 0 : 1) - rescue Exception => e - uid_logger_error(e.message) - tip_exception(e.message) - raise ActiveRecord::Rollback - end - end + @message.update_attributes(:sticky => @message.sticky == 1 ? 0 : 1) end def bulk_delete diff --git a/app/models/message.rb b/app/models/message.rb index d3d507a72..c3b3bca40 100644 --- a/app/models/message.rb +++ b/app/models/message.rb @@ -4,6 +4,8 @@ class Message < ApplicationRecord belongs_to :board, counter_cache: true belongs_to :author, class_name: "User", foreign_key: 'author_id' belongs_to :parent, class_name: "Message", foreign_key: "parent_id", counter_cache: :replies_count, optional: true + belongs_to :root, class_name: 'Message', foreign_key: :root_id, counter_cache: :descendants_count, optional: true + has_one :message_detail, dependent: :destroy accepts_nested_attributes_for :message_detail, update_only: true @@ -12,6 +14,7 @@ class Message < ApplicationRecord has_many :tidings, as: :container, dependent: :destroy has_many :attachments, as: :container, dependent: :destroy has_many :course_acts, :class_name => 'CourseActivity',:as =>:course_act ,:dependent => :destroy # 课程动态 + has_many :descendants, class_name: 'Message', foreign_key: :root_id, dependent: :destroy scope :root_nodes, -> { where("parent_id IS NULL") } #判断该信息是帖子还是回复。null为发布的帖子 scope :reply_nodes, -> { where("parent_id IS NOT NULL") } @@ -70,24 +73,16 @@ class Message < ApplicationRecord # 包含二级回复的总点赞数 def total_praises_count - praises_count + children.includes(:children).reduce(0) { |count, filed| - sub_sum_count = filed.children.reduce(0) { |sub_count, sub_filed| sub_count += sub_filed.praises_count } - count += filed.praises_count - sub_sum_count += count - } + descendants.sum(:praises_count) end # 包含二级回复数的总回复数 def total_replies_count - replies_count + children.includes(:children).reduce(0) { |count, child| - sub_sum_count = child.children.reduce(0) { |sub_count, sub_child| sub_count += sub_child.replies_count } - count += child.replies_count - sub_sum_count += count - } + descendants_count end def has_replies - children.present? + children.exists? end # diff --git a/app/views/messages/index.json.jbuilder b/app/views/messages/index.json.jbuilder index 026e193a6..60d35e769 100644 --- a/app/views/messages/index.json.jbuilder +++ b/app/views/messages/index.json.jbuilder @@ -6,6 +6,11 @@ json.data do json.total_count @messages.total_count json.messages do json.array! @messages do |message| + json.extract! message, :id, :parent_id, :subject, :created_on, :total_replies_count, + :praises_count, :visits, :sticky, :is_hidden, :is_public + + json.total_praises_count @praises_count_map.fetch(message.id, 0) + json.partial! "messages/message", message: message json.author do json.partial! "users/user_simple", user: message.author diff --git a/db/migrate/20190621083604_add_descendants_count_to_messages.rb b/db/migrate/20190621083604_add_descendants_count_to_messages.rb new file mode 100644 index 000000000..02b721583 --- /dev/null +++ b/db/migrate/20190621083604_add_descendants_count_to_messages.rb @@ -0,0 +1,5 @@ +class AddDescendantsCountToMessages < ActiveRecord::Migration[5.2] + def change + add_column :messages, :descendants_count, :integer, default: 0 + end +end diff --git a/lib/tasks/course_board_message_count.rake b/lib/tasks/course_board_message_count.rake index 35e439403..49f33c615 100644 --- a/lib/tasks/course_board_message_count.rake +++ b/lib/tasks/course_board_message_count.rake @@ -20,6 +20,23 @@ namespace :course_board do end end + desc 'transfer root id && statistic descendants count' + task messages_descendants_count_transfer: :environment do + Message.root_nodes.find_each do |root| + logger("Current transfer root id: #{root.id} ~") + children_ids = root.children.pluck(:id) + next if children_ids.blank? + + second_children_ids = Message.where(parent_id: children_ids).pluck(:id) + + ids = children_ids.concat(second_children_ids).uniq + Message.where(id: ids).update_all(root_id: root.id) + + Message.reset_counters(root.id, :descendants) + logger("transfer success ~") + end + end + def logger(msg) puts msg end