From 2295290383d46fb431cb10aa06db28e84a2e60d9 Mon Sep 17 00:00:00 2001 From: Sam Date: Wed, 27 Mar 2013 22:53:11 -0700 Subject: [PATCH] added best=N option to get N best comment on a post --- app/controllers/posts_controller.rb | 2 +- app/controllers/topics_controller.rb | 2 +- lib/topic_view.rb | 20 ++++++++++++++++---- spec/components/topic_view_spec.rb | 21 ++++++++++++++------- 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 1bc426c10dc..5815bb914ec 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -71,7 +71,7 @@ class PostsController < ApplicationController post_serializer.draft_sequence = DraftSequence.current(current_user, post.topic.draft_key) link_counts = TopicLinkClick.counts_for(post.topic, [post]) post_serializer.single_post_link_counts = link_counts[post.id] if link_counts.present? - + post_serializer.topic_slug = post.topic.slug if post.topic.present? result = {post: post_serializer.as_json} if revisor.category_changed.present? diff --git a/app/controllers/topics_controller.rb b/app/controllers/topics_controller.rb index f477852fbef..71a5b45c493 100644 --- a/app/controllers/topics_controller.rb +++ b/app/controllers/topics_controller.rb @@ -168,7 +168,7 @@ class TopicsController < ApplicationController private def create_topic_view - opts = params.slice(:username_filters, :best_of, :page, :post_number, :posts_before, :posts_after) + opts = params.slice(:username_filters, :best_of, :page, :post_number, :posts_before, :posts_after, :best) @topic_view = TopicView.new(params[:id] || params[:topic_id], current_user, opts) end diff --git a/lib/topic_view.rb b/lib/topic_view.rb index c918e96c499..21b9fb90d53 100644 --- a/lib/topic_view.rb +++ b/lib/topic_view.rb @@ -20,6 +20,8 @@ class TopicView Guardian.new(user).ensure_can_see!(@topic) @post_number, @page = options[:post_number], options[:page] + @limit = options[:limit] || SiteSetting.posts_per_page; + @filtered_posts = @topic.posts @filtered_posts = @filtered_posts.with_deleted if user.try(:admin?) @filtered_posts = @filtered_posts.best_of if options[:best_of].present? @@ -91,13 +93,16 @@ class TopicView return filter_posts_near(opts[:post_number].to_i) if opts[:post_number].present? return filter_posts_before(opts[:posts_before].to_i) if opts[:posts_before].present? return filter_posts_after(opts[:posts_after].to_i) if opts[:posts_after].present? + return filter_best(opts[:best]) if opts[:best].present? filter_posts_paged(opts[:page].to_i) end + # Find the sort order for a post in the topic def sort_order_for_post_number(post_number) Post.where(topic_id: @topic.id, post_number: post_number) .with_deleted + .select(:sort_order) .first .try(:sort_order) end @@ -148,14 +153,12 @@ class TopicView sort_order = sort_order_for_post_number(post_number) return nil unless sort_order - - # Find posts before the `sort_order` @posts = @filtered_posts.order('sort_order desc').where("sort_order < ?", sort_order) @index_offset = @posts.count @index_reverse = true - @posts = @posts.includes(:reply_to_user).includes(:topic).joins(:user).limit(SiteSetting.posts_per_page) + @posts = @posts.includes(:reply_to_user).includes(:topic).joins(:user).limit(@limit) end # Filter to all posts after a particular post number @@ -167,7 +170,16 @@ class TopicView @index_offset = @filtered_posts.where("sort_order <= ?", sort_order).count @posts = @filtered_posts.order('sort_order').where("sort_order > ?", sort_order) - @posts = @posts.includes(:reply_to_user).includes(:topic).joins(:user).limit(SiteSetting.posts_per_page) + @posts = @posts.includes(:reply_to_user).includes(:topic).joins(:user).limit(@limit) + end + + def filter_best(max) + @index_offset = 0 + @posts = @filtered_posts.order('percent_rank asc, sort_order asc').where("post_number > 1") + @posts = @posts.includes(:reply_to_user).includes(:topic).joins(:user).limit(max) + @posts = @posts.to_a + @posts.sort!{|a,b| a.post_number <=> b.post_number} + @posts end def read?(post_number) diff --git a/spec/components/topic_view_spec.rb b/spec/components/topic_view_spec.rb index cbf6927c499..e5eb30348e0 100644 --- a/spec/components/topic_view_spec.rb +++ b/spec/components/topic_view_spec.rb @@ -19,15 +19,22 @@ describe TopicView do end context "with a few sample posts" do - let!(:p1) { Fabricate(:post, topic: topic, user: first_poster )} - let!(:p2) { Fabricate(:post, topic: topic, user: coding_horror )} - let!(:p3) { Fabricate(:post, topic: topic, user: first_poster )} + let!(:p1) { Fabricate(:post, topic: topic, user: first_poster, percent_rank: 1 )} + let!(:p2) { Fabricate(:post, topic: topic, user: coding_horror, percent_rank: 0.5 )} + let!(:p3) { Fabricate(:post, topic: topic, user: first_poster, percent_rank: 0 )} + + it "it can the best 2 responses" do + best2 = TopicView.new(topic.id, nil, best: 2) + best2.posts.count.should == 2 + best2.posts[0].id.should == p2.id + best2.posts[1].id.should == p3.id + end - it "raises NotLoggedIn if the user isn't logged in and is trying to view a private message" do - Topic.any_instance.expects(:private_message?).returns(true) - lambda { TopicView.new(topic.id, nil) }.should raise_error(Discourse::NotLoggedIn) - end + it "raises NotLoggedIn if the user isn't logged in and is trying to view a private message" do + Topic.any_instance.expects(:private_message?).returns(true) + lambda { TopicView.new(topic.id, nil) }.should raise_error(Discourse::NotLoggedIn) + end it "provides an absolute url" do topic_view.absolute_url.should be_present