diff --git a/Gemfile b/Gemfile index 2300f74..d4e4763 100644 --- a/Gemfile +++ b/Gemfile @@ -75,7 +75,7 @@ gem 'fancybox2-rails', '~> 0.2.4' #gem 'textacular', require: 'textacular/rails' # Trying pg_search for full-text search… too slow with ranking… screw PostgreSQL -#gem 'pg_search' +gem 'pg_search' # Let's use Elasticsearch. "tire" has been retired but there is not yet a worthy alternative. #gem 'tire' diff --git a/Gemfile.lock b/Gemfile.lock index b4e1ca4..1a8a3ad 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -25,7 +25,6 @@ GEM multi_json (~> 1.3) thread_safe (~> 0.1) tzinfo (~> 0.3.37) - ansi (1.4.3) arel (4.0.1) atomic (1.1.14) better_errors (1.0.1) @@ -51,7 +50,6 @@ GEM foundation-rails (5.4.5.0) railties (>= 3.1.0) sass (>= 3.2.0) - hashr (0.0.22) hike (1.2.3) i18n (0.6.5) jbuilder (1.5.2) @@ -61,9 +59,6 @@ GEM railties (>= 3.0, < 5.0) thor (>= 0.14, < 2.0) json (1.8.1) - kaminari (0.14.1) - actionpack (>= 3.0.0) - activesupport (>= 3.0.0) mail (2.5.4) mime-types (~> 1.16) treetop (~> 1.4.8) @@ -75,6 +70,10 @@ GEM minitest (4.7.5) multi_json (1.8.2) pg (0.17.0) + pg_search (0.7.8) + activerecord (>= 3.1) + activesupport (>= 3.1) + arel polyglot (0.3.3) rack (1.5.2) rack-contrib (1.1.0) @@ -97,8 +96,6 @@ GEM rake (10.1.0) rdoc (3.12.2) json (~> 1.4) - rest-client (1.6.7) - mime-types (>= 1.16) sass (3.2.12) sass-rails (4.0.1) railties (>= 4.0.0, < 5.0) @@ -129,14 +126,6 @@ GEM thread_safe (0.1.3) atomic tilt (1.4.1) - tire (0.6.1) - activemodel (>= 3.0) - activesupport - ansi - hashr (~> 0.0.19) - multi_json (~> 1.3) - rake - rest-client (~> 1.6) treetop (1.4.15) polyglot polyglot (>= 0.3.1) @@ -144,6 +133,7 @@ GEM uglifier (2.3.1) execjs (>= 0.3.0) json (>= 1.8.0) + will_paginate (3.0.7) PLATFORMS ruby @@ -156,12 +146,12 @@ DEPENDENCIES foundation-rails jbuilder (~> 1.2) jquery-rails - kaminari meta_request pg + pg_search rails (= 4.0.0) sass-rails (~> 4.0.0) sdoc slim-rails - tire uglifier (>= 1.3.0) + will_paginate diff --git a/README.Developer b/README.Developer new file mode 100644 index 0000000..c38f7b8 --- /dev/null +++ b/README.Developer @@ -0,0 +1,29 @@ +# Full text search + +The pg_search Ruby gem is used for full-text searched in Rails. +See: https://github.com/Casecommons/pg_search + +Reformatted SQL query for fulltext search: + +SELECT COUNT(*) FROM "packages" WHERE ( + ( + ( + to_tsvector('simple', coalesce("packages"."name"::text, '')) + || + to_tsvector('simple', coalesce("packages"."description"::text, '')) + || + to_tsvector('simple', coalesce("packages"."long_description"::text, '')) + ) + @@ + ( + to_tsquery('simple', '''' || 'browser' || ' ''') + ) + ) +) + +# Index: + +CREATE INDEX packages_gin ON packages USING GIN( (to_tsvector('simple', +coalesce("packages"."name"::text, '')) || to_tsvector('simple', +coalesce("packages"."description"::text, '')) || to_tsvector('simple', +coalesce("packages"."long_description"::text, ''))) ); diff --git a/app/controllers/packages_controller.rb b/app/controllers/packages_controller.rb index d0242b6..98e144e 100644 --- a/app/controllers/packages_controller.rb +++ b/app/controllers/packages_controller.rb @@ -6,6 +6,13 @@ class PackagesController < ApplicationController @packages = @packages.text_search(params[:query]) end + if params[:search] + logger.debug "Searching for #{params[:search]}" + #search_phrase = params[:search].split.join('&') + #@packages = @packages.general_search([:name,:description], search_phrase, :language=>'english', :rank=>true) + @packages = @packages.general_search(params[:search]) + end + # Limit the packages to those that have approved screenshots. # Also eager-load the screenshots. if params[:show]=='onlywith' diff --git a/app/models/package.rb b/app/models/package.rb index 6a78306..267a301 100644 --- a/app/models/package.rb +++ b/app/models/package.rb @@ -1,11 +1,16 @@ class Package < ActiveRecord::Base + # PostgreSQL-based full-text search: + # https://github.com/Casecommons/pg_search + include PgSearch + # TODO: Make search weighted on users' rating + pg_search_scope :general_search, :against => [:name, :description, :long_description] + has_many :screenshots, :inverse_of=>:package default_scope { order('name ASC') } - # Return a query of all packages that have screenshots def self.with_screenshots # Query for all packages who's ID appears in a screenshot's "package_id" field diff --git a/app/views/packages/_sidebar.slim b/app/views/packages/_sidebar.slim index 92fbe9b..89b247e 100644 --- a/app/views/packages/_sidebar.slim +++ b/app/views/packages/_sidebar.slim @@ -5,7 +5,7 @@ .item // Switch to grid view //a href=url(:package, :index) - = link_to packages_grid_path + = link_to packages_grid_path, search: params[:search] img src="/images/sidebar/grid0.svg" width=40 height=40 .item.space img src="/images/sidebar/list1.svg" width=40 height=40 @@ -15,35 +15,35 @@ .item.space // Switch to list view //a href=url(:package, :index, view: 'list') - = link_to packages_list_path + = link_to packages_list_path, search: params[:search] img src="/images/sidebar/list0.svg" width=40 height=40 // Cycling between with/without/any packages filter .caption Screenshots - if params['show'] == 'with' .item - a href=url_for(show: 'without') + a href=url_for(show: 'without', search: params[:search]) img src="/images/sidebar/show-without0.svg" width=40 height=40 .item img src="/images/sidebar/show-with1.svg" width=40 height=40 .item.space - a href=url_for(show: 'any') + a href=url_for(show: 'any', search: params[:search]) img src="/images/sidebar/show-any0.svg" width=40 height=40 - elsif params['show'] == 'without' .item img src="/images/sidebar/show-without1.svg" width=40 height=40 .item - a href=url_for(show: 'with') + a href=url_for(show: 'with', search: params[:search]) img src="/images/sidebar/show-with0.svg" width=40 height=40 .item.space - a href=url_for(show: 'any') + a href=url_for(show: 'any', search: params[:search]) img src="/images/sidebar/show-any0.svg" width=40 height=40 - else # any .item - a href=url_for(show: 'without') + a href=url_for(show: 'without', search: params[:search]) img src="/images/sidebar/show-without0.svg" width=40 height=40 .item - a href=url_for(show: 'with') + a href=url_for(show: 'with', search: params[:search]) img src="/images/sidebar/show-with0.svg" width=40 height=40 .item.space img src="/images/sidebar/show-any1.svg" width=40 height=40 diff --git a/app/views/packages/index-grid.slim b/app/views/packages/index-grid.slim index e0e5002..77ff050 100644 --- a/app/views/packages/index-grid.slim +++ b/app/views/packages/index-grid.slim @@ -23,7 +23,7 @@ ' Sorry. I couldn't find any software package like that. ' Would you like to view ' - a href=url(:package, :index) all packages + a href=url_for(show: params[:show]) all packages ' ' instead? diff --git a/app/views/packages/index-list.slim b/app/views/packages/index-list.slim index 7dad3fd..807162f 100644 --- a/app/views/packages/index-list.slim +++ b/app/views/packages/index-list.slim @@ -39,7 +39,7 @@ ' Sorry. I couldn't find any software package like that. ' Would you like to view ' - a href=url(:package, :index) all packages + a href=url_for(show: params[:show]) all packages ' ' instead?