Merge pull request #880 from consul/debates-search

Debates search
This commit is contained in:
Juanjo Bazán
2016-02-05 09:47:14 +01:00
5 changed files with 80 additions and 80 deletions

View File

@@ -6,6 +6,7 @@ class Debate < ActiveRecord::Base
include Measurable
include Sanitizable
include PgSearch
include SearchCache
include Filterable
apply_simple_captcha
@@ -41,21 +42,28 @@ class Debate < ActiveRecord::Base
visitable # Ahoy will automatically assign visit_id on create
pg_search_scope :pg_search, {
against: {
title: 'A',
description: 'B'
},
associated_against: {
tags: :name
},
against: :ignored, # not used since the using: option has a tsvector_column
using: {
tsearch: { dictionary: "spanish" },
tsearch: { dictionary: "spanish", tsvector_column: 'tsv', prefix: true }
},
ignoring: :accents,
ranked_by: '(:tsearch)',
order_within_rank: "debates.cached_votes_up DESC"
}
def searchable_values
{ title => 'A',
author.username => 'B',
tag_list.join(' ') => 'B',
geozone.try(:name) => 'B',
description => 'D'
}
end
def self.search(terms)
self.pg_search(terms)
end
def description
super.try :html_safe
end
@@ -121,15 +129,6 @@ class Debate < ActiveRecord::Base
cached_votes_up)
end
def self.search(terms)
return none unless terms.present?
debate_ids = where("debates.title ILIKE ? OR debates.description ILIKE ?",
"%#{terms}%", "%#{terms}%").pluck(:id)
tag_ids = tagged_with(terms, wild: true, any: true).pluck(:id)
where(id: [debate_ids, tag_ids].flatten.compact)
end
def after_hide
self.tags.each{ |t| t.decrement_custom_counter_for('Debate') }
end

View File

@@ -0,0 +1,13 @@
class AddTsvectorToDebates < ActiveRecord::Migration
def up
add_column :debates, :tsv, :tsvector
add_index :debates, :tsv, using: "gin"
end
def down
remove_index :debates, :tsv
remove_column :debates, :tsv
end
end

View File

@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20160126090634) do
ActiveRecord::Schema.define(version: 20160204134022) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -120,6 +120,7 @@ ActiveRecord::Schema.define(version: 20160126090634) do
t.integer "confidence_score", default: 0
t.string "external_link", limit: 100
t.integer "geozone_id"
t.tsvector "tsv"
end
add_index "debates", ["author_id", "hidden_at"], name: "index_debates_on_author_id_and_hidden_at", using: :btree
@@ -134,6 +135,7 @@ ActiveRecord::Schema.define(version: 20160126090634) do
add_index "debates", ["hidden_at"], name: "index_debates_on_hidden_at", using: :btree
add_index "debates", ["hot_score"], name: "index_debates_on_hot_score", using: :btree
add_index "debates", ["title"], name: "index_debates_on_title", using: :btree
add_index "debates", ["tsv"], name: "index_debates_on_tsv", using: :gin
create_table "delayed_jobs", force: :cascade do |t|
t.integer "priority", default: 0, null: false

View File

