pg_search 0.3.3 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +6 -0
- data/README.rdoc +10 -1
- data/lib/pg_search.rb +6 -2
- data/lib/pg_search/document.rb +8 -1
- data/lib/pg_search/features/tsearch.rb +1 -1
- data/lib/pg_search/version.rb +1 -1
- data/spec/pg_search_spec.rb +72 -12
- data/spec/spec_helper.rb +21 -19
- metadata +62 -41
- data/script/setup-contrib +0 -12
data/CHANGELOG.rdoc
CHANGED
@@ -1,5 +1,11 @@
|
|
1
1
|
= PgSearch
|
2
2
|
|
3
|
+
== 0.3.4
|
4
|
+
|
5
|
+
* Fix issue with {:using => {:tsearch => {:prefix => true}}} and hyphens.
|
6
|
+
|
7
|
+
* Get tests running against PostgreSQL 9.1 by using CREATE EXTENSION
|
8
|
+
|
3
9
|
== 0.3.3
|
4
10
|
|
5
11
|
* Backport array_agg() aggregate function to PostgreSQL 8.3 and earlier.
|
data/README.rdoc
CHANGED
@@ -75,7 +75,7 @@ Two associations are built automatically. On the original record, there is a has
|
|
75
75
|
|
76
76
|
==== Searching in the global search index
|
77
77
|
|
78
|
-
To fetch the PgSearch::Document entries for all of the records that match a given query, use
|
78
|
+
To fetch the PgSearch::Document entries for all of the records that match a given query, use PgSearch.multisearch.
|
79
79
|
|
80
80
|
odyssey = EpicPoem.create!(:title => "Odyssey", :author => "Homer")
|
81
81
|
rose = Flower.create!(:color => "Red")
|
@@ -93,6 +93,15 @@ PgSearch.multisearch returns an ActiveRecord::Relation, just like scopes do, so
|
|
93
93
|
puts document.searchable.updated_at
|
94
94
|
end
|
95
95
|
|
96
|
+
==== Configuring multi-search
|
97
|
+
|
98
|
+
PgSearch.multisearch can be configured using the same options as `pg_search_scope` (explained in more detail below). Just set the PgSearch.multisearchable_options in an initializer:
|
99
|
+
|
100
|
+
PgSearch.multisearchable_options = {
|
101
|
+
:using => [:tsearch, :trigram],
|
102
|
+
:ignoring => :accents
|
103
|
+
}
|
104
|
+
|
96
105
|
==== Rebuilding search documents for a given class
|
97
106
|
|
98
107
|
If you change the :against option on a class, add multisearchable to a class that already has records in the database, or remove multisearchable from a class in order to remove it from the index, you will find that the pg_search_documents table could become out-of-sync with the actual records in your other tables.
|
data/lib/pg_search.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
1
|
require "active_record"
|
2
2
|
require "active_support/concern"
|
3
|
+
require "active_support/core_ext/module/attribute_accessors"
|
3
4
|
|
4
5
|
module PgSearch
|
5
6
|
extend ActiveSupport::Concern
|
6
7
|
|
8
|
+
mattr_accessor :multisearch_options
|
9
|
+
self.multisearch_options = {}
|
10
|
+
|
7
11
|
module ClassMethods
|
8
12
|
def pg_search_scope(name, options)
|
9
13
|
self.scope(
|
@@ -26,8 +30,8 @@ module PgSearch
|
|
26
30
|
end
|
27
31
|
|
28
32
|
class << self
|
29
|
-
def multisearch(
|
30
|
-
PgSearch::Document.search(
|
33
|
+
def multisearch(*args)
|
34
|
+
PgSearch::Document.search(*args)
|
31
35
|
end
|
32
36
|
|
33
37
|
def disable_multisearch
|
data/lib/pg_search/document.rb
CHANGED
@@ -8,7 +8,14 @@ module PgSearch
|
|
8
8
|
|
9
9
|
before_validation :update_content
|
10
10
|
|
11
|
-
pg_search_scope :search,
|
11
|
+
pg_search_scope :search, lambda { |*args|
|
12
|
+
if PgSearch.multisearch_options.respond_to?(:call)
|
13
|
+
options = PgSearch.multisearch_options.call(*args)
|
14
|
+
else
|
15
|
+
options = PgSearch.multisearch_options.reverse_merge(:query => args.first)
|
16
|
+
end
|
17
|
+
options.reverse_merge(:against => :content)
|
18
|
+
}
|
12
19
|
|
13
20
|
private
|
14
21
|
|
@@ -37,7 +37,7 @@ module PgSearch
|
|
37
37
|
@columns.map { |column| column.to_sql }.join(" || ' ' || ")
|
38
38
|
end
|
39
39
|
|
40
|
-
DISALLOWED_TSQUERY_CHARACTERS = /['
|
40
|
+
DISALLOWED_TSQUERY_CHARACTERS = /['?\\:]/
|
41
41
|
|
42
42
|
def tsquery_for_term(term)
|
43
43
|
sanitized_term = term.gsub(DISALLOWED_TSQUERY_CHARACTERS, " ")
|
data/lib/pg_search/version.rb
CHANGED
data/spec/pg_search_spec.rb
CHANGED
@@ -344,14 +344,11 @@ describe "an ActiveRecord model which includes PgSearch" do
|
|
344
344
|
end
|
345
345
|
|
346
346
|
it "returns rows that match the query when the query has a hyphen" do
|
347
|
-
included =
|
348
|
-
|
349
|
-
ModelWithPgSearch.create!(:title => 'foo-bar')
|
350
|
-
]
|
351
|
-
excluded = ModelWithPgSearch.create!(:title => 'baz quux')
|
347
|
+
included = ModelWithPgSearch.create!(:title => 'foo-bar')
|
348
|
+
excluded = ModelWithPgSearch.create!(:title => 'foo bar')
|
352
349
|
|
353
350
|
results = ModelWithPgSearch.search_title_with_prefixes("foo-bar")
|
354
|
-
results.should
|
351
|
+
results.should include(included)
|
355
352
|
results.should_not include(excluded)
|
356
353
|
end
|
357
354
|
end
|
@@ -703,14 +700,77 @@ describe "an ActiveRecord model which includes PgSearch" do
|
|
703
700
|
end
|
704
701
|
|
705
702
|
describe ".multisearch" do
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
703
|
+
with_table "pg_search_documents", {}, &DOCUMENTS_SCHEMA
|
704
|
+
|
705
|
+
describe "delegation to PgSearch::Document.search" do
|
706
|
+
subject { PgSearch.multisearch(query) }
|
707
|
+
|
708
|
+
let(:query) { double(:query) }
|
709
|
+
let(:relation) { double(:relation) }
|
710
|
+
before do
|
711
|
+
PgSearch::Document.should_receive(:search).with(query).and_return(relation)
|
712
|
+
end
|
713
|
+
|
714
|
+
it { should == relation }
|
715
|
+
end
|
716
|
+
|
717
|
+
context "with PgSearch.multisearch_options set to a Hash" do
|
718
|
+
before { PgSearch.stub(:multisearch_options).and_return({:using => :dmetaphone}) }
|
719
|
+
subject { PgSearch.multisearch(query).map(&:searchable) }
|
720
|
+
|
721
|
+
with_model :MultisearchableModel do
|
722
|
+
table do |t|
|
723
|
+
t.string :title
|
724
|
+
end
|
725
|
+
model do
|
726
|
+
include PgSearch
|
727
|
+
multisearchable :against => :title
|
728
|
+
end
|
729
|
+
end
|
730
|
+
|
731
|
+
let!(:soundalike_record) { MultisearchableModel.create!(:title => 'foning') }
|
732
|
+
let(:query) { "Phoning" }
|
733
|
+
it { should include(soundalike_record) }
|
711
734
|
end
|
712
735
|
|
713
|
-
|
736
|
+
context "with PgSearch.multisearch_options set to a Proc" do
|
737
|
+
subject { PgSearch.multisearch(query, soundalike).map(&:searchable) }
|
738
|
+
|
739
|
+
before do
|
740
|
+
PgSearch.stub(:multisearch_options).and_return do
|
741
|
+
lambda do |query, soundalike|
|
742
|
+
if soundalike
|
743
|
+
{:using => :dmetaphone, :query => query}
|
744
|
+
else
|
745
|
+
{:query => query}
|
746
|
+
end
|
747
|
+
end
|
748
|
+
end
|
749
|
+
end
|
750
|
+
|
751
|
+
with_model :MultisearchableModel do
|
752
|
+
table do |t|
|
753
|
+
t.string :title
|
754
|
+
end
|
755
|
+
model do
|
756
|
+
include PgSearch
|
757
|
+
multisearchable :against => :title
|
758
|
+
end
|
759
|
+
end
|
760
|
+
|
761
|
+
let!(:soundalike_record) { MultisearchableModel.create!(:title => 'foning') }
|
762
|
+
let(:query) { "Phoning" }
|
763
|
+
|
764
|
+
context "with soundalike true" do
|
765
|
+
let(:soundalike) { true }
|
766
|
+
it { should include(soundalike_record) }
|
767
|
+
end
|
768
|
+
|
769
|
+
context "with soundalike false" do
|
770
|
+
let(:soundalike) { false }
|
771
|
+
it { should_not include(soundalike_record) }
|
772
|
+
end
|
773
|
+
end
|
714
774
|
end
|
715
775
|
|
716
776
|
describe ".disable_multisearch" do
|
data/spec/spec_helper.rb
CHANGED
@@ -7,7 +7,9 @@ begin
|
|
7
7
|
:username => ('postgres' if ENV["TRAVIS"]),
|
8
8
|
:min_messages => 'warning')
|
9
9
|
connection = ActiveRecord::Base.connection
|
10
|
+
postgresql_version = connection.send(:postgresql_version)
|
10
11
|
connection.execute("SELECT 1")
|
12
|
+
puts "postgresql_version = #{postgresql_version}"
|
11
13
|
rescue PGError => e
|
12
14
|
puts "-" * 80
|
13
15
|
puts "Unable to connect to database. Please run:"
|
@@ -17,40 +19,40 @@ rescue PGError => e
|
|
17
19
|
raise e
|
18
20
|
end
|
19
21
|
|
20
|
-
def
|
22
|
+
def install_extension_if_missing(name, query, expected_result)
|
21
23
|
connection = ActiveRecord::Base.connection
|
22
24
|
result = connection.select_value(query)
|
23
25
|
raise "Unexpected output for #{query}: #{result.inspect}" unless result.downcase == expected_result.downcase
|
24
26
|
rescue => e
|
25
27
|
begin
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
28
|
+
if postgresql_version >= 90100
|
29
|
+
ActiveRecord::Base.connection.execute "CREATE EXTENSION #{name};"
|
30
|
+
else
|
31
|
+
share_path = `pg_config --sharedir`.strip
|
32
|
+
ActiveRecord::Base.connection.execute File.read(File.join(share_path, 'contrib', "#{name}.sql"))
|
33
|
+
puts $!.message
|
34
|
+
end
|
35
|
+
rescue => e2
|
30
36
|
puts "-" * 80
|
31
37
|
puts "Please install the #{name} contrib module"
|
32
38
|
puts "-" * 80
|
33
|
-
raise
|
39
|
+
raise e2
|
34
40
|
end
|
35
41
|
end
|
36
42
|
|
37
|
-
|
38
|
-
unless
|
39
|
-
|
43
|
+
install_extension_if_missing("pg_trgm", "SELECT 'abcdef' % 'cdef'", "t")
|
44
|
+
unless postgresql_version < 90000
|
45
|
+
install_extension_if_missing("unaccent", "SELECT unaccent('foo')", "foo")
|
40
46
|
end
|
41
|
-
|
47
|
+
install_extension_if_missing("fuzzystrmatch", "SELECT dmetaphone('foo')", "f")
|
42
48
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
connection.execute(File.read(File.join(File.dirname(__FILE__), '..', 'sql', 'array_agg.sql')))
|
47
|
-
end
|
48
|
-
connection.execute(File.read(File.join(File.dirname(__FILE__), '..', 'sql', 'unnest.sql')))
|
49
|
+
if postgresql_version < 80400
|
50
|
+
unless connection.select_value("SELECT 1 FROM pg_catalog.pg_aggregate WHERE aggfnoid = 'array_agg'::REGPROC") == "1"
|
51
|
+
connection.execute(File.read(File.join(File.dirname(__FILE__), '..', 'sql', 'array_agg.sql')))
|
49
52
|
end
|
50
|
-
connection.execute(File.read(File.join(File.dirname(__FILE__), '..', 'sql', '
|
53
|
+
connection.execute(File.read(File.join(File.dirname(__FILE__), '..', 'sql', 'unnest.sql')))
|
51
54
|
end
|
52
|
-
|
53
|
-
|
55
|
+
connection.execute(File.read(File.join(File.dirname(__FILE__), '..', 'sql', 'dmetaphone.sql')))
|
54
56
|
|
55
57
|
require "with_model"
|
56
58
|
|
metadata
CHANGED
@@ -1,46 +1,60 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: pg_search
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 3
|
9
|
+
- 4
|
10
|
+
version: 0.3.4
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
12
|
+
authors:
|
8
13
|
- Case Commons, LLC
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
|
18
|
+
date: 2011-11-25 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
15
21
|
name: activerecord
|
16
|
-
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
17
24
|
none: false
|
18
|
-
requirements:
|
19
|
-
- -
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 5
|
29
|
+
segments:
|
30
|
+
- 3
|
31
|
+
version: "3"
|
22
32
|
type: :runtime
|
23
|
-
|
24
|
-
|
25
|
-
- !ruby/object:Gem::Dependency
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
26
35
|
name: activesupport
|
27
|
-
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
28
38
|
none: false
|
29
|
-
requirements:
|
30
|
-
- -
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
hash: 5
|
43
|
+
segments:
|
44
|
+
- 3
|
45
|
+
version: "3"
|
33
46
|
type: :runtime
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
full text search
|
38
|
-
email:
|
47
|
+
version_requirements: *id002
|
48
|
+
description: PgSearch builds ActiveRecord named scopes that take advantage of PostgreSQL's full text search
|
49
|
+
email:
|
39
50
|
- casecommons-dev@googlegroups.com
|
40
51
|
executables: []
|
52
|
+
|
41
53
|
extensions: []
|
54
|
+
|
42
55
|
extra_rdoc_files: []
|
43
|
-
|
56
|
+
|
57
|
+
files:
|
44
58
|
- .autotest
|
45
59
|
- .gitignore
|
46
60
|
- .rspec
|
@@ -69,7 +83,6 @@ files:
|
|
69
83
|
- lib/pg_search/tasks.rb
|
70
84
|
- lib/pg_search/version.rb
|
71
85
|
- pg_search.gemspec
|
72
|
-
- script/setup-contrib
|
73
86
|
- spec/associations_spec.rb
|
74
87
|
- spec/pg_search/document_spec.rb
|
75
88
|
- spec/pg_search/multisearch_spec.rb
|
@@ -84,30 +97,38 @@ files:
|
|
84
97
|
- sql/unnest.sql
|
85
98
|
homepage: https://github.com/Casecommons/pg_search
|
86
99
|
licenses: []
|
100
|
+
|
87
101
|
post_install_message:
|
88
102
|
rdoc_options: []
|
89
|
-
|
103
|
+
|
104
|
+
require_paths:
|
90
105
|
- lib
|
91
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
106
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
107
|
none: false
|
93
|
-
requirements:
|
94
|
-
- -
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
|
97
|
-
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
hash: 3
|
112
|
+
segments:
|
113
|
+
- 0
|
114
|
+
version: "0"
|
115
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
116
|
none: false
|
99
|
-
requirements:
|
100
|
-
- -
|
101
|
-
- !ruby/object:Gem::Version
|
102
|
-
|
117
|
+
requirements:
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
hash: 3
|
121
|
+
segments:
|
122
|
+
- 0
|
123
|
+
version: "0"
|
103
124
|
requirements: []
|
125
|
+
|
104
126
|
rubyforge_project:
|
105
127
|
rubygems_version: 1.8.10
|
106
128
|
signing_key:
|
107
129
|
specification_version: 3
|
108
|
-
summary: PgSearch builds ActiveRecord named scopes that take advantage of PostgreSQL's
|
109
|
-
|
110
|
-
test_files:
|
130
|
+
summary: PgSearch builds ActiveRecord named scopes that take advantage of PostgreSQL's full text search
|
131
|
+
test_files:
|
111
132
|
- spec/associations_spec.rb
|
112
133
|
- spec/pg_search/document_spec.rb
|
113
134
|
- spec/pg_search/multisearch_spec.rb
|
data/script/setup-contrib
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
#!/bin/sh
|
2
|
-
POSTGRESQL_VERSION=`pg_config --version | awk '{print $2}'`
|
3
|
-
|
4
|
-
cd /tmp
|
5
|
-
test -e /tmp/postgresql-$POSTGRESQL_VERSION.tar.bz2 || wget http://ftp9.us.postgresql.org/pub/mirrors/postgresql/source/v$POSTGRESQL_VERSION/postgresql-$POSTGRESQL_VERSION.tar.bz2
|
6
|
-
test -d /tmp/postgresql-$POSTGRESQL_VERSION || tar zxvf postgresql-$POSTGRESQL_VERSION.tar.bz2
|
7
|
-
cd postgresql-$POSTGRESQL_VERSION && eval ./configure `pg_config --configure` && make
|
8
|
-
cd contrib/unaccent && make && make install
|
9
|
-
cd ..
|
10
|
-
cd contrib/pg_trgm && make && make install
|
11
|
-
cd ..
|
12
|
-
cd contrib/fuzzystrmatch && make && make install
|