thinking-sphinx 1.3.20 → 1.4.0
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/README.textile +3 -0
- data/VERSION +1 -1
- data/features/excerpts.feature +8 -0
- data/features/field_sorting.feature +18 -0
- data/features/searching_across_models.feature +1 -1
- data/features/searching_by_model.feature +0 -7
- data/features/sphinx_scopes.feature +18 -0
- data/features/step_definitions/common_steps.rb +4 -0
- data/features/step_definitions/search_steps.rb +5 -0
- data/features/support/env.rb +3 -5
- data/features/thinking_sphinx/db/fixtures/people.rb +1 -1
- data/features/thinking_sphinx/models/andrew.rb +17 -0
- data/features/thinking_sphinx/models/person.rb +2 -1
- data/lib/thinking_sphinx.rb +2 -0
- data/lib/thinking_sphinx/active_record.rb +1 -1
- data/lib/thinking_sphinx/active_record/scopes.rb +7 -0
- data/lib/thinking_sphinx/adapters/abstract_adapter.rb +38 -8
- data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +6 -2
- data/lib/thinking_sphinx/attribute.rb +5 -0
- data/lib/thinking_sphinx/configuration.rb +11 -7
- data/lib/thinking_sphinx/context.rb +4 -2
- data/lib/thinking_sphinx/property.rb +1 -0
- data/lib/thinking_sphinx/search.rb +66 -36
- data/lib/thinking_sphinx/tasks.rb +7 -0
- data/spec/thinking_sphinx/active_record/has_many_association_spec.rb +1 -0
- data/spec/thinking_sphinx/active_record/scopes_spec.rb +2 -3
- data/spec/thinking_sphinx/adapters/abstract_adapter_spec.rb +134 -0
- data/spec/thinking_sphinx/configuration_spec.rb +7 -0
- data/spec/thinking_sphinx/context_spec.rb +3 -2
- data/spec/thinking_sphinx/search_spec.rb +67 -25
- data/tasks/distribution.rb +0 -14
- data/tasks/testing.rb +29 -21
- metadata +227 -91
data/README.textile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.4.0
|
data/features/excerpts.feature
CHANGED
@@ -11,3 +11,11 @@ Feature: Generate excerpts for search results
|
|
11
11
|
And I am searching on comments
|
12
12
|
And I search for "lorem"
|
13
13
|
Then calling content on the first result excerpts object should return "de un sitio mientras que mira su diseño. El punto de usar <span class="match">Lorem</span> Ipsum es que tiene una distribución"
|
14
|
+
|
15
|
+
Scenario: Excerpt Options
|
16
|
+
Given Sphinx is running
|
17
|
+
And I am searching on comments
|
18
|
+
And I search for "lorem"
|
19
|
+
And I provide excerpt option "before_match" with value "<em>"
|
20
|
+
And I provide excerpt option "after_match" with value "</em>"
|
21
|
+
Then calling content on the first result excerpts object should return "de un sitio mientras que mira su diseño. El punto de usar <em>Lorem</em> Ipsum es que tiene una distribución"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Feature: Field Sorting
|
2
|
+
In order to sort by strings
|
3
|
+
As a developer
|
4
|
+
I want to enable sorting by existing fields
|
5
|
+
|
6
|
+
Background:
|
7
|
+
Given Sphinx is running
|
8
|
+
And I am searching on people
|
9
|
+
|
10
|
+
Scenario: Searching with ordering on a sortable field
|
11
|
+
When I order by first_name
|
12
|
+
Then I should get 20 results
|
13
|
+
And the first_name of each result should indicate order
|
14
|
+
|
15
|
+
Scenario: Sort on a case insensitive sortable field
|
16
|
+
When I order by last_name
|
17
|
+
Then the first result's "last_name" should be "abbott"
|
18
|
+
|
@@ -7,7 +7,7 @@ Feature: Searching across multiple model
|
|
7
7
|
Given Sphinx is running
|
8
8
|
When I search for James
|
9
9
|
And I am retrieving the result count
|
10
|
-
Then I should get a value of
|
10
|
+
Then I should get a value of 6
|
11
11
|
|
12
12
|
Scenario: Confirming existance of a document id in a given index
|
13
13
|
Given Sphinx is running
|
@@ -97,13 +97,6 @@ Feature: Searching on a single model
|
|
97
97
|
Then I should get 10 results
|
98
98
|
And the value of each result should indicate order
|
99
99
|
|
100
|
-
Scenario: Searching with ordering on a sortable field
|
101
|
-
Given Sphinx is running
|
102
|
-
And I am searching on people
|
103
|
-
And I order by first_name
|
104
|
-
Then I should get 20 results
|
105
|
-
And the first_name of each result should indicate order
|
106
|
-
|
107
100
|
Scenario: Intepreting Sphinx Internal Identifiers
|
108
101
|
Given Sphinx is running
|
109
102
|
And I am searching on people
|
@@ -48,3 +48,21 @@ Feature: Sphinx Scopes
|
|
48
48
|
And I am retrieving the scoped result count for "Byrne"
|
49
49
|
Then I should get a value of 1
|
50
50
|
|
51
|
+
Scenario: Default Scope
|
52
|
+
Given Sphinx is running
|
53
|
+
And I am searching on andrews
|
54
|
+
Then I should get 7 results
|
55
|
+
|
56
|
+
Scenario: Default Scope and additional query terms
|
57
|
+
Given Sphinx is running
|
58
|
+
And I am searching on andrews
|
59
|
+
When I search for "Byrne"
|
60
|
+
Then I should get 1 result
|
61
|
+
|
62
|
+
Scenario: Explicit scope plus search over a default scope
|
63
|
+
Given Sphinx is running
|
64
|
+
And I am searching on andrews
|
65
|
+
When I use the locked_last_name scope
|
66
|
+
And I search for "Cecil"
|
67
|
+
Then I should get 1 result
|
68
|
+
|
@@ -155,6 +155,10 @@ Then /^the (\w+) of each result should indicate order$/ do |attribute|
|
|
155
155
|
end
|
156
156
|
end
|
157
157
|
|
158
|
+
Then /^the first result's "([^"]*)" should be "([^"]*)"$/ do |attribute, value|
|
159
|
+
results.first.send(attribute.to_sym).should == value
|
160
|
+
end
|
161
|
+
|
158
162
|
Then /^I can iterate by result and (\w+)$/ do |attribute|
|
159
163
|
iteration = lambda { |result, attr_value|
|
160
164
|
result.should be_kind_of(@model)
|
@@ -87,3 +87,8 @@ end
|
|
87
87
|
Then /^the first result should have a (\w+\s?\w*) of (\d+)$/ do |attribute, value|
|
88
88
|
results.first.sphinx_attributes[attribute.gsub(/\s+/, '_')].should == value.to_i
|
89
89
|
end
|
90
|
+
|
91
|
+
Given /^I provide excerpt option "([a-z_]*)" with value "([^"]*)"$/ do |k, v|
|
92
|
+
@options[:excerpt_options] ||= {}
|
93
|
+
@options[:excerpt_options][k.to_sym] = v
|
94
|
+
end
|
data/features/support/env.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require 'cucumber'
|
3
|
-
require 'spec'
|
4
2
|
require 'fileutils'
|
5
|
-
require '
|
6
|
-
|
7
|
-
require
|
3
|
+
require 'bundler'
|
4
|
+
|
5
|
+
Bundler.require :default, :development
|
8
6
|
|
9
7
|
$:.unshift File.dirname(__FILE__) + '/../../lib'
|
10
8
|
Dir[File.join(File.dirname(__FILE__), '../../vendor/*/lib')].each do |path|
|
@@ -18,7 +18,7 @@ Person.create :gender => "male", :first_name => "Peter", :middle_initial => "C",
|
|
18
18
|
Person.create :gender => "female", :first_name => "Hollie", :middle_initial => "C", :last_name => "Hunter", :street_address => "34 Cornish Street", :city => "Kensington", :state => "VIC", :postcode => "3031", :email => "Hollie.C.Hunter@mailinator.com", :birthday => "1954/2/16 00:00:00"
|
19
19
|
Person.create :gender => "male", :first_name => "Jonathan", :middle_initial => "C", :last_name => "Turner", :street_address => "2 Kopkes Road", :city => "Carngham", :state => "VIC", :postcode => "3351", :email => "Jonathan.C.Turner@trashymail.com", :birthday => "1963/8/26 00:00:00"
|
20
20
|
Person.create :gender => "female", :first_name => "Kate", :middle_initial => "S", :last_name => "Doyle", :street_address => "42 Gregory Way", :city => "Mungalup", :state => "WA", :postcode => "6225", :email => "Kate.S.Doyle@mailinator.com", :birthday => "1974/1/5 00:00:00"
|
21
|
-
Person.create :gender => "male", :first_name => "Harley", :middle_initial => "M", :last_name => "
|
21
|
+
Person.create :gender => "male", :first_name => "Harley", :middle_initial => "M", :last_name => "abbott", :street_address => "39 Faulkner Street", :city => "Tilbuster", :state => "NSW", :postcode => "2350", :email => "Harley.M.Abbott@trashymail.com", :birthday => "1953/10/4 00:00:00"
|
22
22
|
Person.create :gender => "male", :first_name => "Morgan", :middle_initial => "E", :last_name => "Iqbal", :street_address => "64 Carlisle Street", :city => "Dysart", :state => "VIC", :postcode => "3660", :email => "Morgan.E.Iqbal@spambob.com", :birthday => "1954/7/6 00:00:00"
|
23
23
|
Person.create :gender => "female", :first_name => "Phoebe", :middle_initial => "T", :last_name => "Wells", :street_address => "10 Mnimbah Road", :city => "Eccleston", :state => "NSW", :postcode => "2311", :email => "Phoebe.T.Wells@trashymail.com", :birthday => "1949/5/27 00:00:00"
|
24
24
|
Person.create :gender => "male", :first_name => "Finley", :middle_initial => "I", :last_name => "Martin", :street_address => "15 Thomas Lane", :city => "Epping", :state => "VIC", :postcode => "3076", :email => "Finley.I.Martin@dodgit.com", :birthday => "1983/3/12 00:00:00"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/person"
|
2
|
+
|
3
|
+
class Andrew < ActiveRecord::Base
|
4
|
+
set_table_name 'people'
|
5
|
+
|
6
|
+
define_index do
|
7
|
+
indexes first_name, last_name, street_address
|
8
|
+
end
|
9
|
+
|
10
|
+
sphinx_scope(:locked_first_name) {
|
11
|
+
{:conditions => {:first_name => 'Andrew'}}
|
12
|
+
}
|
13
|
+
sphinx_scope(:locked_last_name) {
|
14
|
+
{:conditions => {:last_name => 'Byrne'}}
|
15
|
+
}
|
16
|
+
default_sphinx_scope :locked_first_name
|
17
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
class Person < ActiveRecord::Base
|
2
2
|
define_index do
|
3
|
-
indexes first_name,
|
3
|
+
indexes first_name, :sortable => true
|
4
|
+
indexes last_name, :sortable => :insensitive
|
4
5
|
|
5
6
|
has [first_name, middle_initial, last_name], :as => :name_sort
|
6
7
|
has birthday
|
data/lib/thinking_sphinx.rb
CHANGED
@@ -363,7 +363,7 @@ module ThinkingSphinx
|
|
363
363
|
# @return [Integer] Unique record id for the purposes of Sphinx.
|
364
364
|
#
|
365
365
|
def primary_key_for_sphinx
|
366
|
-
|
366
|
+
read_attribute(self.class.primary_key_for_sphinx)
|
367
367
|
end
|
368
368
|
|
369
369
|
def sphinx_document_id
|
@@ -53,6 +53,13 @@ module ThinkingSphinx
|
|
53
53
|
|
54
54
|
ThinkingSphinx::Search.new(options)
|
55
55
|
end
|
56
|
+
|
57
|
+
define_method("#{method}_without_default".to_sym) do |*args|
|
58
|
+
options = {:classes => classes_option, :ignore_default => true}
|
59
|
+
options.merge! block.call(*args)
|
60
|
+
|
61
|
+
ThinkingSphinx::Search.new(options)
|
62
|
+
end
|
56
63
|
end
|
57
64
|
end
|
58
65
|
|
@@ -10,24 +10,50 @@ module ThinkingSphinx
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.detect(model)
|
13
|
+
adapter = adapter_for_model model
|
14
|
+
case adapter
|
15
|
+
when :mysql
|
16
|
+
ThinkingSphinx::MysqlAdapter.new model
|
17
|
+
when :postgresql
|
18
|
+
ThinkingSphinx::PostgreSQLAdapter.new model
|
19
|
+
else
|
20
|
+
raise "Invalid Database Adapter: Sphinx only supports MySQL and PostgreSQL, not #{adapter}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.adapter_for_model(model)
|
25
|
+
case ThinkingSphinx.database_adapter
|
26
|
+
when String
|
27
|
+
ThinkingSphinx.database_adapter.to_sym
|
28
|
+
when NilClass
|
29
|
+
standard_adapter_for_model model
|
30
|
+
when Proc
|
31
|
+
ThinkingSphinx.database_adapter.call model
|
32
|
+
else
|
33
|
+
ThinkingSphinx.database_adapter
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.standard_adapter_for_model(model)
|
13
38
|
case model.connection.class.name
|
14
39
|
when "ActiveRecord::ConnectionAdapters::MysqlAdapter",
|
15
40
|
"ActiveRecord::ConnectionAdapters::MysqlplusAdapter",
|
16
41
|
"ActiveRecord::ConnectionAdapters::Mysql2Adapter",
|
17
42
|
"ActiveRecord::ConnectionAdapters::NullDBAdapter"
|
18
|
-
|
43
|
+
:mysql
|
19
44
|
when "ActiveRecord::ConnectionAdapters::PostgreSQLAdapter"
|
20
|
-
|
45
|
+
:postgresql
|
21
46
|
when "ActiveRecord::ConnectionAdapters::JdbcAdapter"
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
47
|
+
case model.connection.config[:adapter]
|
48
|
+
when "jdbcmysql"
|
49
|
+
:mysql
|
50
|
+
when "jdbcpostgresql"
|
51
|
+
:postgresql
|
26
52
|
else
|
27
|
-
|
53
|
+
model.connection.config[:adapter]
|
28
54
|
end
|
29
55
|
else
|
30
|
-
|
56
|
+
model.connection.class.name
|
31
57
|
end
|
32
58
|
end
|
33
59
|
|
@@ -39,6 +65,10 @@ module ThinkingSphinx
|
|
39
65
|
/bigint/i
|
40
66
|
end
|
41
67
|
|
68
|
+
def downcase(clause)
|
69
|
+
"LOWER(#{clause})"
|
70
|
+
end
|
71
|
+
|
42
72
|
protected
|
43
73
|
|
44
74
|
def connection
|
@@ -68,7 +68,7 @@ module ThinkingSphinx
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def utc_query_pre
|
71
|
-
|
71
|
+
"SET TIME ZONE 'UTC'"
|
72
72
|
end
|
73
73
|
|
74
74
|
private
|
@@ -119,6 +119,10 @@ module ThinkingSphinx
|
|
119
119
|
DECLARE j int;
|
120
120
|
DECLARE word_array bytea;
|
121
121
|
BEGIN
|
122
|
+
IF COALESCE(word, '') = '' THEN
|
123
|
+
return 0;
|
124
|
+
END IF;
|
125
|
+
|
122
126
|
i = 0;
|
123
127
|
tmp = 4294967295;
|
124
128
|
word_array = decode(replace(word, E'\\\\', E'\\\\\\\\'), 'escape');
|
@@ -139,7 +143,7 @@ module ThinkingSphinx
|
|
139
143
|
END LOOP;
|
140
144
|
return (tmp # 4294967295);
|
141
145
|
END
|
142
|
-
$$ IMMUTABLE
|
146
|
+
$$ IMMUTABLE LANGUAGE plpgsql;
|
143
147
|
SQL
|
144
148
|
execute function, true
|
145
149
|
end
|
@@ -111,6 +111,7 @@ module ThinkingSphinx
|
|
111
111
|
clause = adapter.crc(clause) if @crc
|
112
112
|
clause = adapter.concatenate(clause, separator) if concat_ws?
|
113
113
|
clause = adapter.group_concatenate(clause, separator) if is_many?
|
114
|
+
clause = adapter.downcase(clause) if insensitive?
|
114
115
|
|
115
116
|
"#{clause} AS #{quote_column(unique_name)}"
|
116
117
|
end
|
@@ -376,5 +377,9 @@ block:
|
|
376
377
|
value
|
377
378
|
end
|
378
379
|
end
|
380
|
+
|
381
|
+
def insensitive?
|
382
|
+
@sortable == :insensitive
|
383
|
+
end
|
379
384
|
end
|
380
385
|
end
|
@@ -54,13 +54,14 @@ module ThinkingSphinx
|
|
54
54
|
sql_query_killlist sql_ranged_throttle sql_query_post_index unpack_zlib
|
55
55
|
unpack_mysqlcompress unpack_mysqlcompress_maxsize )
|
56
56
|
|
57
|
-
IndexOptions = %w( charset_table charset_type charset_dictpath
|
58
|
-
enable_star exceptions
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
57
|
+
IndexOptions = %w( blend_chars charset_table charset_type charset_dictpath
|
58
|
+
docinfo enable_star exceptions expand_keywords hitless_words
|
59
|
+
html_index_attrs html_remove_elements html_strip index_exact_words
|
60
|
+
ignore_chars inplace_docinfo_gap inplace_enable inplace_hit_gap
|
61
|
+
inplace_reloc_factor inplace_write_factor min_infix_len min_prefix_len
|
62
|
+
min_stemming_len min_word_len mlock morphology ngram_chars ngram_len
|
63
|
+
ondisk_dict overshort_step phrase_boundary phrase_boundary_step preopen
|
64
|
+
stopwords stopwords_step wordforms )
|
64
65
|
|
65
66
|
CustomOptions = %w( disable_range )
|
66
67
|
|
@@ -233,9 +234,12 @@ module ThinkingSphinx
|
|
233
234
|
@controller.indexer_binary_name = name
|
234
235
|
end
|
235
236
|
|
237
|
+
attr_accessor :timeout
|
238
|
+
|
236
239
|
def client
|
237
240
|
client = Riddle::Client.new address, port
|
238
241
|
client.max_matches = configuration.searchd.max_matches || 1000
|
242
|
+
client.timeout = timeout || 0
|
239
243
|
client
|
240
244
|
end
|
241
245
|
|
@@ -65,8 +65,10 @@ class ThinkingSphinx::Context
|
|
65
65
|
model_name.gsub!(/.*[\/\\]/, '').nil? ? next : retry
|
66
66
|
rescue NameError
|
67
67
|
next
|
68
|
-
rescue StandardError
|
69
|
-
STDERR.puts "Warning: Error loading #{file}"
|
68
|
+
rescue StandardError => err
|
69
|
+
STDERR.puts "Warning: Error loading #{file}:"
|
70
|
+
STDERR.puts err.message
|
71
|
+
STDERR.puts err.backtrace.join("\n"), ''
|
70
72
|
end
|
71
73
|
end
|
72
74
|
end
|
@@ -86,6 +86,8 @@ module ThinkingSphinx
|
|
86
86
|
@options = args.extract_options!
|
87
87
|
@args = args
|
88
88
|
|
89
|
+
add_default_scope unless options[:ignore_default]
|
90
|
+
|
89
91
|
populate if @options[:populate]
|
90
92
|
end
|
91
93
|
|
@@ -123,7 +125,7 @@ module ThinkingSphinx
|
|
123
125
|
add_scope(method, *args, &block)
|
124
126
|
return self
|
125
127
|
elsif method == :search_count
|
126
|
-
merge_search one_class.search(*args)
|
128
|
+
merge_search one_class.search(*args), self.args, options
|
127
129
|
return scoped_count
|
128
130
|
elsif method.to_s[/^each_with_.*/].nil? && !@array.respond_to?(method)
|
129
131
|
super
|
@@ -270,18 +272,43 @@ module ThinkingSphinx
|
|
270
272
|
|
271
273
|
populate
|
272
274
|
client.excerpts(
|
273
|
-
|
274
|
-
|
275
|
-
|
275
|
+
{
|
276
|
+
:docs => [string.to_s],
|
277
|
+
:words => results[:words].keys.join(' '),
|
278
|
+
:index => options[:index] || "#{model.source_of_sphinx_index.sphinx_name}_core"
|
279
|
+
}.merge(options[:excerpt_options] || {})
|
276
280
|
).first
|
277
281
|
end
|
278
282
|
|
279
283
|
def search(*args)
|
280
|
-
|
281
|
-
merge_search ThinkingSphinx::Search.new(*args)
|
284
|
+
args << args.extract_options!.merge(:ignore_default => true)
|
285
|
+
merge_search ThinkingSphinx::Search.new(*args), self.args, options
|
282
286
|
self
|
283
287
|
end
|
284
288
|
|
289
|
+
def search_for_ids(*args)
|
290
|
+
args << args.extract_options!.merge(
|
291
|
+
:ignore_default => true,
|
292
|
+
:ids_only => true
|
293
|
+
)
|
294
|
+
merge_search ThinkingSphinx::Search.new(*args), self.args, options
|
295
|
+
self
|
296
|
+
end
|
297
|
+
|
298
|
+
def facets(*args)
|
299
|
+
options = args.extract_options!
|
300
|
+
merge_search self, args, options
|
301
|
+
args << options
|
302
|
+
|
303
|
+
ThinkingSphinx::FacetSearch.new *args
|
304
|
+
end
|
305
|
+
|
306
|
+
def client
|
307
|
+
client = options[:client] || config.client
|
308
|
+
|
309
|
+
prepare client
|
310
|
+
end
|
311
|
+
|
285
312
|
def append_to(client)
|
286
313
|
prepare client
|
287
314
|
client.append_query query, indexes, comment
|
@@ -382,9 +409,16 @@ module ThinkingSphinx
|
|
382
409
|
|
383
410
|
def self.log(message, method = :debug, identifier = 'Sphinx')
|
384
411
|
return if ::ActiveRecord::Base.logger.nil?
|
385
|
-
|
386
|
-
info =
|
387
|
-
|
412
|
+
|
413
|
+
info = ''
|
414
|
+
if ::ActiveRecord::Base.colorize_logging
|
415
|
+
identifier_color, message_color = "4;32;1", "0" # 0;1 = Bold
|
416
|
+
info << " \e[#{identifier_color}m#{identifier}\e[0m "
|
417
|
+
info << "\e[#{message_color}m#{message}\e[0m"
|
418
|
+
else
|
419
|
+
info = "#{identifier} #{message}"
|
420
|
+
end
|
421
|
+
|
388
422
|
::ActiveRecord::Base.logger.send method, info
|
389
423
|
end
|
390
424
|
|
@@ -392,12 +426,6 @@ module ThinkingSphinx
|
|
392
426
|
self.class.log(*args)
|
393
427
|
end
|
394
428
|
|
395
|
-
def client
|
396
|
-
client = config.client
|
397
|
-
|
398
|
-
prepare client
|
399
|
-
end
|
400
|
-
|
401
429
|
def prepare(client)
|
402
430
|
index_options = one_class ?
|
403
431
|
one_class.sphinx_indexes.first.local_options : {}
|
@@ -489,7 +517,8 @@ module ThinkingSphinx
|
|
489
517
|
query.gsub(/("#{token}(.*?#{token})?"|(?![!-])#{token})/u) do
|
490
518
|
pre, proper, post = $`, $&, $'
|
491
519
|
# E.g. "@foo", "/2", "~3", but not as part of a token
|
492
|
-
is_operator = pre.match(%r{(\W|^)[@~/]\Z})
|
520
|
+
is_operator = pre.match(%r{(\W|^)[@~/]\Z}) ||
|
521
|
+
pre.match(%r{(\W|^)@\([^\)]*$})
|
493
522
|
# E.g. "foo bar", with quotes
|
494
523
|
is_quote = proper.starts_with?('"') && proper.ends_with?('"')
|
495
524
|
has_star = pre.ends_with?("*") || post.starts_with?("*")
|
@@ -603,24 +632,8 @@ module ThinkingSphinx
|
|
603
632
|
filters
|
604
633
|
end
|
605
634
|
|
606
|
-
def condition_filters
|
607
|
-
(options[:conditions] || {}).collect { |attrib, value|
|
608
|
-
if attributes.include?(attrib.to_sym)
|
609
|
-
puts <<-MSG
|
610
|
-
Deprecation Warning: filters on attributes should be done using the :with
|
611
|
-
option, not :conditions. For example:
|
612
|
-
:with => {:#{attrib} => #{value.inspect}}
|
613
|
-
MSG
|
614
|
-
Riddle::Client::Filter.new attrib.to_s, filter_value(value)
|
615
|
-
else
|
616
|
-
nil
|
617
|
-
end
|
618
|
-
}.compact
|
619
|
-
end
|
620
|
-
|
621
635
|
def filters
|
622
636
|
internal_filters +
|
623
|
-
condition_filters +
|
624
637
|
(options[:with] || {}).collect { |attrib, value|
|
625
638
|
Riddle::Client::Filter.new attrib.to_s, filter_value(value)
|
626
639
|
} +
|
@@ -708,6 +721,21 @@ MSG
|
|
708
721
|
end
|
709
722
|
end
|
710
723
|
|
724
|
+
def include_for_class(klass)
|
725
|
+
includes = options[:include] || klass.sphinx_index_options[:include]
|
726
|
+
|
727
|
+
case includes
|
728
|
+
when NilClass
|
729
|
+
nil
|
730
|
+
when Array
|
731
|
+
includes.select { |inc| klass.reflections[inc] }
|
732
|
+
when Symbol
|
733
|
+
klass.reflections[includes].nil? ? nil : includes
|
734
|
+
else
|
735
|
+
includes
|
736
|
+
end
|
737
|
+
end
|
738
|
+
|
711
739
|
def instances_from_class(klass, matches)
|
712
740
|
index_options = klass.sphinx_index_options
|
713
741
|
|
@@ -716,7 +744,7 @@ MSG
|
|
716
744
|
:all,
|
717
745
|
:joins => options[:joins],
|
718
746
|
:conditions => {klass.primary_key_for_sphinx.to_sym => ids},
|
719
|
-
:include => (
|
747
|
+
:include => include_for_class(klass),
|
720
748
|
:select => (options[:select] || index_options[:select]),
|
721
749
|
:order => (options[:sql_order] || index_options[:sql_order])
|
722
750
|
) : []
|
@@ -786,14 +814,16 @@ MSG
|
|
786
814
|
|
787
815
|
# Adds the default_sphinx_scope if set.
|
788
816
|
def add_default_scope
|
789
|
-
|
817
|
+
return unless one_class && one_class.has_default_sphinx_scope?
|
818
|
+
add_scope(one_class.get_default_sphinx_scope.to_sym)
|
790
819
|
end
|
791
820
|
|
792
821
|
def add_scope(method, *args, &block)
|
793
|
-
|
822
|
+
method = "#{method}_without_default".to_sym
|
823
|
+
merge_search one_class.send(method, *args, &block), self.args, options
|
794
824
|
end
|
795
825
|
|
796
|
-
def merge_search(search)
|
826
|
+
def merge_search(search, args, options)
|
797
827
|
search.args.each { |arg| args << arg }
|
798
828
|
|
799
829
|
search.options.keys.each do |key|
|