pg_search 0.5.4 → 0.5.5

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.rdoc CHANGED
@@ -1,5 +1,11 @@
1
1
  = PgSearch
2
2
 
3
+ == 0.5.5
4
+
5
+ * Fix bug with single table inheritance.
6
+
7
+ * Allow option for specifying an alternate function for unaccent().
8
+
3
9
  == 0.5.4
4
10
 
5
11
  * Fix bug in associated_against join clause when search scope is chained after other scopes.
data/README.rdoc CHANGED
@@ -495,6 +495,10 @@ Ignoring accents uses the {unaccent contrib package}[http://www.postgresql.org/d
495
495
  SpanishQuestion.gringo_search("Que") # => [what]
496
496
  SpanishQuestion.gringo_search("Cüåñtô") # => [how_many]
497
497
 
498
+ Advanced users may wish to add indexes for the expressions that pg_search generates. Unfortunately, the unaccent function supplied by this contrib package is not indexable (as of PostgreSQL 9.1). Thus, you may want to write your own wrapper function and use it instead. This can be configured by calling the following code, perhaps in an initializer.
499
+
500
+ PgSearch.unaccent_function = "my_unaccent"
501
+
498
502
  === Using tsvector columns
499
503
 
500
504
  PostgreSQL allows you the ability to search against a column with type tsvector instead of using an expression; this speeds up searching dramatically as it offloads creation of the tsvector that the tsquery is evaluated against.
data/lib/pg_search.rb CHANGED
@@ -18,11 +18,25 @@ module PgSearch
18
18
  mattr_accessor :multisearch_options
19
19
  self.multisearch_options = {}
20
20
 
21
+ mattr_accessor :unaccent_function
22
+ self.unaccent_function = "unaccent"
23
+
21
24
  module ClassMethods
22
25
  def pg_search_scope(name, options)
23
- scope = PgSearch::Scope.new(name, self, options)
26
+ options_proc = if options.respond_to?(:call)
27
+ options
28
+ else
29
+ unless options.respond_to?(:merge)
30
+ raise ArgumentError, "pg_search_scope expects a Hash or Proc"
31
+ end
32
+ lambda { |query| {:query => query}.merge(options) }
33
+ end
24
34
 
25
- method_proc = scope.method(:build_relation)
35
+ method_proc = lambda do |*args|
36
+ config = Configuration.new(options_proc.call(*args), self)
37
+ scope_options = ScopeOptions.new(config)
38
+ scope_options.apply(self)
39
+ end
26
40
 
27
41
  if respond_to?(:define_singleton_method)
28
42
  define_singleton_method name, &method_proc
@@ -15,7 +15,7 @@ module PgSearch
15
15
 
16
16
  class << self
17
17
  def alias(*strings)
18
- name = Array.wrap(strings).compact.join("_")
18
+ name = Array(strings).compact.join("_")
19
19
  # By default, PostgreSQL limits names to 32 characters, so we hash and limit to 32 characters.
20
20
  "pg_search_#{Digest::SHA2.hexdigest(name)}"[0,32]
21
21
  end
@@ -26,16 +26,16 @@ module PgSearch
26
26
  end
27
27
 
28
28
  def regular_columns
29
- return [] unless @options[:against]
30
- Array(@options[:against]).map do |column_name, weight|
31
- Column.new(column_name, weight, @model)
29
+ return [] unless options[:against]
30
+ Array(options[:against]).map do |column_name, weight|
31
+ Column.new(column_name, weight, model)
32
32
  end
33
33
  end
34
34
 
35
35
  def associations
36
- return [] unless @options[:associated_against]
37
- @options[:associated_against].map do |association, column_names|
38
- Association.new(@model, association, column_names)
36
+ return [] unless options[:associated_against]
37
+ options[:associated_against].map do |association, column_names|
38
+ Association.new(model, association, column_names)
39
39
  end.flatten
40
40
  end
41
41
 
@@ -44,35 +44,33 @@ module PgSearch
44
44
  end
45
45
 
46
46
  def query
47
- @options[:query].to_s
47
+ options[:query].to_s
48
48
  end
49
49
 
50
50
  def ignore
51
- Array.wrap(@options[:ignoring])
51
+ Array(options[:ignoring])
52
52
  end
53
53
 
54
54
  def ranking_sql
55
- @options[:ranked_by]
55
+ options[:ranked_by]
56
56
  end
57
57
 
58
58
  def features
59
- Array(@options[:using])
59
+ Array(options[:using])
60
60
  end
61
61
 
62
62
  def order_within_rank
63
- @options[:order_within_rank]
63
+ options[:order_within_rank]
64
64
  end
65
65
 
66
66
  def postgresql_version
67
- @model.connection.send(:postgresql_version)
68
- end
69
-
70
- def logger
71
- @model.logger
67
+ model.connection.send(:postgresql_version)
72
68
  end
73
69
 
74
70
  private
75
71
 
72
+ attr_reader :options
73
+
76
74
  def default_options
77
75
  {:using => :tsearch}
78
76
  end
@@ -97,7 +95,7 @@ module PgSearch
97
95
  options.assert_valid_keys(VALID_KEYS)
98
96
 
99
97
  VALID_VALUES.each do |key, values_for_key|
100
- Array.wrap(options[key]).each do |value|
98
+ Array(options[key]).each do |value|
101
99
  unless values_for_key.include?(value)
102
100
  raise ArgumentError, ":#{key} cannot accept #{value}"
103
101
  end
@@ -27,7 +27,7 @@ module PgSearch
27
27
  private
28
28
 
29
29
  def update_content
30
- methods = Array.wrap(searchable.pg_search_multisearchable_options[:against])
30
+ methods = Array(searchable.pg_search_multisearchable_options[:against])
31
31
  searchable_text = methods.map { |symbol| searchable.send(symbol) }.join(" ")
32
32
  self.content = searchable_text
33
33
  end
@@ -8,23 +8,31 @@ module PgSearch
8
8
  end
9
9
 
10
10
  def conditions
11
- @tsearch.conditions
11
+ tsearch.conditions
12
12
  end
13
13
 
14
14
  def rank
15
- @tsearch.rank
15
+ tsearch.rank
16
16
  end
17
17
 
18
+ private
19
+
20
+ attr_reader :tsearch
21
+
18
22
  # Decorates a normalizer with dmetaphone processing.
19
23
  class Normalizer
20
24
  def initialize(normalizer_to_wrap)
21
- @decorated_normalizer = normalizer_to_wrap
25
+ @normalizer_to_wrap = normalizer_to_wrap
22
26
  end
23
27
 
24
28
  def add_normalization(original_sql)
25
- otherwise_normalized_sql = @decorated_normalizer.add_normalization(original_sql)
29
+ otherwise_normalized_sql = normalizer_to_wrap.add_normalization(original_sql)
26
30
  "pg_search_dmetaphone(#{otherwise_normalized_sql})"
27
31
  end
32
+
33
+ private
34
+
35
+ attr_reader :normalizer_to_wrap
28
36
  end
29
37
  end
30
38
  end
@@ -11,17 +11,19 @@ module PgSearch
11
11
 
12
12
  private
13
13
 
14
+ attr_reader :query, :options, :columns, :model, :normalizer
15
+
14
16
  def document
15
- if @columns.length == 1
16
- @columns.first.to_sql
17
+ if columns.length == 1
18
+ columns.first.to_sql
17
19
  else
18
- expressions = @columns.map { |column| column.to_sql }.join(", ")
20
+ expressions = columns.map { |column| column.to_sql }.join(", ")
19
21
  "array_to_string(ARRAY[#{expressions}], ' ')"
20
22
  end
21
23
  end
22
24
 
23
25
  def normalize(expression)
24
- @normalizer.add_normalization(expression)
26
+ normalizer.add_normalization(expression)
25
27
  end
26
28
  end
27
29
  end
@@ -4,14 +4,14 @@ module PgSearch
4
4
  def conditions
5
5
  [
6
6
  "(#{normalize(document)}) % #{normalize(":query")}",
7
- {:query => @query}
7
+ {:query => query}
8
8
  ]
9
9
  end
10
10
 
11
11
  def rank
12
12
  [
13
13
  "similarity((#{normalize(document)}), #{normalize(":query")})",
14
- {:query => @query}
14
+ {:query => query}
15
15
  ]
16
16
  end
17
17
  end
@@ -5,10 +5,10 @@ module PgSearch
5
5
  class TSearch < Feature
6
6
  delegate :connection, :quoted_table_name, :to => :'@model'
7
7
 
8
- def initialize(query, options, columns, model, normalizer)
8
+ def initialize(*args)
9
9
  super
10
10
 
11
- if @options[:prefix] && @model.connection.send(:postgresql_version) < 80400
11
+ if options[:prefix] && model.connection.send(:postgresql_version) < 80400
12
12
  raise PgSearch::NotSupportedForPostgresqlVersion.new(<<-MESSAGE.gsub /^\s*/, '')
13
13
  Sorry, {:using => {:tsearch => {:prefix => true}}} only works in PostgreSQL 8.4 and above.")
14
14
  MESSAGE
@@ -26,7 +26,7 @@ module PgSearch
26
26
  private
27
27
 
28
28
  def interpolations
29
- {:query => @query.to_s, :dictionary => dictionary.to_s}
29
+ {:query => query.to_s, :dictionary => dictionary.to_s}
30
30
  end
31
31
 
32
32
  DISALLOWED_TSQUERY_CHARACTERS = /['?\\:]/
@@ -42,25 +42,25 @@ module PgSearch
42
42
  connection.quote("' "),
43
43
  term_sql,
44
44
  connection.quote(" '"),
45
- (connection.quote(':*') if @options[:prefix])
45
+ (connection.quote(':*') if options[:prefix])
46
46
  ].compact.join(" || ")
47
47
 
48
48
  "to_tsquery(:dictionary, #{tsquery_sql})"
49
49
  end
50
50
 
51
51
  def tsquery
52
- return "''" if @query.blank?
53
- query_terms = @query.split(" ").compact
52
+ return "''" if query.blank?
53
+ query_terms = query.split(" ").compact
54
54
  tsquery_terms = query_terms.map { |term| tsquery_for_term(term) }
55
- tsquery_terms.join(@options[:any_word] ? ' || ' : ' && ')
55
+ tsquery_terms.join(options[:any_word] ? ' || ' : ' && ')
56
56
  end
57
57
 
58
58
  def tsdocument
59
- if @options[:tsvector_column]
60
- column_name = connection.quote_column_name(@options[:tsvector_column])
59
+ if options[:tsvector_column]
60
+ column_name = connection.quote_column_name(options[:tsvector_column])
61
61
  "#{quoted_table_name}.#{column_name}"
62
62
  else
63
- @columns.map do |search_column|
63
+ columns.map do |search_column|
64
64
  tsvector = "to_tsvector(:dictionary, #{normalize(search_column.to_sql)})"
65
65
  if search_column.weight.nil?
66
66
  tsvector
@@ -81,7 +81,7 @@ module PgSearch
81
81
  # 32 divides the rank by itself + 1
82
82
  # The integer option controls several behaviors, so it is a bit mask: you can specify one or more behaviors
83
83
  def normalization
84
- @options[:normalization] || 0
84
+ options[:normalization] || 0
85
85
  end
86
86
 
87
87
  def tsearch_rank
@@ -89,7 +89,7 @@ module PgSearch
89
89
  end
90
90
 
91
91
  def dictionary
92
- @options[:dictionary] || :simple
92
+ options[:dictionary] || :simple
93
93
  end
94
94
  end
95
95
  end
@@ -1,18 +1,6 @@
1
1
  module PgSearch
2
2
  module Multisearch
3
3
  class Rebuilder
4
- REBUILD_SQL_TEMPLATE = <<-SQL
5
- INSERT INTO :documents_table (searchable_type, searchable_id, content, created_at, updated_at)
6
- SELECT :model_name AS searchable_type,
7
- :model_table.id AS searchable_id,
8
- (
9
- :content_expressions
10
- ) AS content,
11
- :current_time AS created_at,
12
- :current_time AS updated_at
13
- FROM :model_table
14
- SQL
15
-
16
4
  def initialize(model)
17
5
  unless model.respond_to?(:pg_search_multisearchable_options)
18
6
  raise ModelNotMultisearchable.new(model)
@@ -22,19 +10,33 @@ SQL
22
10
  end
23
11
 
24
12
  def rebuild
25
- if @model.respond_to?(:rebuild_pg_search_documents)
26
- @model.rebuild_pg_search_documents
13
+ if model.respond_to?(:rebuild_pg_search_documents)
14
+ model.rebuild_pg_search_documents
27
15
  else
28
- @model.connection.execute(rebuild_sql)
16
+ model.connection.execute(rebuild_sql)
29
17
  end
30
18
  end
31
19
 
32
20
  private
33
21
 
22
+ attr_reader :model
23
+
34
24
  def connection
35
- @model.connection
25
+ model.connection
36
26
  end
37
27
 
28
+ REBUILD_SQL_TEMPLATE = <<-SQL
29
+ INSERT INTO :documents_table (searchable_type, searchable_id, content, created_at, updated_at)
30
+ SELECT :model_name AS searchable_type,
31
+ :model_table.id AS searchable_id,
32
+ (
33
+ :content_expressions
34
+ ) AS content,
35
+ :current_time AS created_at,
36
+ :current_time AS updated_at
37
+ FROM :model_table
38
+ SQL
39
+
38
40
  def rebuild_sql
39
41
  replacements.inject(REBUILD_SQL_TEMPLATE) do |sql, key|
40
42
  sql.gsub ":#{key}", send(key)
@@ -52,15 +54,15 @@ SQL
52
54
  end
53
55
 
54
56
  def columns
55
- Array.wrap(@model.pg_search_multisearchable_options[:against])
57
+ Array(model.pg_search_multisearchable_options[:against])
56
58
  end
57
59
 
58
60
  def model_name
59
- connection.quote(@model.name)
61
+ connection.quote(model.name)
60
62
  end
61
63
 
62
64
  def model_table
63
- @model.quoted_table_name
65
+ model.quoted_table_name
64
66
  end
65
67
 
66
68
  def documents_table
@@ -5,18 +5,22 @@ 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
8
+ if config.ignore.include?(:accents)
9
+ if config.postgresql_version < 90000
10
10
  raise PgSearch::NotSupportedForPostgresqlVersion.new(<<-MESSAGE.gsub /^\s*/, '')
11
11
  Sorry, {:ignoring => :accents} only works in PostgreSQL 9.0 and above.
12
- #{@config.inspect}
12
+ #{config.inspect}
13
13
  MESSAGE
14
14
  else
15
- "unaccent(#{sql_expression})"
15
+ "#{PgSearch.unaccent_function}(#{sql_expression})"
16
16
  end
17
17
  else
18
18
  sql_expression
19
19
  end
20
20
  end
21
+
22
+ private
23
+
24
+ attr_reader :config
21
25
  end
22
26
  end
@@ -2,10 +2,9 @@ require "active_support/core_ext/module/delegation"
2
2
 
3
3
  module PgSearch
4
4
  class ScopeOptions
5
- delegate :connection, :quoted_table_name, :sanitize_sql_array, :to => :@model
5
+ attr_reader :config, :feature_options
6
6
 
7
- def initialize(name, config)
8
- @name = name
7
+ def initialize(config)
9
8
  @config = config
10
9
  @model = config.model
11
10
  @feature_options = Hash[config.features]
@@ -17,14 +16,16 @@ module PgSearch
17
16
 
18
17
  private
19
18
 
19
+ delegate :connection, :quoted_table_name, :sanitize_sql_array, :to => :@model
20
+
20
21
  def conditions
21
- @config.features.map do |feature_name, feature_options|
22
+ config.features.map do |feature_name, feature_options|
22
23
  "(#{sanitize_sql_array(feature_for(feature_name).conditions)})"
23
24
  end.join(" OR ")
24
25
  end
25
26
 
26
27
  def order_within_rank
27
- @config.order_within_rank || "#{primary_key} ASC"
28
+ config.order_within_rank || "#{primary_key} ASC"
28
29
  end
29
30
 
30
31
  def primary_key
@@ -32,7 +33,7 @@ module PgSearch
32
33
  end
33
34
 
34
35
  def joins
35
- @config.associations.map do |association|
36
+ config.associations.map do |association|
36
37
  association.join(primary_key)
37
38
  end.join(' ')
38
39
  end
@@ -49,19 +50,19 @@ module PgSearch
49
50
 
50
51
  raise ArgumentError.new("Unknown feature: #{feature_name}") unless feature_class
51
52
 
52
- normalizer = Normalizer.new(@config)
53
+ normalizer = Normalizer.new(config)
53
54
 
54
55
  feature_class.new(
55
- @config.query,
56
- @feature_options[feature_name],
57
- @config.columns,
58
- @config.model,
56
+ config.query,
57
+ feature_options[feature_name],
58
+ config.columns,
59
+ config.model,
59
60
  normalizer
60
61
  )
61
62
  end
62
63
 
63
64
  def rank
64
- (@config.ranking_sql || ":tsearch").gsub(/:(\w*)/) do
65
+ (config.ranking_sql || ":tsearch").gsub(/:(\w*)/) do
65
66
  sanitize_sql_array(feature_for($1).rank)
66
67
  end
67
68
  end
@@ -1,3 +1,3 @@
1
1
  module PgSearch
2
- VERSION = "0.5.4"
2
+ VERSION = "0.5.5"
3
3
  end
@@ -7,7 +7,7 @@ describe PgSearch::Document do
7
7
  table
8
8
  model do
9
9
  include PgSearch
10
- multisearchable({})
10
+ multisearchable
11
11
  end
12
12
  end
13
13
 
@@ -0,0 +1,58 @@
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
@@ -751,6 +751,50 @@ describe "an ActiveRecord model which includes PgSearch" do
751
751
  end
752
752
  end
753
753
  end
754
+
755
+ context "on an STI subclass" do
756
+ with_model :SuperclassModel do
757
+ table do |t|
758
+ t.text 'content'
759
+ t.string 'type'
760
+ end
761
+
762
+ model do
763
+ include PgSearch
764
+ end
765
+ end
766
+
767
+ before do
768
+ SuperclassModel.pg_search_scope :search_content, :against => :content
769
+
770
+ class SubclassModel < SuperclassModel
771
+ end
772
+
773
+ class AnotherSubclassModel < SuperclassModel
774
+ end
775
+ end
776
+
777
+ it "should returns only results for that subclass" do
778
+ included = [
779
+ SubclassModel.create!(:content => "foo bar")
780
+ ]
781
+ excluded = [
782
+ SubclassModel.create!(:content => "baz"),
783
+ SuperclassModel.create!(:content => "foo bar"),
784
+ SuperclassModel.create!(:content => "baz"),
785
+ AnotherSubclassModel.create!(:content => "foo bar"),
786
+ AnotherSubclassModel.create!(:content => "baz")
787
+ ]
788
+
789
+ SuperclassModel.count.should == 6
790
+ SubclassModel.count.should == 2
791
+
792
+ results = SubclassModel.search_content("foo bar")
793
+
794
+ results.should include(*included)
795
+ results.should_not include(*excluded)
796
+ end
797
+ end
754
798
  end
755
799
 
756
800
  describe ".multisearchable" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg_search
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.4
4
+ version: 0.5.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-07 00:00:00.000000000 Z
12
+ date: 2012-09-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -83,7 +83,6 @@ files:
83
83
  - lib/pg_search/multisearchable.rb
84
84
  - lib/pg_search/normalizer.rb
85
85
  - lib/pg_search/railtie.rb
86
- - lib/pg_search/scope.rb
87
86
  - lib/pg_search/scope_options.rb
88
87
  - lib/pg_search/tasks.rb
89
88
  - lib/pg_search/version.rb
@@ -92,6 +91,7 @@ files:
92
91
  - spec/pg_search/document_spec.rb
93
92
  - spec/pg_search/multisearch_spec.rb
94
93
  - spec/pg_search/multisearchable_spec.rb
94
+ - spec/pg_search/normalizer_spec.rb
95
95
  - spec/pg_search_spec.rb
96
96
  - spec/spec_helper.rb
97
97
  - sql/array_agg.sql
@@ -114,7 +114,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
114
114
  version: '0'
115
115
  segments:
116
116
  - 0
117
- hash: 1787882256283338763
117
+ hash: -4514756727807360588
118
118
  required_rubygems_version: !ruby/object:Gem::Requirement
119
119
  none: false
120
120
  requirements:
@@ -123,7 +123,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
123
123
  version: '0'
124
124
  segments:
125
125
  - 0
126
- hash: 1787882256283338763
126
+ hash: -4514756727807360588
127
127
  requirements: []
128
128
  rubyforge_project:
129
129
  rubygems_version: 1.8.24
@@ -136,5 +136,6 @@ test_files:
136
136
  - spec/pg_search/document_spec.rb
137
137
  - spec/pg_search/multisearch_spec.rb
138
138
  - spec/pg_search/multisearchable_spec.rb
139
+ - spec/pg_search/normalizer_spec.rb
139
140
  - spec/pg_search_spec.rb
140
141
  - spec/spec_helper.rb
@@ -1,27 +0,0 @@
1
- module PgSearch
2
- class Scope
3
- def initialize(name, model, scope_options_or_proc)
4
- @name = name
5
- @model = model
6
- @options_proc = build_options_proc(scope_options_or_proc)
7
- end
8
-
9
- def build_relation(*args)
10
- config = Configuration.new(@options_proc.call(*args), @model)
11
- scope_options = ScopeOptions.new(@name, config)
12
- scope_options.apply(@model)
13
- end
14
-
15
- private
16
-
17
- def build_options_proc(scope_options)
18
- return scope_options if scope_options.respond_to?(:call)
19
-
20
- unless scope_options.respond_to?(:merge)
21
- raise ArgumentError, "pg_search_scope expects a Hash or Proc"
22
- end
23
-
24
- lambda { |query| {:query => query}.merge(scope_options) }
25
- end
26
- end
27
- end