filter by tag and domain when searching for comments

This commit is contained in:
David Wolgemuth 2018-06-11 18:28:11 -05:00 committed by Peter Bhat Harkins
parent 86ac9887b8
commit c1681a4063
4 changed files with 101 additions and 20 deletions

View File

@ -47,4 +47,5 @@ group :test, :development do
gem "sqlite3"
gem "faker"
gem "byebug"
gem "rb-readline"
end

View File

@ -153,6 +153,7 @@ GEM
rb-fsevent (0.10.3)
rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2)
rb-readline (0.5.5)
rotp (3.3.1)
rqrcode (0.10.1)
chunky_png (~> 1.0)
@ -241,6 +242,7 @@ DEPENDENCIES
nokogiri (>= 1.7.2)
oauth
rails (~> 5.2.0)
rb-readline
rotp
rqrcode
rspec-rails

View File

@ -61,6 +61,23 @@ class Search
.group("stories.id")
end
def with_stories_in_domain(base, domain)
begin
reg = Regexp.new("//([^/]*\.)?#{domain}/")
base.where("`stories`.`url` REGEXP '" +
ActiveRecord::Base.connection.quote_string(reg.source) + "'")
rescue RegexpError
return base
end
end
def with_stories_matching_tags(base, tag_scopes)
story_ids_matching_tags = with_tags(
Story.unmerged.where(:is_expired => false), tag_scopes
).select(:id).map(&:id)
base.where(story_id: story_ids_matching_tags)
end
def search_for_user!(user)
self.results = []
self.total_results = 0
@ -84,13 +101,7 @@ class Search
when "stories"
base = Story.unmerged.where(:is_expired => false)
if domain.present?
begin
reg = Regexp.new("//([^/]*\.)?#{domain}/")
base = base.where("`url` REGEXP '" +
ActiveRecord::Base.connection.quote_string(reg.source) + "'")
rescue RegexpError
return false
end
base = with_stories_in_domain(base, domain)
end
title_match_sql = Arel.sql("MATCH(stories.title) AGAINST('#{qwords}' IN BOOLEAN MODE)")
@ -138,17 +149,20 @@ class Search
end
when "comments"
base = Comment.active.where(Arel.sql("MATCH(comment) AGAINST('#{qwords}' IN BOOLEAN MODE)"))
.includes(:user, :story)
base = Comment.active
if domain.present?
base = with_stories_in_domain(base.joins(:story), domain)
end
if tag_scopes.present?
base = with_stories_matching_tags(base, tag_scopes)
end
if qwords.present?
base = base.where(Arel.sql("MATCH(comment) AGAINST('#{qwords}' IN BOOLEAN MODE)"))
end
self.results = base.select(
"comments.*, " +
"MATCH(comment) AGAINST('#{qwords}' IN BOOLEAN MODE) AS rel_comment"
)
if tag_scopes.present?
self.results = with_tags(base, tag_scopes)
end
).includes(:user, :story)
case self.order
when "relevance"
@ -158,12 +172,8 @@ class Search
when "points"
self.results.order!("#{Comment.score_sql} DESC")
end
end
if tag_scopes.present?
self.total_results = self.results.length
else
self.total_results = base.count
end
if self.page > self.page_count

View File

@ -31,11 +31,29 @@ describe Search do
:user_id => @user.id,
:tags_a => ["tag1"]),
]
@comments = [
create(:comment, :comment => "comment0",
:story_id => @multi_tag.id,
:user_id => @user.id),
create(:comment, :comment => "comment1",
:story_id => @stories[0].id,
:user_id => @user.id),
create(:comment, :comment => "comment2",
:story_id => @stories[1].id,
:user_id => @user.id),
create(:comment, :comment => "comment3",
:story_id => @stories[2].id,
:user_id => @user.id),
create(:comment, :comment => "comment4",
:story_id => @stories[4].id,
:user_id => @user.id),
]
end
after(:all) do
@user.destroy!
@comments.each(&:destroy!)
@stories.each(&:destroy!)
@user.destroy! if @user
end
it "can search for stories" do
@ -103,4 +121,54 @@ describe Search do
expect(search.results.length).to eq(2)
end
it "can search for comments" do
search = Search.new
search.q = "comment1"
search.what = "comments"
search.search_for_user!(@user)
expect(search.results).to include(@comments[1])
end
it "can search for comments by tag" do
search = Search.new
search.q = "comment2 comment3 tag:tag1"
search.what = "comments"
search.search_for_user!(@user)
expect(search.results).to include(@comments[2])
expect(search.results).not_to include(@comments[3])
end
it "can search for comments with only tags" do
search = Search.new
search.q = "tag:tag1"
search.what = "comments"
search.search_for_user!(@user)
expect(search.results).to include(@comments[2])
expect(search.results).not_to include(@comments[3])
end
it "should only return comments matching all tags if multiple are present" do
search = Search.new
search.q = "tag:tag1 tag:tag2"
search.what = "comments"
search.search_for_user!(@user)
expect(search.results).to eq([@comments[0]])
end
it "should only return comments with stories in domain if domain present" do
search = Search.new
search.q = "comment3 comment4 domain:lobste.rs"
search.what = "comments"
search.search_for_user!(@user)
expect(search.results).to include(@comments[4])
expect(search.results).not_to include(@comments[3])
end
end