Use search context for filtering search results by current category or user
This commit is contained in:
parent
f4640e3bff
commit
bd779834e5
|
@ -2,12 +2,39 @@ require_dependency 'search'
|
|||
|
||||
class SearchController < ApplicationController
|
||||
|
||||
def query
|
||||
search = Search.new(params[:term],
|
||||
guardian: guardian,
|
||||
type_filter: params[:type_filter])
|
||||
def self.valid_context_types
|
||||
%w{user topic category}
|
||||
end
|
||||
|
||||
def query
|
||||
requires_parameter(:term)
|
||||
|
||||
search_args = {guardian: guardian}
|
||||
search_args[:type_filter] = params[:type_filter] if params[:type_filter].present?
|
||||
|
||||
search_context = params[:search_context]
|
||||
if search_context.present?
|
||||
raise Discourse::InvalidParameters.new(:search_context) unless SearchController.valid_context_types.include?(search_context[:type])
|
||||
raise Discourse::InvalidParameters.new(:search_context) if search_context[:id].blank?
|
||||
|
||||
klass = search_context[:type].classify.constantize
|
||||
|
||||
# A user is found by username
|
||||
context_obj = nil
|
||||
if search_context[:type] == 'user'
|
||||
context_obj = klass.where(username: params[:search_context][:id]).first
|
||||
else
|
||||
context_obj = klass.where(id: params[:search_context][:id]).first
|
||||
end
|
||||
|
||||
guardian.ensure_can_see!(context_obj)
|
||||
search_args[:search_context] = context_obj
|
||||
end
|
||||
|
||||
search = Search.new(params[:term], search_args.symbolize_keys)
|
||||
render_json_dump(search.execute.as_json)
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
|
|
@ -35,6 +35,7 @@ class Search
|
|||
|
||||
@opts = opts || {}
|
||||
@guardian = @opts[:guardian] || Guardian.new
|
||||
@search_context = @opts[:search_context]
|
||||
@limit = Search.per_facet * Search.facets.size
|
||||
@results = GroupedSearchResults.new(@opts[:type_filter])
|
||||
end
|
||||
|
@ -142,6 +143,19 @@ class Search
|
|||
.order("topics.bumped_at DESC")
|
||||
.limit(limit)
|
||||
|
||||
# Search context post results
|
||||
if @search_context.present?
|
||||
|
||||
if @search_context.is_a?(User)
|
||||
# If the context is a user, restrict posts to that user
|
||||
posts = posts.where(user_id: @search_context.id)
|
||||
elsif @search_context.is_a?(Category)
|
||||
# If the context is a category, restrict posts to that category
|
||||
posts = posts.where('topics.category_id' => @search_context.id)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if secure_category_ids.present?
|
||||
posts = posts.where("(categories.id IS NULL) OR (NOT categories.secure) OR (categories.id IN (?))", secure_category_ids)
|
||||
else
|
||||
|
|
|
@ -233,6 +233,30 @@ describe Search do
|
|||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context 'search_context' do
|
||||
|
||||
context 'user as a search context' do
|
||||
let(:search_user) { Search.new('hello', search_context: post.user).execute }
|
||||
let(:search_coding_horror) { Search.new('hello', search_context: Fabricate(:coding_horror)).execute }
|
||||
|
||||
Given!(:post) { Fabricate(:post) }
|
||||
Then { first_of_type(search_user, 'topic')['id'] == post.topic_id }
|
||||
And { first_of_type(search_coding_horror, 'topic').should be_blank }
|
||||
end
|
||||
|
||||
context 'category as a search context' do
|
||||
let(:category) { Fabricate(:category) }
|
||||
let(:search_cat) { Search.new('hello', search_context: category).execute }
|
||||
let(:search_other_cat) { Search.new('hello', search_context: Fabricate(:category) ).execute }
|
||||
let(:topic) { Fabricate(:topic, category: category) }
|
||||
|
||||
Given!(:post) { Fabricate(:post, topic: topic, user: topic.user ) }
|
||||
Then { first_of_type(search_cat, 'topic')['id'] == post.topic_id }
|
||||
Then { first_of_type(search_other_cat, 'topic').should be_blank }
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -2,12 +2,14 @@ require 'spec_helper'
|
|||
|
||||
describe SearchController do
|
||||
|
||||
let(:search_context) { {type: 'user', id: 'eviltrout'} }
|
||||
|
||||
it 'performs the query' do
|
||||
guardian = Guardian.new
|
||||
Guardian.stubs(:new).returns(guardian)
|
||||
|
||||
search = mock()
|
||||
Search.expects(:new).with('test', guardian: guardian, type_filter: nil).returns(search)
|
||||
Search.expects(:new).with('test', guardian: guardian).returns(search)
|
||||
search.expects(:execute)
|
||||
|
||||
xhr :get, :query, term: 'test'
|
||||
|
@ -24,4 +26,47 @@ describe SearchController do
|
|||
xhr :get, :query, term: 'test', type_filter: 'topic'
|
||||
end
|
||||
|
||||
context "search context" do
|
||||
|
||||
it "raises an error with an invalid context type" do
|
||||
lambda {
|
||||
xhr :get, :query, term: 'test', search_context: {type: 'security', id: 'hole'}
|
||||
}.should raise_error(Discourse::InvalidParameters)
|
||||
end
|
||||
|
||||
it "raises an error with a missing id" do
|
||||
lambda {
|
||||
xhr :get, :query, term: 'test', search_context: {type: 'user'}
|
||||
}.should raise_error(Discourse::InvalidParameters)
|
||||
end
|
||||
|
||||
context "with a user" do
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
|
||||
it "raises an error if the user can't see the context" do
|
||||
Guardian.any_instance.expects(:can_see?).with(user).returns(false)
|
||||
xhr :get, :query, term: 'test', search_context: {type: 'user', id: user.username}
|
||||
response.should_not be_success
|
||||
end
|
||||
|
||||
|
||||
it 'performs the query with a search context' do
|
||||
guardian = Guardian.new
|
||||
Guardian.stubs(:new).returns(guardian)
|
||||
|
||||
search = mock()
|
||||
Search.expects(:new).with('test', guardian: guardian, search_context: user).returns(search)
|
||||
search.expects(:execute)
|
||||
|
||||
xhr :get, :query, term: 'test', search_context: {type: 'user', id: user.username}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue