pg_search 0.5.7 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.travis.yml +22 -1
  4. data/CHANGELOG.rdoc +14 -0
  5. data/Gemfile +12 -8
  6. data/Guardfile +6 -0
  7. data/LICENSE +1 -1
  8. data/README.rdoc +37 -14
  9. data/lib/pg_search/configuration.rb +9 -5
  10. data/lib/pg_search/features/feature.rb +2 -0
  11. data/lib/pg_search/features/trigram.rb +18 -8
  12. data/lib/pg_search/features/tsearch.rb +18 -11
  13. data/lib/pg_search/migration/templates/add_pg_search_associated_against_support_functions.rb.erb +2 -2
  14. data/lib/pg_search/migration/templates/add_pg_search_dmetaphone_support_functions.rb.erb +4 -4
  15. data/lib/pg_search/normalizer.rb +19 -11
  16. data/lib/pg_search/scope_options.rb +22 -6
  17. data/lib/pg_search/tasks.rb +9 -2
  18. data/lib/pg_search/version.rb +1 -1
  19. data/pg_search.gemspec +7 -6
  20. data/spec/{associations_spec.rb → integration/associations_spec.rb} +36 -0
  21. data/spec/{pg_search_spec.rb → integration/pg_search_spec.rb} +55 -11
  22. data/spec/{pg_search → lib/pg_search}/document_spec.rb +0 -0
  23. data/spec/lib/pg_search/features/trigram_spec.rb +26 -0
  24. data/spec/lib/pg_search/features/tsearch_spec.rb +51 -0
  25. data/spec/{pg_search → lib/pg_search}/multisearch/rebuilder_spec.rb +0 -0
  26. data/spec/{pg_search → lib/pg_search}/multisearch_spec.rb +0 -0
  27. data/spec/{pg_search → lib/pg_search}/multisearchable_spec.rb +0 -0
  28. data/spec/lib/pg_search/normalizer_spec.rb +82 -0
  29. data/spec/spec_helper.rb +15 -45
  30. data/sql/dmetaphone.sql +1 -1
  31. metadata +40 -45
  32. data/.rvmrc +0 -52
  33. data/spec/pg_search/normalizer_spec.rb +0 -58
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 953137586cb6148bd40249e053348adc9d1e4c4e
4
+ data.tar.gz: bd82cbede7a515ea77280bb2667617abcbb3ba6a
5
+ SHA512:
6
+ metadata.gz: 4054d7eb7e376aee61ed698ccda4f8573752823e4b8de9e7bc192eefc84845aa2f3b0162f8de12704f5696367187bc1db2202f03c28aca1816128145e6aeebf9
7
+ data.tar.gz: 3a2031283e5b9a8e80e19607dc1b6bf044c4bd9340febdc0fd6606dffeff9729be7a36e214dddd877a915e6ae02e61b9099aab4b6d972d8a43afd314fc218dd0
data/.gitignore CHANGED
@@ -6,3 +6,6 @@ doc
6
6
  tags
7
7
  *~
8
8
  Gemfile.lock
9
+ .rbx
10
+ coverage/
11
+ tmp/
data/.travis.yml CHANGED
@@ -2,14 +2,35 @@ language: ruby
2
2
 
3
3
  rvm:
4
4
  - 1.8.7
5
- - 1.9.2
6
5
  - 1.9.3
6
+ - 2.0.0
7
7
  - jruby-18mode
8
8
  - jruby-19mode
9
9
  - rbx-18mode
10
10
  - rbx-19mode
11
11
  - ree
12
12
 
13
+ env:
14
+ - ACTIVE_RECORD_VERSION="~> 4.0.0.beta1"
15
+ - ACTIVE_RECORD_VERSION="~> 3.2.0"
16
+ - ACTIVE_RECORD_VERSION="~> 3.1.0"
17
+
18
+ matrix:
19
+ allow_failures:
20
+ - rvm: rbx-18mode
21
+ - rvm: rbx-19mode
22
+ - env: ACTIVE_RECORD_VERSION="~> 4.0.0.beta1"
23
+ exclude:
24
+ - rvm: 1.8.7
25
+ env: ACTIVE_RECORD_VERSION="~> 4.0.0.beta1"
26
+ - rvm: jruby-18mode
27
+ env: ACTIVE_RECORD_VERSION="~> 4.0.0.beta1"
28
+ - rvm: rbx-18mode
29
+ env: ACTIVE_RECORD_VERSION="~> 4.0.0.beta1"
30
+ - rvm: ree
31
+ env: ACTIVE_RECORD_VERSION="~> 4.0.0.beta1"
32
+
33
+
13
34
  before_script:
14
35
  - "psql -c 'create database pg_search_test;' -U postgres >/dev/null"
15
36
 
data/CHANGELOG.rdoc CHANGED
@@ -1,5 +1,19 @@
1
1
  = PgSearch
2
2
 
3
+ == 0.6.0
4
+
5
+ * Drop support for Active Record 3.0.
6
+
7
+ * Address warnings in Ruby 2.0.
8
+
9
+ * Remove all usages of sanitize_sql_array for future Rails 4 compatibility.
10
+
11
+ * Start using Arel internally to build SQL strings (not yet complete).
12
+
13
+ * Disable eager loading, fixes issue #14.
14
+
15
+ * Support named schemas in pg_search:multisearch:rebuild. (Victor Olteanu)
16
+
3
17
  == 0.5.7
4
18
 
5
19
  * Fix issue with eager loading now that the Scope class has been removed. (Piotr Murach)
data/Gemfile CHANGED
@@ -6,15 +6,19 @@ gem "rake"
6
6
  gem "rdoc"
7
7
  gem "pry"
8
8
 
9
- platforms :ruby do
10
- gem 'pg'
11
- end
12
-
13
- platforms :jruby do
14
- gem "activerecord-jdbcpostgresql-adapter"
15
- end
9
+ gem 'pg', :platform => :ruby
10
+ gem "activerecord-jdbcpostgresql-adapter", :platform => :jruby
16
11
 
17
12
  gem "rspec"
18
13
  gem "with_model"
19
14
 
20
- gem "activerecord", "~> #{ENV["ACTIVE_RECORD_VERSION"]}.0" if ENV["ACTIVE_RECORD_VERSION"]
15
+ gem "activerecord", ENV["ACTIVE_RECORD_VERSION"] if ENV["ACTIVE_RECORD_VERSION"]
16
+
17
+ gem 'coveralls', :require => false, :platform => :mri_20
18
+
19
+ group :development do
20
+ gem 'guard-rspec', :require => false
21
+ gem 'rb-inotify', :require => false
22
+ gem 'rb-fsevent', :require => false
23
+ gem 'rb-fchange', :require => false
24
+ end
data/Guardfile ADDED
@@ -0,0 +1,6 @@
1
+ guard 'rspec' do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec" }
5
+ end
6
+
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010-12 Case Commons, LLC
1
+ Copyright (c) 2010-13 Case Commons, LLC
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
data/README.rdoc CHANGED
@@ -2,31 +2,51 @@
2
2
 
3
3
  * http://github.com/casecommons/pg_search/
4
4
 
5
- {<img src="https://secure.travis-ci.org/Casecommons/pg_search.png?branch=master" alt="Build Status" />}[http://travis-ci.org/Casecommons/pg_search] {<img src="https://gemnasium.com/Casecommons/pg_search.png" alt="Dependency Status" />}[https://gemnasium.com/Casecommons/pg_search] {<img src="https://codeclimate.com/badge.png" />}[https://codeclimate.com/github/Casecommons/pg_search]
5
+ {<img src="https://secure.travis-ci.org/Casecommons/pg_search.png?branch=master" alt="Build Status" />}[http://travis-ci.org/Casecommons/pg_search]
6
+ {<img src="https://gemnasium.com/Casecommons/pg_search.png" alt="Dependency Status" />}[https://gemnasium.com/Casecommons/pg_search]
7
+ {<img src="https://codeclimate.com/github/Casecommons/pg_search.png" />}[https://codeclimate.com/github/Casecommons/pg_search]
8
+ {<img src="https://coveralls.io/repos/Casecommons/pg_search/badge.png?branch=master" alt="Coverage Status" />}[https://coveralls.io/r/Casecommons/pg_search]
9
+ {<img src="https://badge.fury.io/rb/pg_search.png" alt="Gem Version" />}[http://badge.fury.io/rb/pg_search]
6
10
 
7
11
  == DESCRIPTION
8
12
 
9
13
  PgSearch builds named scopes that take advantage of PostgreSQL's full text search
10
14
 
11
- Read the blog post introducing PgSearch at http://bit.ly/pg_search
15
+ Read the blog post introducing PgSearch at http://pivotallabs.com/pg-search/
16
+
17
+ == REQUIREMENTS
18
+
19
+ * Active Record 3.1 or later
20
+ * PostgreSQL
21
+ * {PostgreSQL contrib packages for certain features}[https://github.com/Casecommons/pg_search/wiki/Installing-Postgres-Contrib-Modules]
12
22
 
13
23
  == INSTALL
14
24
 
15
25
  gem install pg_search
16
26
 
17
- === Rails 3
27
+ === Rails 3.1 or later
18
28
 
19
29
  In Gemfile
20
30
 
21
31
  gem 'pg_search'
22
32
 
33
+ === Rails 3.0
34
+
35
+ The newest versions of PgSearch no longer support Rails 3.0. However, the 0.5 series still works. It's not actively maintained, but submissions are welcome for backports and bugfixes.
36
+
37
+ gem 'pg_search', "~> 0.5.7"
38
+
39
+ The 0.5 branch lives at https://github.com/Casecommons/pg_search/tree/0.5-stable
40
+
23
41
  === Rails 2
24
42
 
25
43
  The newest versions of PgSearch no longer support Rails 2. However, the 0.2 series still works. It's not actively maintained, but submissions are welcome for backports and bugfixes.
26
44
 
45
+ gem 'pg_search', "~> 0.2.0"
46
+
27
47
  The 0.2 branch lives at https://github.com/Casecommons/pg_search/tree/0.2-stable
28
48
 
29
- === Other ActiveRecord-based projects
49
+ === Other Active Record projects
30
50
 
31
51
  In addition to installing and requiring the gem, you may want to include the PgSearch rake tasks in your Rakefile. This isn't necessary for Rails projects, which gain the Rake tasks via a Railtie.
32
52
 
@@ -34,7 +54,7 @@ In addition to installing and requiring the gem, you may want to include the PgS
34
54
 
35
55
  == USAGE
36
56
 
37
- To add PgSearch to an ActiveRecord model, simply include the PgSearch module.
57
+ To add PgSearch to an Active Record model, simply include the PgSearch module.
38
58
 
39
59
  class Shape < ActiveRecord::Base
40
60
  include PgSearch
@@ -71,6 +91,8 @@ To add a model to the global search index for your application, call multisearch
71
91
  multisearchable :against => :color
72
92
  end
73
93
 
94
+ If this model already has existing records, you will need to reindex this model to get existing records into the pg_search_documents table. See the rebuild task below.
95
+
74
96
  Whenever a record is created, updated, or destroyed, an Active Record callback will fire, leading to the creation of a corresponding PgSearch::Document record in the pg_search_documents table. The :against option can be one or several methods which will be called on the record to generate its search text.
75
97
 
76
98
  You can also pass a Proc or method name to call to determine whether or not a particular record should be included.
@@ -164,16 +186,23 @@ To remove all of the documents for a given class, you can simply delete all of t
164
186
 
165
187
  PgSearch::Document.delete_all(:searchable_type => "Animal")
166
188
 
167
- Run this Rake task to regenerate all of the documents for a given class.
189
+ To regenerate the documents for a given class, run:
190
+
191
+ PgSearch::Multisearch.rebuild(Product)
192
+
193
+ This is also available as a Rake task, for convenience.
168
194
 
169
195
  $ rake pg_search:multisearch:rebuild[BlogPost]
170
196
 
171
- Currently this is only supported for :against methods that directly map to Active Record attributes. Until that is fixed, you could also manually rebuild all of the documents.
197
+ A second optional argument can be passed to specify the PostgreSQL schema search path to use, for multi-tenant databases that have multiple pg_search_documents tables. The following will set the schema search path to "my_schema" before reindexing.
198
+
199
+ $ rake pg_search:multisearch:rebuild[BlogPost,my_schema]
200
+
201
+ For models that are multisearchable :against methods that directly map to Active Record attributes, an efficient single SQL statement is run to update the pg_search_documents table all at once. However, if you call any dynamic methods in :against, the following strategy will be used:
172
202
 
173
203
  PgSearch::Document.delete_all(:searchable_type => "Ingredient")
174
204
  Ingredient.find_each { |record| record.update_pg_search_document }
175
205
 
176
-
177
206
  You can also provide a custom implementation for rebuilding the documents by adding a class method called `rebuild_pg_search_documents` to your model.
178
207
 
179
208
  class Movie < ActiveRecord::Base
@@ -569,12 +598,6 @@ To use this functionality you'll need to do a few things:
569
598
 
570
599
  Please note that the :against column is only used when the tsvector_column is not present for the search type.
571
600
 
572
- == REQUIREMENTS
573
-
574
- * ActiveRecord 3
575
- * PostgreSQL
576
- * {PostgreSQL contrib packages for certain features}[https://github.com/Casecommons/pg_search/wiki/Installing-Postgres-Contrib-Modules]
577
-
578
601
  == ATTRIBUTIONS
579
602
 
580
603
  PgSearch would not have been possible without inspiration from
@@ -59,6 +59,14 @@ module PgSearch
59
59
  Array(options[:using])
60
60
  end
61
61
 
62
+ def feature_options
63
+ @feature_options ||= Hash.new.tap do |hash|
64
+ features.map do |feature_name, feature_options|
65
+ hash[feature_name] = feature_options
66
+ end
67
+ end
68
+ end
69
+
62
70
  def order_within_rank
63
71
  options[:order_within_rank]
64
72
  end
@@ -85,11 +93,7 @@ module PgSearch
85
93
 
86
94
  def assert_valid_options(options)
87
95
  unless options[:against] || options[:associated_against]
88
- raise ArgumentError, "the search scope #{@name} must have :against#{" or :associated_against" if defined?(ActiveRecord::Relation)} in its options"
89
- end
90
-
91
- if options[:associated_against] && !defined?(ActiveRecord::Relation)
92
- raise ArgumentError, ":associated_against requires Active Record 3 or later"
96
+ raise ArgumentError, "the search scope #{@name} must have :against or :associated_against in its options"
93
97
  end
94
98
 
95
99
  options.assert_valid_keys(VALID_KEYS)
@@ -1,6 +1,8 @@
1
1
  module PgSearch
2
2
  module Features
3
3
  class Feature
4
+ delegate :connection, :quoted_table_name, :to => :'@model'
5
+
4
6
  def initialize(query, options, columns, model, normalizer)
5
7
  @query = query
6
8
  @options = options || {}
@@ -2,17 +2,27 @@ module PgSearch
2
2
  module Features
3
3
  class Trigram < Feature
4
4
  def conditions
5
- [
6
- "(#{normalize(document)}) % #{normalize(":query")}",
7
- {:query => query}
8
- ]
5
+ Arel::Nodes::Grouping.new(
6
+ Arel::Nodes::InfixOperation.new("%", normalized_document, normalize(query))
7
+ )
9
8
  end
10
9
 
11
10
  def rank
12
- [
13
- "similarity((#{normalize(document)}), #{normalize(":query")})",
14
- {:query => query}
15
- ]
11
+ Arel::Nodes::Grouping.new(
12
+ Arel::Nodes::NamedFunction.new(
13
+ "similarity",
14
+ [
15
+ normalized_document,
16
+ normalize(query)
17
+ ]
18
+ )
19
+ )
20
+ end
21
+
22
+ private
23
+
24
+ def normalized_document
25
+ Arel::Nodes::Grouping.new(normalize(Arel.sql(document)))
16
26
  end
17
27
  end
18
28
  end
@@ -3,8 +3,6 @@ require "active_support/core_ext/module/delegation"
3
3
  module PgSearch
4
4
  module Features
5
5
  class TSearch < Feature
6
- delegate :connection, :quoted_table_name, :to => :'@model'
7
-
8
6
  def initialize(*args)
9
7
  super
10
8
 
@@ -16,19 +14,17 @@ module PgSearch
16
14
  end
17
15
 
18
16
  def conditions
19
- ["(#{tsdocument}) @@ (#{tsquery})", interpolations]
17
+ Arel::Nodes::Grouping.new(
18
+ Arel::Nodes::InfixOperation.new("@@", arel_wrap(tsdocument), arel_wrap(tsquery))
19
+ )
20
20
  end
21
21
 
22
22
  def rank
23
- tsearch_rank
23
+ arel_wrap(tsearch_rank)
24
24
  end
25
25
 
26
26
  private
27
27
 
28
- def interpolations
29
- {:query => query.to_s, :dictionary => dictionary.to_s}
30
- end
31
-
32
28
  DISALLOWED_TSQUERY_CHARACTERS = /['?\\:]/
33
29
 
34
30
  def tsquery_for_term(term)
@@ -45,7 +41,10 @@ module PgSearch
45
41
  (connection.quote(':*') if options[:prefix])
46
42
  ].compact.join(" || ")
47
43
 
48
- "to_tsquery(:dictionary, #{tsquery_sql})"
44
+ Arel::Nodes::NamedFunction.new(
45
+ "to_tsquery",
46
+ [dictionary, Arel.sql(tsquery_sql)]
47
+ ).to_sql
49
48
  end
50
49
 
51
50
  def tsquery
@@ -61,7 +60,11 @@ module PgSearch
61
60
  "#{quoted_table_name}.#{column_name}"
62
61
  else
63
62
  columns.map do |search_column|
64
- tsvector = "to_tsvector(:dictionary, #{normalize(search_column.to_sql)})"
63
+ tsvector = Arel::Nodes::NamedFunction.new(
64
+ "to_tsvector",
65
+ [dictionary, Arel.sql(normalize(search_column.to_sql))]
66
+ ).to_sql
67
+
65
68
  if search_column.weight.nil?
66
69
  tsvector
67
70
  else
@@ -85,12 +88,16 @@ module PgSearch
85
88
  end
86
89
 
87
90
  def tsearch_rank
88
- ["ts_rank((#{tsdocument}), (#{tsquery}), #{normalization})", interpolations]
91
+ "ts_rank((#{tsdocument}), (#{tsquery}), #{normalization})"
89
92
  end
90
93
 
91
94
  def dictionary
92
95
  options[:dictionary] || :simple
93
96
  end
97
+
98
+ def arel_wrap(sql_string)
99
+ Arel::Nodes::Grouping.new(Arel.sql(sql_string))
100
+ end
94
101
  end
95
102
  end
96
103
  end
@@ -2,7 +2,7 @@ class AddPgSearchAssociatedAgainstSupportFunctions < ActiveRecord::Migration
2
2
  def self.up
3
3
  say_with_time("Adding support functions for pg_search :associated_against") do
4
4
  if ActiveRecord::Base.connection.send(:postgresql_version) < 80400
5
- execute <<-SQL
5
+ execute <<-'SQL'
6
6
  <%= read_sql_file "array_agg" %>
7
7
  SQL
8
8
  end
@@ -12,7 +12,7 @@ class AddPgSearchAssociatedAgainstSupportFunctions < ActiveRecord::Migration
12
12
  def self.down
13
13
  say_with_time("Dropping support functions for pg_search :associated_against") do
14
14
  if ActiveRecord::Base.connection.send(:postgresql_version) < 80400
15
- execute <<-SQL
15
+ execute <<-'SQL'
16
16
  <%= read_sql_file "uninstall_array_agg" %>
17
17
  SQL
18
18
  end
@@ -2,12 +2,12 @@ class AddPgSearchDmetaphoneSupportFunctions < ActiveRecord::Migration
2
2
  def self.up
3
3
  say_with_time("Adding support functions for pg_search :dmetaphone") do
4
4
  if ActiveRecord::Base.connection.send(:postgresql_version) < 80400
5
- execute <<-SQL
5
+ execute <<-'SQL'
6
6
  <%= read_sql_file "unnest" %>
7
7
  SQL
8
8
  end
9
9
 
10
- execute <<-SQL
10
+ execute <<-'SQL'
11
11
  <%= read_sql_file "dmetaphone" %>
12
12
  SQL
13
13
  end
@@ -15,12 +15,12 @@ class AddPgSearchDmetaphoneSupportFunctions < ActiveRecord::Migration
15
15
 
16
16
  def self.down
17
17
  say_with_time("Dropping support functions for pg_search :dmetaphone") do
18
- execute <<-SQL
18
+ execute <<-'SQL'
19
19
  <%= read_sql_file "uninstall_dmetaphone" %>
20
20
  SQL
21
21
 
22
22
  if ActiveRecord::Base.connection.send(:postgresql_version) < 80400
23
- execute <<-SQL
23
+ execute <<-'SQL'
24
24
  <%= read_sql_file "uninstall_unnest" %>
25
25
  SQL
26
26
  end
@@ -5,18 +5,26 @@ module PgSearch
5
5
  end
6
6
 
7
7
  def add_normalization(sql_expression)
8
- if config.ignore.include?(:accents)
9
- if config.postgresql_version < 90000
10
- raise PgSearch::NotSupportedForPostgresqlVersion.new(<<-MESSAGE.gsub /^\s*/, '')
11
- Sorry, {:ignoring => :accents} only works in PostgreSQL 9.0 and above.
12
- #{config.inspect}
13
- MESSAGE
14
- else
15
- "#{PgSearch.unaccent_function}(#{sql_expression})"
16
- end
17
- else
18
- sql_expression
8
+ return sql_expression unless config.ignore.include?(:accents)
9
+
10
+ if config.postgresql_version < 90000
11
+ raise PgSearch::NotSupportedForPostgresqlVersion.new(<<-MESSAGE.gsub /^\s*/, '')
12
+ Sorry, {:ignoring => :accents} only works in PostgreSQL 9.0 and above.
13
+ #{config.inspect}
14
+ MESSAGE
19
15
  end
16
+
17
+ sql_node = case sql_expression
18
+ when Arel::Nodes::Node
19
+ sql_expression
20
+ else
21
+ Arel.sql(sql_expression)
22
+ end
23
+
24
+ Arel::Nodes::NamedFunction.new(
25
+ PgSearch.unaccent_function,
26
+ [sql_node]
27
+ ).to_sql
20
28
  end
21
29
 
22
30
  private
@@ -1,3 +1,5 @@
1
+ # encoding: UTF-8
2
+
1
3
  require "active_support/core_ext/module/delegation"
2
4
 
3
5
  module PgSearch
@@ -7,21 +9,35 @@ module PgSearch
7
9
  def initialize(config)
8
10
  @config = config
9
11
  @model = config.model
10
- @feature_options = Hash[config.features]
12
+ @feature_options = config.feature_options
11
13
  end
12
14
 
13
15
  def apply(scope)
14
- scope.select("#{quoted_table_name}.*, (#{rank}) AS pg_search_rank").where(conditions).order("pg_search_rank DESC, #{order_within_rank}").joins(joins)
16
+ scope.
17
+ select("#{quoted_table_name}.*, (#{rank}) AS pg_search_rank").
18
+ where(conditions).
19
+ order("pg_search_rank DESC, #{order_within_rank}").
20
+ joins(joins).
21
+ extend(DisableEagerLoading)
22
+ end
23
+
24
+ # workaround for https://github.com/Casecommons/pg_search/issues/14
25
+ module DisableEagerLoading
26
+ def eager_loading?
27
+ return false
28
+ end
15
29
  end
16
30
 
17
31
  private
18
32
 
19
- delegate :connection, :quoted_table_name, :sanitize_sql_array, :to => :@model
33
+ delegate :connection, :quoted_table_name, :to => :@model
20
34
 
21
35
  def conditions
22
36
  config.features.map do |feature_name, feature_options|
23
- "(#{sanitize_sql_array(feature_for(feature_name).conditions)})"
24
- end.join(" OR ")
37
+ feature_for(feature_name).conditions
38
+ end.inject do |accumulator, expression|
39
+ Arel::Nodes::Or.new(accumulator, expression)
40
+ end
25
41
  end
26
42
 
27
43
  def order_within_rank
@@ -63,7 +79,7 @@ module PgSearch
63
79
 
64
80
  def rank
65
81
  (config.ranking_sql || ":tsearch").gsub(/:(\w*)/) do
66
- sanitize_sql_array(feature_for($1).rank)
82
+ feature_for($1).rank.to_sql
67
83
  end
68
84
  end
69
85
  end
@@ -4,13 +4,20 @@ require 'pg_search'
4
4
  namespace :pg_search do
5
5
  namespace :multisearch do
6
6
  desc "Rebuild PgSearch multisearch records for a given model"
7
- task :rebuild, [:model] => :environment do |task, args|
7
+ task :rebuild, [:model,:schema] => :environment do |task, args|
8
8
  raise ArgumentError, <<-MESSAGE unless args.model
9
9
  You must pass a model as an argument.
10
10
  Example: rake pg_search:multisearch:rebuild[BlogPost]
11
11
  MESSAGE
12
12
  model_class = args.model.classify.constantize
13
- PgSearch::Multisearch.rebuild(model_class)
13
+ connection = PgSearch::Document.connection
14
+ original_schema_search_path = connection.schema_search_path
15
+ begin
16
+ connection.schema_search_path = args.schema if args.schema
17
+ PgSearch::Multisearch.rebuild(model_class)
18
+ ensure
19
+ connection.schema_search_path = original_schema_search_path
20
+ end
14
21
  end
15
22
  end
16
23
  end
@@ -1,3 +1,3 @@
1
1
  module PgSearch
2
- VERSION = "0.5.7"
2
+ VERSION = "0.6.0"
3
3
  end
data/pg_search.gemspec CHANGED
@@ -6,17 +6,18 @@ Gem::Specification.new do |s|
6
6
  s.name = "pg_search"
7
7
  s.version = PgSearch::VERSION
8
8
  s.platform = Gem::Platform::RUBY
9
- s.authors = ["Case Commons, LLC"]
10
- s.email = ["casecommons-dev@googlegroups.com"]
9
+ s.authors = ["Grant Hutchins", "Case Commons, LLC"]
10
+ s.email = ["gems@nertzy.com", "casecommons-dev@googlegroups.com"]
11
11
  s.homepage = "https://github.com/Casecommons/pg_search"
12
- s.summary = %q{PgSearch builds ActiveRecord named scopes that take advantage of PostgreSQL's full text search}
13
- s.description = %q{PgSearch builds ActiveRecord named scopes that take advantage of PostgreSQL's full text search}
12
+ s.summary = %q{PgSearch builds Active Record named scopes that take advantage of PostgreSQL's full text search}
13
+ s.description = %q{PgSearch builds Active Record named scopes that take advantage of PostgreSQL's full text search}
14
+ s.licenses = ["MIT"]
14
15
 
15
16
  s.files = `git ls-files`.split("\n")
16
17
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
19
  s.require_paths = ["lib"]
19
20
 
20
- s.add_dependency 'activerecord', '>=3'
21
- s.add_dependency 'activesupport', '>=3'
21
+ s.add_dependency 'activerecord', '>=3.1'
22
+ s.add_dependency 'activesupport', '>=3.1'
22
23
  end
@@ -343,6 +343,42 @@ describe PgSearch do
343
343
  results.should_not include(excluded)
344
344
  end
345
345
  end
346
+
347
+ context "when including the associated model" do
348
+ with_model :Parent do
349
+ table do |t|
350
+ t.text :name
351
+ end
352
+
353
+ model do
354
+ has_many :children
355
+ include PgSearch
356
+ pg_search_scope :search_name, :against => :name
357
+ end
358
+ end
359
+
360
+ with_model :Child do
361
+ table do |t|
362
+ t.belongs_to :parent
363
+ end
364
+
365
+ model do
366
+ belongs_to :parent
367
+ end
368
+ end
369
+
370
+ # https://github.com/Casecommons/pg_search/issues/14
371
+ it "supports queries with periods" do
372
+ included = Parent.create!(:name => 'bar.foo')
373
+ excluded = Parent.create!(:name => 'foo.bar')
374
+
375
+ results = Parent.search_name('bar.foo').includes(:children)
376
+ results.to_a
377
+
378
+ results.should include(included)
379
+ results.should_not include(excluded)
380
+ end
381
+ end
346
382
  end
347
383
 
348
384
  context "merging a pg_search_scope into another model's scope" do
@@ -1,7 +1,6 @@
1
1
  require "spec_helper"
2
2
 
3
- describe "an ActiveRecord model which includes PgSearch" do
4
-
3
+ describe "an Active Record model which includes PgSearch" do
5
4
  with_model :ModelWithPgSearch do
6
5
  table do |t|
7
6
  t.string 'title'
@@ -163,9 +162,6 @@ describe "an ActiveRecord model which includes PgSearch" do
163
162
  end
164
163
 
165
164
  it "returns rows that match the query but not its case" do
166
- # \303\241 is a with acute accent
167
- # \303\251 is e with acute accent
168
-
169
165
  included = [ModelWithPgSearch.create!(:content => "foo"),
170
166
  ModelWithPgSearch.create!(:content => "FOO")]
171
167
 
@@ -600,7 +596,11 @@ describe "an ActiveRecord model which includes PgSearch" do
600
596
  end
601
597
 
602
598
  it "should pass the custom configuration down to the specified feature" do
603
- stub_feature = stub(:conditions => "1 = 1", :rank => "1.0")
599
+ stub_feature = stub(
600
+ :conditions => Arel::Nodes::Grouping.new(Arel.sql("1 = 1")),
601
+ :rank => Arel::Nodes::Grouping.new(Arel.sql("1.0"))
602
+ )
603
+
604
604
  PgSearch::Features::TSearch.should_receive(:new).with(anything, @tsearch_config, anything, anything, anything).at_least(:once).and_return(stub_feature)
605
605
  PgSearch::Features::Trigram.should_receive(:new).with(anything, @trigram_config, anything, anything, anything).at_least(:once).and_return(stub_feature)
606
606
 
@@ -734,22 +734,66 @@ describe "an ActiveRecord model which includes PgSearch" do
734
734
 
735
735
  %w[tsearch trigram dmetaphone].each do |feature|
736
736
  context "using the #{feature} ranking algorithm" do
737
- before do
738
- @scope_name = scope_name = :"search_content_ranked_by_#{feature}"
737
+ it "should return results with a rank" do
738
+ scope_name = :"search_content_ranked_by_#{feature}"
739
739
 
740
740
  ModelWithPgSearch.pg_search_scope scope_name,
741
741
  :against => :content,
742
742
  :ranked_by => ":#{feature}"
743
- end
744
743
 
745
- it "should return results with a rank" do
746
744
  ModelWithPgSearch.create!(:content => 'foo')
747
745
 
748
- results = ModelWithPgSearch.send(@scope_name, 'foo')
746
+ results = ModelWithPgSearch.send(scope_name, 'foo')
749
747
  results.first.pg_search_rank.should be_a Float
750
748
  end
751
749
  end
752
750
  end
751
+
752
+ context "using the tsearch ranking algorithm" do
753
+ it "sorts results by the tsearch rank" do
754
+ ModelWithPgSearch.pg_search_scope :search_content_ranked_by_tsearch,
755
+ :using => :tsearch,
756
+ :against => :content,
757
+ :ranked_by => ":tsearch"
758
+
759
+
760
+ once = ModelWithPgSearch.create!(:content => 'foo bar')
761
+ twice = ModelWithPgSearch.create!(:content => 'foo foo')
762
+
763
+ results = ModelWithPgSearch.search_content_ranked_by_tsearch('foo')
764
+ results.index(twice).should be < results.index(once)
765
+ end
766
+ end
767
+
768
+ context "using the trigram ranking algorithm" do
769
+ it "sorts results by the trigram rank" do
770
+ ModelWithPgSearch.pg_search_scope :search_content_ranked_by_trigram,
771
+ :using => :trigram,
772
+ :against => :content,
773
+ :ranked_by => ":trigram"
774
+
775
+ close = ModelWithPgSearch.create!(:content => 'abcdef')
776
+ exact = ModelWithPgSearch.create!(:content => 'abc')
777
+
778
+ results = ModelWithPgSearch.search_content_ranked_by_trigram('abc')
779
+ results.index(exact).should be < results.index(close)
780
+ end
781
+ end
782
+
783
+ context "using the dmetaphone ranking algorithm" do
784
+ it "sorts results by the dmetaphone rank" do
785
+ ModelWithPgSearch.pg_search_scope :search_content_ranked_by_dmetaphone,
786
+ :using => :dmetaphone,
787
+ :against => :content,
788
+ :ranked_by => ":dmetaphone"
789
+
790
+ once = ModelWithPgSearch.create!(:content => 'Phoo Bar')
791
+ twice = ModelWithPgSearch.create!(:content => 'Phoo Fu')
792
+
793
+ results = ModelWithPgSearch.search_content_ranked_by_dmetaphone('foo')
794
+ results.index(twice).should be < results.index(once)
795
+ end
796
+ end
753
797
  end
754
798
 
755
799
  context "on an STI subclass" do
File without changes
@@ -0,0 +1,26 @@
1
+ require "spec_helper"
2
+
3
+ describe PgSearch::Features::Trigram do
4
+ describe "#rank" do
5
+ with_model :Model do
6
+ table do |t|
7
+ t.string :name
8
+ t.text :content
9
+ end
10
+ end
11
+
12
+ it "returns an expression using the similarity() function" do
13
+ query = "query"
14
+ columns = [
15
+ PgSearch::Configuration::Column.new(:name, nil, Model),
16
+ PgSearch::Configuration::Column.new(:content, nil, Model),
17
+ ]
18
+ options = stub(:options)
19
+ config = stub(:config, :ignore => [])
20
+ normalizer = PgSearch::Normalizer.new(config)
21
+
22
+ feature = described_class.new(query, options, columns, Model, normalizer)
23
+ feature.rank.to_sql.should == %Q{(similarity((coalesce(#{Model.quoted_table_name}."name"::text, '') || ' ' || coalesce(#{Model.quoted_table_name}."content"::text, '')), 'query'))}
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,51 @@
1
+ require "spec_helper"
2
+
3
+ describe PgSearch::Features::TSearch do
4
+ describe "#rank" do
5
+ with_model :Model do
6
+ table do |t|
7
+ t.string :name
8
+ t.text :content
9
+ end
10
+ end
11
+
12
+ it "returns an expression using the ts_rank() function" do
13
+ query = "query"
14
+ columns = [
15
+ PgSearch::Configuration::Column.new(:name, nil, Model),
16
+ PgSearch::Configuration::Column.new(:content, nil, Model),
17
+ ]
18
+ options = {}
19
+ config = stub(:config, :ignore => [])
20
+ normalizer = PgSearch::Normalizer.new(config)
21
+
22
+ feature = described_class.new(query, options, columns, Model, normalizer)
23
+ feature.rank.to_sql.should ==
24
+ %Q{(ts_rank((to_tsvector('simple', coalesce(#{Model.quoted_table_name}."name"::text, '')) || to_tsvector('simple', coalesce(#{Model.quoted_table_name}."content"::text, ''))), (to_tsquery('simple', ''' ' || 'query' || ' ''')), 0))}
25
+ end
26
+ end
27
+
28
+ describe "#conditions" do
29
+ with_model :Model do
30
+ table do |t|
31
+ t.string :name
32
+ t.text :content
33
+ end
34
+ end
35
+
36
+ it "returns an expression using the @@ infix operator" do
37
+ query = "query"
38
+ columns = [
39
+ PgSearch::Configuration::Column.new(:name, nil, Model),
40
+ PgSearch::Configuration::Column.new(:content, nil, Model),
41
+ ]
42
+ options = {}
43
+ config = stub(:config, :ignore => [])
44
+ normalizer = PgSearch::Normalizer.new(config)
45
+
46
+ feature = described_class.new(query, options, columns, Model, normalizer)
47
+ feature.conditions.to_sql.should ==
48
+ %Q{((to_tsvector('simple', coalesce(#{Model.quoted_table_name}."name"::text, '')) || to_tsvector('simple', coalesce(#{Model.quoted_table_name}."content"::text, ''))) @@ (to_tsquery('simple', ''' ' || 'query' || ' ''')))}
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,82 @@
1
+ require "spec_helper"
2
+
3
+ describe PgSearch::Normalizer do
4
+ describe "#add_normalization" do
5
+ context "for PostgreSQL 9.0 and above" do
6
+ context "when config[:ignore] includes :accents" do
7
+ context "when passed an Arel node" do
8
+ it "wraps the expression in unaccent()" do
9
+ config = stub("config", :ignore => [:accents], :postgresql_version => 90000)
10
+ node = Arel::Nodes::NamedFunction.new("foo", ["bar"])
11
+
12
+ normalizer = PgSearch::Normalizer.new(config)
13
+ normalizer.add_normalization(node).should == "unaccent(foo('bar'))"
14
+ end
15
+
16
+ context "when a custom unaccent function is specified" do
17
+ it "wraps the expression in that function" do
18
+ PgSearch.stub(:unaccent_function).and_return("my_unaccent")
19
+ node = Arel::Nodes::NamedFunction.new("foo", ["bar"])
20
+
21
+ config = stub("config", :ignore => [:accents], :postgresql_version => 90000)
22
+
23
+ normalizer = PgSearch::Normalizer.new(config)
24
+ normalizer.add_normalization(node).should == "my_unaccent(foo('bar'))"
25
+ end
26
+ end
27
+ end
28
+
29
+ context "when passed a String" do
30
+ it "wraps the expression in unaccent()" do
31
+ config = stub("config", :ignore => [:accents], :postgresql_version => 90000)
32
+
33
+ normalizer = PgSearch::Normalizer.new(config)
34
+ normalizer.add_normalization("foo").should == "unaccent(foo)"
35
+ end
36
+
37
+ context "when a custom unaccent function is specified" do
38
+ it "wraps the expression in that function" do
39
+ PgSearch.stub(:unaccent_function).and_return("my_unaccent")
40
+
41
+ config = stub("config", :ignore => [:accents], :postgresql_version => 90000)
42
+
43
+ normalizer = PgSearch::Normalizer.new(config)
44
+ normalizer.add_normalization("foo").should == "my_unaccent(foo)"
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ context "when config[:ignore] does not include :accents" do
51
+ it "passes the expression through" do
52
+ config = stub("config", :ignore => [], :postgresql_version => 90000)
53
+
54
+ normalizer = PgSearch::Normalizer.new(config)
55
+ normalizer.add_normalization("foo").should == "foo"
56
+ end
57
+ end
58
+ end
59
+
60
+ context "for PostgreSQL versions before 9.0" do
61
+ context "when config[:ignore] includes :accents" do
62
+ it "raises a NotSupportedForPostgresqlVersion exception" do
63
+ config = stub("config", :ignore => [:accents], :postgresql_version => 89999)
64
+
65
+ normalizer = PgSearch::Normalizer.new(config)
66
+ expect {
67
+ normalizer.add_normalization("foo")
68
+ }.to raise_exception(PgSearch::NotSupportedForPostgresqlVersion)
69
+ end
70
+ end
71
+
72
+ context "when config[:ignore] does not include :accents" do
73
+ it "passes the expression through" do
74
+ config = stub("config", :ignore => [], :postgresql_version => 90000)
75
+
76
+ normalizer = PgSearch::Normalizer.new(config)
77
+ normalizer.add_normalization("foo").should == "foo"
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,12 @@
1
1
  require "bundler/setup"
2
2
  require "pg_search"
3
3
 
4
+ begin
5
+ require 'coveralls'
6
+ Coveralls.wear!
7
+ rescue LoadError
8
+ end
9
+
4
10
  begin
5
11
  require "pg"
6
12
  error_class = PGError
@@ -73,13 +79,19 @@ unless postgresql_version < 90000
73
79
  end
74
80
  install_extension_if_missing("fuzzystrmatch", "SELECT dmetaphone('foo')", "f")
75
81
 
82
+ def load_sql(filename)
83
+ connection = ActiveRecord::Base.connection
84
+ file_contents = File.read(File.join(File.dirname(__FILE__), '..', 'sql', filename))
85
+ connection.execute(file_contents)
86
+ end
87
+
76
88
  if postgresql_version < 80400
77
89
  unless connection.select_value("SELECT 1 FROM pg_catalog.pg_aggregate WHERE aggfnoid = 'array_agg'::REGPROC") == "1"
78
- connection.execute(File.read(File.join(File.dirname(__FILE__), '..', 'sql', 'array_agg.sql')))
90
+ load_sql("array_agg.sql")
79
91
  end
80
- connection.execute(File.read(File.join(File.dirname(__FILE__), '..', 'sql', 'unnest.sql')))
92
+ load_sql("unnest.sql")
81
93
  end
82
- connection.execute(File.read(File.join(File.dirname(__FILE__), '..', 'sql', 'dmetaphone.sql')))
94
+ load_sql("dmetaphone.sql")
83
95
 
84
96
  require "with_model"
85
97
 
@@ -94,45 +106,3 @@ DOCUMENTS_SCHEMA = lambda do |t|
94
106
  t.text :content
95
107
  t.timestamps
96
108
  end
97
-
98
- require 'irb'
99
-
100
- class IRB::Irb
101
- alias initialize_orig initialize
102
- def initialize(workspace = nil, *args)
103
- default = IRB.conf[:DEFAULT_OBJECT]
104
- workspace ||= IRB::WorkSpace.new default if default
105
- initialize_orig(workspace, *args)
106
- end
107
- end
108
-
109
- # Drop into an IRB session for whatever object you pass in:
110
- #
111
- # class Dude
112
- # def abides
113
- # true
114
- # end
115
- # end
116
- #
117
- # console_for(Dude.new)
118
- #
119
- # Then type "quit" or "exit" to get out. In a step definition, it should look like:
120
- #
121
- # When /^I console/ do
122
- # console_for(self)
123
- # end
124
- #
125
- # Also, I definitely stole this hack from some mailing list post somewhere. I wish I
126
- # could remember who did it, but I can't. Sorry!
127
- def console_for(target)
128
- puts "== ENTERING CONSOLE MODE. ==\nType 'exit' to move on.\nContext: #{target.inspect}"
129
-
130
- begin
131
- oldargs = ARGV.dup
132
- ARGV.clear
133
- IRB.conf[:DEFAULT_OBJECT] = target
134
- IRB.start
135
- ensure
136
- ARGV.replace(oldargs)
137
- end
138
- end
data/sql/dmetaphone.sql CHANGED
@@ -1,3 +1,3 @@
1
1
  CREATE OR REPLACE FUNCTION pg_search_dmetaphone(text) RETURNS text LANGUAGE SQL IMMUTABLE STRICT AS $function$
2
- SELECT array_to_string(ARRAY(SELECT dmetaphone(unnest(regexp_split_to_array($1, E'\\\\s+')))), ' ')
2
+ SELECT array_to_string(ARRAY(SELECT dmetaphone(unnest(regexp_split_to_array($1, E'\\s+')))), ' ')
3
3
  $function$;
metadata CHANGED
@@ -1,51 +1,48 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg_search
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.7
5
- prerelease:
4
+ version: 0.6.0
6
5
  platform: ruby
7
6
  authors:
7
+ - Grant Hutchins
8
8
  - Case Commons, LLC
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-07 00:00:00.000000000 Z
12
+ date: 2013-04-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
16
16
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
17
  requirements:
19
- - - ! '>='
18
+ - - '>='
20
19
  - !ruby/object:Gem::Version
21
- version: '3'
20
+ version: '3.1'
22
21
  type: :runtime
23
22
  prerelease: false
24
23
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
24
  requirements:
27
- - - ! '>='
25
+ - - '>='
28
26
  - !ruby/object:Gem::Version
29
- version: '3'
27
+ version: '3.1'
30
28
  - !ruby/object:Gem::Dependency
31
29
  name: activesupport
32
30
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
31
  requirements:
35
- - - ! '>='
32
+ - - '>='
36
33
  - !ruby/object:Gem::Version
37
- version: '3'
34
+ version: '3.1'
38
35
  type: :runtime
39
36
  prerelease: false
40
37
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
38
  requirements:
43
- - - ! '>='
39
+ - - '>='
44
40
  - !ruby/object:Gem::Version
45
- version: '3'
46
- description: PgSearch builds ActiveRecord named scopes that take advantage of PostgreSQL's
41
+ version: '3.1'
42
+ description: PgSearch builds Active Record named scopes that take advantage of PostgreSQL's
47
43
  full text search
48
44
  email:
45
+ - gems@nertzy.com
49
46
  - casecommons-dev@googlegroups.com
50
47
  executables: []
51
48
  extensions: []
@@ -54,10 +51,10 @@ files:
54
51
  - .autotest
55
52
  - .gitignore
56
53
  - .rspec
57
- - .rvmrc
58
54
  - .travis.yml
59
55
  - CHANGELOG.rdoc
60
56
  - Gemfile
57
+ - Guardfile
61
58
  - LICENSE
62
59
  - README.rdoc
63
60
  - Rakefile
@@ -87,13 +84,15 @@ files:
87
84
  - lib/pg_search/tasks.rb
88
85
  - lib/pg_search/version.rb
89
86
  - pg_search.gemspec
90
- - spec/associations_spec.rb
91
- - spec/pg_search/document_spec.rb
92
- - spec/pg_search/multisearch/rebuilder_spec.rb
93
- - spec/pg_search/multisearch_spec.rb
94
- - spec/pg_search/multisearchable_spec.rb
95
- - spec/pg_search/normalizer_spec.rb
96
- - spec/pg_search_spec.rb
87
+ - spec/integration/associations_spec.rb
88
+ - spec/integration/pg_search_spec.rb
89
+ - spec/lib/pg_search/document_spec.rb
90
+ - spec/lib/pg_search/features/trigram_spec.rb
91
+ - spec/lib/pg_search/features/tsearch_spec.rb
92
+ - spec/lib/pg_search/multisearch/rebuilder_spec.rb
93
+ - spec/lib/pg_search/multisearch_spec.rb
94
+ - spec/lib/pg_search/multisearchable_spec.rb
95
+ - spec/lib/pg_search/normalizer_spec.rb
97
96
  - spec/spec_helper.rb
98
97
  - sql/array_agg.sql
99
98
  - sql/dmetaphone.sql
@@ -102,42 +101,38 @@ files:
102
101
  - sql/uninstall_unnest.sql
103
102
  - sql/unnest.sql
104
103
  homepage: https://github.com/Casecommons/pg_search
105
- licenses: []
104
+ licenses:
105
+ - MIT
106
+ metadata: {}
106
107
  post_install_message:
107
108
  rdoc_options: []
108
109
  require_paths:
109
110
  - lib
110
111
  required_ruby_version: !ruby/object:Gem::Requirement
111
- none: false
112
112
  requirements:
113
- - - ! '>='
113
+ - - '>='
114
114
  - !ruby/object:Gem::Version
115
115
  version: '0'
116
- segments:
117
- - 0
118
- hash: -1475822108196160881
119
116
  required_rubygems_version: !ruby/object:Gem::Requirement
120
- none: false
121
117
  requirements:
122
- - - ! '>='
118
+ - - '>='
123
119
  - !ruby/object:Gem::Version
124
120
  version: '0'
125
- segments:
126
- - 0
127
- hash: -1475822108196160881
128
121
  requirements: []
129
122
  rubyforge_project:
130
- rubygems_version: 1.8.24
123
+ rubygems_version: 2.0.3
131
124
  signing_key:
132
- specification_version: 3
133
- summary: PgSearch builds ActiveRecord named scopes that take advantage of PostgreSQL's
125
+ specification_version: 4
126
+ summary: PgSearch builds Active Record named scopes that take advantage of PostgreSQL's
134
127
  full text search
135
128
  test_files:
136
- - spec/associations_spec.rb
137
- - spec/pg_search/document_spec.rb
138
- - spec/pg_search/multisearch/rebuilder_spec.rb
139
- - spec/pg_search/multisearch_spec.rb
140
- - spec/pg_search/multisearchable_spec.rb
141
- - spec/pg_search/normalizer_spec.rb
142
- - spec/pg_search_spec.rb
129
+ - spec/integration/associations_spec.rb
130
+ - spec/integration/pg_search_spec.rb
131
+ - spec/lib/pg_search/document_spec.rb
132
+ - spec/lib/pg_search/features/trigram_spec.rb
133
+ - spec/lib/pg_search/features/tsearch_spec.rb
134
+ - spec/lib/pg_search/multisearch/rebuilder_spec.rb
135
+ - spec/lib/pg_search/multisearch_spec.rb
136
+ - spec/lib/pg_search/multisearchable_spec.rb
137
+ - spec/lib/pg_search/normalizer_spec.rb
143
138
  - spec/spec_helper.rb
data/.rvmrc DELETED
@@ -1,52 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- # This is an RVM Project .rvmrc file, used to automatically load the ruby
4
- # development environment upon cd'ing into the directory
5
-
6
- # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional,
7
- # Only full ruby name is supported here, for short names use:
8
- # echo "rvm use 1.9.3" > .rvmrc
9
- environment_id="ruby-1.9.3-p194@pg_search"
10
-
11
- # Uncomment the following lines if you want to verify rvm version per project
12
- # rvmrc_rvm_version="1.12.4 ()" # 1.10.1 seams as a safe start
13
- # eval "$(echo ${rvm_version}.${rvmrc_rvm_version} | awk -F. '{print "[[ "$1*65536+$2*256+$3" -ge "$4*65536+$5*256+$6" ]]"}' )" || {
14
- # echo "This .rvmrc file requires at least RVM ${rvmrc_rvm_version}, aborting loading."
15
- # return 1
16
- # }
17
-
18
- # First we attempt to load the desired environment directly from the environment
19
- # file. This is very fast and efficient compared to running through the entire
20
- # CLI and selector. If you want feedback on which environment was used then
21
- # insert the word 'use' after --create as this triggers verbose mode.
22
- if [[ -d "${rvm_path:-$HOME/.rvm}/environments"
23
- && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]]
24
- then
25
- \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
26
- [[ -s "${rvm_path:-$HOME/.rvm}/hooks/after_use" ]] &&
27
- \. "${rvm_path:-$HOME/.rvm}/hooks/after_use" || true
28
- if [[ $- == *i* ]] # check for interactive shells
29
- then echo "Using: $(tput setaf 2)$GEM_HOME$(tput sgr0)" # show the user the ruby and gemset they are using in green
30
- else echo "Using: $GEM_HOME" # don't use colors in non-interactive shells
31
- fi
32
- else
33
- # If the environment file has not yet been created, use the RVM CLI to select.
34
- rvm --create use "$environment_id" || {
35
- echo "Failed to create RVM environment '${environment_id}'."
36
- return 1
37
- }
38
- fi
39
-
40
- # If you use bundler, this might be useful to you:
41
- if [[ -s Gemfile ]] && {
42
- ! builtin command -v bundle >/dev/null ||
43
- builtin command -v bundle | grep $rvm_path/bin/bundle >/dev/null
44
- }
45
- then
46
- printf "%b" "The rubygem 'bundler' is not installed. Installing it now.\n"
47
- gem install bundler
48
- fi
49
- if [[ -s Gemfile ]] && builtin command -v bundle >/dev/null
50
- then
51
- bundle install | grep -vE '^Using|Your bundle is complete'
52
- fi
@@ -1,58 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe PgSearch::Normalizer do
4
- describe "#add_normalization" do
5
- context "for PostgreSQL 9.0 and above" do
6
- context "when config[:ignore] includes :accents" do
7
- it "wraps the expression in unaccent()" do
8
- config = stub("config", :ignore => [:accents], :postgresql_version => 90000)
9
-
10
- normalizer = PgSearch::Normalizer.new(config)
11
- normalizer.add_normalization("foo").should == "unaccent(foo)"
12
- end
13
-
14
- context "when a custom unaccent function is specified" do
15
- it "wraps the expression in that function" do
16
- PgSearch.stub(:unaccent_function).and_return("my_unaccent")
17
-
18
- config = stub("config", :ignore => [:accents], :postgresql_version => 90000)
19
-
20
- normalizer = PgSearch::Normalizer.new(config)
21
- normalizer.add_normalization("foo").should == "my_unaccent(foo)"
22
- end
23
- end
24
- end
25
-
26
- context "when config[:ignore] does not include :accents" do
27
- it "passes the expression through" do
28
- config = stub("config", :ignore => [], :postgresql_version => 90000)
29
-
30
- normalizer = PgSearch::Normalizer.new(config)
31
- normalizer.add_normalization("foo").should == "foo"
32
- end
33
- end
34
- end
35
-
36
- context "for PostgreSQL versions before 9.0" do
37
- context "when config[:ignore] includes :accents" do
38
- it "raises a NotSupportedForPostgresqlVersion exception" do
39
- config = stub("config", :ignore => [:accents], :postgresql_version => 89999)
40
-
41
- normalizer = PgSearch::Normalizer.new(config)
42
- expect {
43
- normalizer.add_normalization("foo")
44
- }.to raise_exception(PgSearch::NotSupportedForPostgresqlVersion)
45
- end
46
- end
47
-
48
- context "when config[:ignore] does not include :accents" do
49
- it "passes the expression through" do
50
- config = stub("config", :ignore => [], :postgresql_version => 90000)
51
-
52
- normalizer = PgSearch::Normalizer.new(config)
53
- normalizer.add_normalization("foo").should == "foo"
54
- end
55
- end
56
- end
57
- end
58
- end