@@ -778,32 +778,32 @@ feature 'Debates' do
end
end
xscenario "Order by relevance by default", :js do
scenario "Order by relevance by default", :js do
debate1 = create(:debate, title: "Show you got", cached_votes_up: 10)
debate2 = create(:debate, title: "Show what you got", cached_votes_up: 1)
debate3 = create(:debate, title: "Show you got", cached_votes_up: 100)
visit debates_path
fill_in "search", with: "Show what you got"
fill_in "search", with: "Show you got"
click_button "Search"
expect(page).to have_selector("a.active", text: "relevance")
within("#debates") do
expect(all(".debate")[0].text).to match "Show what you got"
expect(all(".debate")[0].text).to match "Show you got"
expect(all(".debate")[1].text).to match "Show you got"
expect(all(".debate")[2].text).to match "Show you got"
expect(all(".debate")[2].text).to match "Show what you got"
end
end
xscenario "Reorder results maintaing search", :js do
scenario "Reorder results maintaing search", :js do
debate1 = create(:debate, title: "Show you got", cached_votes_up: 10, created_at: 1.week.ago)
debate2 = create(:debate, title: "Show what you got", cached_votes_up: 1, created_at: 1.month.ago)
debate3 = create(:debate, title: "Show you got", cached_votes_up: 100, created_at: Time.now)
debate4 = create(:debate, title: "Do not display", cached_votes_up: 1, created_at: 1.week.ago)
visit debates_path
fill_in "search", with: "Show what you got"
fill_in "search", with: "Show you got"
click_button "Search"
click_link 'newest'
expect(page).to have_selector("a.active", text: "newest")
@@ -960,12 +960,12 @@ feature 'Debates' do
debate5 = create(:debate, title: "Fifth debate has 5 votes", cached_votes_up: 5)
debate6 = create(:debate, title: "Sixth debate has 6 votes", description: 'This is the sixth debate', cached_votes_up: 6)
debate7 = create(:debate, title: "This has seven votes, and is not suggest", description: 'This is the seven', cached_votes_up: 7)
visit new_debate_path
fill_in 'debate_title', with: 'debate'
fill_in 'debate_title', with: 'debate'
check "debate_terms_of_service"
within('div#js-suggest') do
within('div#js-suggest') do
expect(page).to have_content ("You are seeing 5 of 6 debates containing the term 'debate'")
end
end
@@ -976,14 +976,14 @@ feature 'Debates' do
debate1 = create(:debate, title: "First debate has 10 vote", cached_votes_up: 10)
debate2 = create(:debate, title: "Second debate has 2 votes", cached_votes_up: 2)
visit new_debate_path
fill_in 'debate_title', with: 'proposal'
check "debate_terms_of_service"
check "debate_terms_of_service"
within('div#js-suggest') do
expect(page).to_not have_content ('You are seeing')
end
end
end
end
end

View File

