Permalink
Browse files

Add suggestions to search results when nothing is found according to …

…user's query.
  • Loading branch information...
1 parent bfdf210 commit fba2f5462f1a90da089d7039b105782f5b48668f @zuhao committed Feb 21, 2013
Showing with 46 additions and 6 deletions.
  1. +1 −0 Gemfile
  2. +2 −0 Gemfile.lock
  3. +3 −3 TODO.txt
  4. +17 −2 app/controllers/searches_controller.rb
  5. +23 −1 app/views/searches/index.html.haml
View
@@ -35,6 +35,7 @@ gem 'gems'
gem 'recaptcha', :require => 'recaptcha/rails'
gem 'pkgwat'
gem 'ruby-bugzilla'
+gem 'text'
group :test, :development do
gem 'rspec-rails'
View
@@ -189,6 +189,7 @@ GEM
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
sqlite3 (1.3.7)
+ text (1.2.1)
therubyracer (0.10.2)
libv8 (~> 3.3.10)
thor (0.14.6)
@@ -237,6 +238,7 @@ DEPENDENCIES
ruby_parser
sass-rails (~> 3.2.3)
sqlite3
+ text
therubyracer (~> 0.10.2)
thor (= 0.14.6)
uglifier (>= 1.0.3)
View
@@ -10,13 +10,13 @@
- [ ] Allow one to set update options interactively
- [ ] Allow one to pause/continue update
-** TODO Add decent robots.txt
+** TODO Add decent robots.txt
** TODO Fix "most wanted gems" (or erase)
-** TODO Make a nice error message appear when a user types a wrong URL
+** DONE Make a nice error message appear when a user types a wrong URL
-> Example: http://www.isitfedoraruby.com/fedorarpms/non-existent-rpm
-- [ ] It would be totally awesome to have a "did you mean...?" sign
+- [x] It would be totally awesome to have a "did you mean...?" sign
** TODO furthur improve import mechanism
- Instead of scraping websites, we should use the APIs for git, bugzilla,
@@ -1,20 +1,35 @@
+require 'text'
+
class SearchesController < ApplicationController
def index
@page_title = 'Search'
searchphrase = params[:id]
@results = RubyGem.where('name LIKE ?', "%#{searchphrase}%").paginate(:page => params[:page], :per_page => 50, :group => "name", :order => "length(name) asc")
+ @suggests = []
+ if @results == []
+ all_gems = RubyGem.select('name').map{|x| x.name}
+ dist_score = Hash[all_gems.map{|x| [x, Text::Levenshtein.distance(x, searchphrase)]}]
+ dist_score = dist_score.sort_by{|x,d| d}.collect{|x,d| x}
+ sim_score = Hash[all_gems.map{|x| [x, Text::WhiteSimilarity.similarity(x, searchphrase)]}]
+ sim_score = sim_score.sort_by{|x,s| s}.reverse.collect{|x,s| x}
+ # suggestions are intersection of max similarity and min Levenshtein distance
+ # 50 is arbitrary, usually it is more than enough to give a good result.
+ @suggests = sim_score[0..50] & dist_score[0..50]
+ # give maximum 5 suggestions
+ @suggests = @suggests[0..4].map{|x| RubyGem.find_by_name(x)}
+ end
end
def suggest_gems (result = [])
@gems = RubyGem.where("name like ?", "%#{params[:q]}%").limit(10)
@gems.each { |g|
result << {:name => g.name}
- }
+ }
respond_to do |format|
format.json { render :json => result.to_json }
end
- end
+ end
def redirect
if params[:search]
@@ -1,3 +1,4 @@
+
%h1 Search Results
- if @results != []
@@ -23,4 +24,25 @@
%div.pagination
= will_paginate @results
- else
- %h2 Sorry, there were no results when searching for the Ruby Gem "#{params[:id]}"
+ %h2 Sorry, there were no results when searching for the Ruby Gem "#{params[:id]}"
+ %h2 However, did you mean...
+ - if @suggests != []
+ %table.table.table-striped.table-condensed
+ %thead
+ %tr
+ %th Gem Name
+ %th Gem Version
+ %th Rpm Name
+ %th Rpm Version (Rawhide)
+
+ %tbody
+ - @suggests.each do |gem|
+ %tr
+ %td= link_to gem.name, rubygem_path(gem.name)
+ %td= gem.version
+ - if gem.fedora_rpm != nil
+ %td= link_to gem.fedora_rpm.name, fedorarpm_path(gem.fedora_rpm.name)
+ %td= gem.fedora_rpm.version_for('rawhide')
+ -else
+ %td
+ %td

0 comments on commit fba2f54

Please sign in to comment.