diff --git a/app/logical/post_sets/post.rb b/app/logical/post_sets/post.rb index 7ecd2acfa..cca5a44fe 100644 --- a/app/logical/post_sets/post.rb +++ b/app/logical/post_sets/post.rb @@ -115,7 +115,7 @@ module PostSets @post_count = get_post_count if is_random? - get_random_posts + get_random_posts.paginate(page, search_count: false, limit: per_page, max_limit: max_per_page).load else normalized_query.build.paginate(page, count: post_count, search_count: !post_count.nil?, limit: per_page, max_limit: max_per_page).load end diff --git a/app/models/post.rb b/app/models/post.rb index 94f8a7c0f..f3fbe1d98 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -1145,11 +1145,18 @@ class Post < ApplicationRecord end module SearchMethods + # Return a set of up to N random posts. May return less if there aren't + # enough posts. + # + # @param n [Integer] The maximum number of posts to return + # @return [ActiveRecord::Relation] def random(n = 1) - n.times.map do + posts = n.times.map do key = SecureRandom.hex(16) random_up(key) || random_down(key) end.compact.uniq + + find_ordered(posts.map(&:id)) end def random_up(key) diff --git a/test/functional/posts_controller_test.rb b/test/functional/posts_controller_test.rb index bc97bc278..aa2f7face 100644 --- a/test/functional/posts_controller_test.rb +++ b/test/functional/posts_controller_test.rb @@ -322,6 +322,15 @@ class PostsControllerTest < ActionDispatch::IntegrationTest get posts_path, params: { random: "1" } assert_response :success end + + should "return all posts for a .json response" do + create_list(:post, 2, tag_string: "honk_honk") + get posts_path, params: { tags: "honk_honk order:random" }, as: :json + + assert_response :success + assert_equal(true, response.parsed_body.is_a?(Array)) + assert_equal(2, response.parsed_body.size) + end end context "with the .atom format" do