@@ -436,26 +436,26 @@ describe Debate do
context "attributes" do
xit "searches by title" do
it "searches by title" do
debate = create(:debate, title: 'save the world')
results = Debate.search('save the world')
expect(results).to eq([debate])
end
xit "searches by description" do
it "searches by description" do
debate = create(:debate, description: 'in order to save the world one must think about...')
results = Debate.search('one must think')
expect(results).to eq([debate])
end
xit "searches by author name" do
it "searches by author name" do
author = create(:user, username: 'Danny Trejo')
debate = create(:debate, author: author)
results = Debate.search('Danny')
expect(results).to eq([debate])
end
xit "searches by geozone" do
it "searches by geozone" do
geozone = create(:geozone, name: 'California')
debate = create(:debate, geozone: geozone)
results = Debate.search('California')
@@ -466,7 +466,7 @@ describe Debate do
context "stemming" do
xit "searches word stems" do
it "searches word stems" do
debate = create(:debate, title: 'limpiar')
results = Debate.search('limpiará')
@@ -483,7 +483,7 @@ describe Debate do
context "accents" do
xit "searches with accents" do
it "searches with accents" do
debate = create(:debate, title: 'difusión')
results = Debate.search('difusion')
@@ -492,13 +492,16 @@ describe Debate do
debate2 = create(:debate, title: 'estadisticas')
results = Debate.search('estadísticas')
expect(results).to eq([debate2])
debate3 = create(:debate, title: 'público')
results = Debate.search('publico')
expect(results).to eq([debate3])
end
end
context "case" do
xit "searches case insensite" do
it "searches case insensite" do
debate = create(:debate, title: 'SHOUT')
results = Debate.search('shout')
@@ -508,27 +511,23 @@ describe Debate do
results = Debate.search("SCREAM")
expect(results).to eq([debate2])
end
end
context "typos" do
context "tags" do
it "searches by tags" do
debate = create(:debate, tag_list: 'Latina')
xit "searches with typos" do
debate = create(:debate, title: 'difusión')
results = Debate.search('Latina')
expect(results.first).to eq(debate)
results = Debate.search('difuon')
expect(results).to eq([debate])
debate2 = create(:debate, title: 'desarrollo')
results = Debate.search('desarolo')
expect(results).to eq([debate2])
results = Debate.search('Latin')
expect(results.first).to eq(debate)
end
end
context "order" do
xit "orders by weight" do
it "orders by weight" do
debate_description = create(:debate, description: 'stop corruption')
debate_title = create(:debate, title: 'stop corruption')
@@ -538,7 +537,7 @@ describe Debate do
expect(results.second).to eq(debate_description)
end
xit "orders by weight and then votes" do
it "orders by weight and then votes" do
title_some_votes = create(:debate, title: 'stop corruption', cached_votes_up: 5)
title_least_voted = create(:debate, title: 'stop corruption', cached_votes_up: 2)
title_most_voted = create(:debate, title: 'stop corruption', cached_votes_up: 10)
@@ -547,28 +546,26 @@ describe Debate do
results = Debate.search('stop corruption')
expect(results.first).to eq(title_most_voted)
expect(results.second).to eq(description_most_voted)
expect(results.third).to eq(title_some_votes)
expect(results.fourth).to eq(title_least_voted)
expect(results.second).to eq(title_some_votes)
expect(results.third).to eq(title_least_voted)
expect(results.fourth).to eq(description_most_voted)
end
xit "orders by weight and then votes and then created_at" do
newest = create(:debate, title: 'stop corruption', cached_votes_up: 5, created_at: Time.now)
oldest = create(:debate, title: 'stop corruption', cached_votes_up: 5, created_at: 1.month.ago)
old = create(:debate, title: 'stop corruption', cached_votes_up: 5, created_at: 1.week.ago)
it "gives much more weight to word matches than votes" do
exact_title_few_votes = create(:debate, title: 'stop corruption', cached_votes_up: 5)
similar_title_many_votes = create(:debate, title: 'stop some of the corruption', cached_votes_up: 500)
results = Debate.search('stop corruption')
expect(results.first).to eq(newest)
expect(results.second).to eq(old)
expect(results.third).to eq(oldest)
expect(results.first).to eq(exact_title_few_votes)
expect(results.second).to eq(similar_title_many_votes)
end
end
context "reorder" do
xit "should be able to reorder by hot_score after searching" do
it "should be able to reorder by hot_score after searching" do
lowest_score = create(:debate, title: 'stop corruption', cached_votes_up: 1)
highest_score = create(:debate, title: 'stop corruption', cached_votes_up: 2)
average_score = create(:debate, title: 'stop corruption', cached_votes_up: 3)
@@ -590,7 +587,7 @@ describe Debate do
expect(results.third).to eq(lowest_score)
end
xit "should be able to reorder by confidence_score after searching" do
it "should be able to reorder by confidence_score after searching" do
lowest_score = create(:debate, title: 'stop corruption', cached_votes_up: 1)
highest_score = create(:debate, title: 'stop corruption', cached_votes_up: 2)
average_score = create(:debate, title: 'stop corruption', cached_votes_up: 3)
@@ -612,7 +609,7 @@ describe Debate do
expect(results.third).to eq(lowest_score)
end
xit "should be able to reorder by created_at after searching" do
it "should be able to reorder by created_at after searching" do
recent = create(:debate, title: 'stop corruption', cached_votes_up: 1, created_at: 1.week.ago)
newest = create(:debate, title: 'stop corruption', cached_votes_up: 2, created_at: Time.now)
oldest = create(:debate, title: 'stop corruption', cached_votes_up: 3, created_at: 1.month.ago)
@@ -630,7 +627,7 @@ describe Debate do
expect(results.third).to eq(oldest)
end
xit "should be able to reorder by most commented after searching" do
it "should be able to reorder by most commented after searching" do
least_commented = create(:debate, title: 'stop corruption', cached_votes_up: 1, comments_count: 1)
most_commented = create(:debate, title: 'stop corruption', cached_votes_up: 2, comments_count: 100)
some_comments = create(:debate, title: 'stop corruption', cached_votes_up: 3, comments_count: 10)
@@ -650,41 +647,30 @@ describe Debate do
end
context "tags" do
xit "searches by tags" do
debate = create(:debate, tag_list: 'Latina')
results = Debate.search('Latina')
expect(results.first).to eq(debate)
end
end
context "no results" do
xit "no words match" do
it "no words match" do
debate = create(:debate, title: 'save world')
results = Debate.search('destroy planet')
expect(results).to eq([])
end
xit "too many typos" do
it "too many typos" do
debate = create(:debate, title: 'fantastic')
results = Debate.search('frantac')
expect(results).to eq([])
end
xit "too much stemming" do
it "too much stemming" do
debate = create(:debate, title: 'reloj')
results = Debate.search('superrelojimetro')
expect(results).to eq([])
end
xit "empty" do
it "empty" do
debate = create(:debate, title: 'great')
results = Debate.search('')