thinking-sphinx 1.4.2 → 1.4.3
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 +2 -0
- data/VERSION +1 -1
- data/lib/thinking_sphinx/active_record.rb +2 -2
- data/lib/thinking_sphinx/active_record/has_many_association.rb +1 -16
- data/lib/thinking_sphinx/active_record/has_many_association_with_scopes.rb +21 -0
- data/lib/thinking_sphinx/active_record/scopes.rb +11 -0
- data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +3 -1
- data/lib/thinking_sphinx/search.rb +49 -32
- data/spec/thinking_sphinx/search_spec.rb +30 -0
- metadata +5 -4
data/README.textile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.4.
|
1
|
+
1.4.3
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'thinking_sphinx/active_record/attribute_updates'
|
2
2
|
require 'thinking_sphinx/active_record/delta'
|
3
3
|
require 'thinking_sphinx/active_record/has_many_association'
|
4
|
+
require 'thinking_sphinx/active_record/has_many_association_with_scopes'
|
4
5
|
require 'thinking_sphinx/active_record/scopes'
|
5
6
|
|
6
7
|
module ThinkingSphinx
|
@@ -45,8 +46,7 @@ module ThinkingSphinx
|
|
45
46
|
end
|
46
47
|
|
47
48
|
def sphinx_database_adapter
|
48
|
-
|
49
|
-
ThinkingSphinx::AbstractAdapter.detect(self)
|
49
|
+
ThinkingSphinx::AbstractAdapter.detect(self)
|
50
50
|
end
|
51
51
|
|
52
52
|
def sphinx_name
|
@@ -9,17 +9,7 @@ module ThinkingSphinx
|
|
9
9
|
args << options
|
10
10
|
@reflection.klass.search(*args)
|
11
11
|
end
|
12
|
-
|
13
|
-
def method_missing(method, *args, &block)
|
14
|
-
if responds_to_scope(method)
|
15
|
-
@reflection.klass.
|
16
|
-
search(:with => default_filter).
|
17
|
-
send(method, *args, &block)
|
18
|
-
else
|
19
|
-
super
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
12
|
+
|
23
13
|
private
|
24
14
|
|
25
15
|
def attribute_for_foreign_key
|
@@ -41,11 +31,6 @@ module ThinkingSphinx
|
|
41
31
|
def default_filter
|
42
32
|
{attribute_for_foreign_key.unique_name => @owner.id}
|
43
33
|
end
|
44
|
-
|
45
|
-
def responds_to_scope(scope)
|
46
|
-
@reflection.klass.respond_to?(:sphinx_scopes) &&
|
47
|
-
@reflection.klass.sphinx_scopes.include?(scope)
|
48
|
-
end
|
49
34
|
end
|
50
35
|
end
|
51
36
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module ThinkingSphinx
|
2
|
+
module ActiveRecord
|
3
|
+
module HasManyAssociationWithScopes
|
4
|
+
def method_missing(method, *args, &block)
|
5
|
+
if responds_to_scope(method)
|
6
|
+
@reflection.klass.
|
7
|
+
search(:with => default_filter).
|
8
|
+
send(method, *args, &block)
|
9
|
+
else
|
10
|
+
super
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
def responds_to_scope(scope)
|
16
|
+
@reflection.klass.respond_to?(:sphinx_scopes) &&
|
17
|
+
@reflection.klass.sphinx_scopes.include?(scope)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -17,6 +17,7 @@ module ThinkingSphinx
|
|
17
17
|
# The scope is automatically applied when the search method is called. It
|
18
18
|
# will only be applied if it is an existing sphinx_scope.
|
19
19
|
def default_sphinx_scope(sphinx_scope_name)
|
20
|
+
add_sphinx_scopes_support_to_has_many_associations
|
20
21
|
@default_sphinx_scope = sphinx_scope_name
|
21
22
|
end
|
22
23
|
|
@@ -43,6 +44,8 @@ module ThinkingSphinx
|
|
43
44
|
# @articles = Article.latest_first.search 'pancakes'
|
44
45
|
#
|
45
46
|
def sphinx_scope(method, &block)
|
47
|
+
add_sphinx_scopes_support_to_has_many_associations
|
48
|
+
|
46
49
|
@sphinx_scopes ||= []
|
47
50
|
@sphinx_scopes << method
|
48
51
|
|
@@ -76,6 +79,14 @@ module ThinkingSphinx
|
|
76
79
|
|
77
80
|
sphinx_scopes.clear
|
78
81
|
end
|
82
|
+
|
83
|
+
def add_sphinx_scopes_support_to_has_many_associations
|
84
|
+
scope_mixin = ::ThinkingSphinx::ActiveRecord::HasManyAssociationWithScopes
|
85
|
+
|
86
|
+
::ActiveRecord::Associations::HasManyAssociation.send(:include, scope_mixin)
|
87
|
+
::ActiveRecord::Associations::HasManyThroughAssociation.send(:include, scope_mixin)
|
88
|
+
end
|
89
|
+
|
79
90
|
end
|
80
91
|
end
|
81
92
|
end
|
@@ -117,6 +117,7 @@ module ThinkingSphinx
|
|
117
117
|
DECLARE tmp bigint;
|
118
118
|
DECLARE i int;
|
119
119
|
DECLARE j int;
|
120
|
+
DECLARE byte_length int;
|
120
121
|
DECLARE word_array bytea;
|
121
122
|
BEGIN
|
122
123
|
IF COALESCE(word, '') = '' THEN
|
@@ -125,6 +126,7 @@ module ThinkingSphinx
|
|
125
126
|
|
126
127
|
i = 0;
|
127
128
|
tmp = 4294967295;
|
129
|
+
byte_length = bit_length(word) / 8;
|
128
130
|
word_array = decode(replace(word, E'\\\\', E'\\\\\\\\'), 'escape');
|
129
131
|
LOOP
|
130
132
|
tmp = (tmp # get_byte(word_array, i))::bigint;
|
@@ -137,7 +139,7 @@ module ThinkingSphinx
|
|
137
139
|
EXIT;
|
138
140
|
END IF;
|
139
141
|
END LOOP;
|
140
|
-
IF i >=
|
142
|
+
IF i >= byte_length THEN
|
141
143
|
EXIT;
|
142
144
|
END IF;
|
143
145
|
END LOOP;
|
@@ -29,32 +29,32 @@ module ThinkingSphinx
|
|
29
29
|
|
30
30
|
# Deprecated. Use ThinkingSphinx.search
|
31
31
|
def self.search(*args)
|
32
|
-
|
33
|
-
ThinkingSphinx.search
|
32
|
+
warn 'ThinkingSphinx::Search.search is deprecated. Please use ThinkingSphinx.search instead.'
|
33
|
+
ThinkingSphinx.search(*args)
|
34
34
|
end
|
35
35
|
|
36
36
|
# Deprecated. Use ThinkingSphinx.search_for_ids
|
37
37
|
def self.search_for_ids(*args)
|
38
|
-
|
39
|
-
ThinkingSphinx.search_for_ids
|
38
|
+
warn 'ThinkingSphinx::Search.search_for_ids is deprecated. Please use ThinkingSphinx.search_for_ids instead.'
|
39
|
+
ThinkingSphinx.search_for_ids(*args)
|
40
40
|
end
|
41
41
|
|
42
42
|
# Deprecated. Use ThinkingSphinx.search_for_ids
|
43
43
|
def self.search_for_id(*args)
|
44
|
-
|
45
|
-
ThinkingSphinx.search_for_id
|
44
|
+
warn 'ThinkingSphinx::Search.search_for_id is deprecated. Please use ThinkingSphinx.search_for_id instead.'
|
45
|
+
ThinkingSphinx.search_for_id(*args)
|
46
46
|
end
|
47
47
|
|
48
48
|
# Deprecated. Use ThinkingSphinx.count
|
49
49
|
def self.count(*args)
|
50
|
-
|
51
|
-
ThinkingSphinx.count
|
50
|
+
warn 'ThinkingSphinx::Search.count is deprecated. Please use ThinkingSphinx.count instead.'
|
51
|
+
ThinkingSphinx.count(*args)
|
52
52
|
end
|
53
53
|
|
54
54
|
# Deprecated. Use ThinkingSphinx.facets
|
55
55
|
def self.facets(*args)
|
56
|
-
|
57
|
-
ThinkingSphinx.facets
|
56
|
+
warn 'ThinkingSphinx::Search.facets is deprecated. Please use ThinkingSphinx.facets instead.'
|
57
|
+
ThinkingSphinx.facets(*args)
|
58
58
|
end
|
59
59
|
|
60
60
|
def self.bundle_searches(enum = nil)
|
@@ -334,7 +334,7 @@ module ThinkingSphinx
|
|
334
334
|
merge_search self, args, options
|
335
335
|
args << options
|
336
336
|
|
337
|
-
ThinkingSphinx::FacetSearch.new
|
337
|
+
ThinkingSphinx::FacetSearch.new(*args)
|
338
338
|
end
|
339
339
|
|
340
340
|
def client
|
@@ -354,16 +354,7 @@ module ThinkingSphinx
|
|
354
354
|
@populated = true
|
355
355
|
@results = results
|
356
356
|
|
357
|
-
|
358
|
-
replace @results[:matches].collect { |match|
|
359
|
-
match[:attributes]["sphinx_internal_id"]
|
360
|
-
}
|
361
|
-
else
|
362
|
-
replace instances_from_matches
|
363
|
-
add_excerpter
|
364
|
-
add_sphinx_attributes
|
365
|
-
add_matching_fields if client.rank_mode == :fieldmask
|
366
|
-
end
|
357
|
+
compose_results
|
367
358
|
end
|
368
359
|
|
369
360
|
private
|
@@ -395,18 +386,44 @@ module ThinkingSphinx
|
|
395
386
|
raise ThinkingSphinx::ConnectionError,
|
396
387
|
'Connection to Sphinx Daemon (searchd) failed.'
|
397
388
|
end
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
389
|
+
|
390
|
+
compose_results
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
def compose_results
|
395
|
+
if options[:ids_only]
|
396
|
+
compose_ids_results
|
397
|
+
elsif options[:only]
|
398
|
+
compose_only_results
|
399
|
+
else
|
400
|
+
replace instances_from_matches
|
401
|
+
add_excerpter
|
402
|
+
add_sphinx_attributes
|
403
|
+
add_matching_fields if client.rank_mode == :fieldmask
|
404
|
+
end
|
405
|
+
end
|
406
|
+
|
407
|
+
def compose_ids_results
|
408
|
+
replace @results[:matches].collect { |match|
|
409
|
+
match[:attributes]['sphinx_internal_id']
|
410
|
+
}
|
411
|
+
end
|
412
|
+
|
413
|
+
def compose_only_results
|
414
|
+
replace @results[:matches].collect { |match|
|
415
|
+
case only = options[:only]
|
416
|
+
when String, Symbol
|
417
|
+
match[:attributes][only.to_s]
|
418
|
+
when Array
|
419
|
+
only.inject({}) do |hash, attribute|
|
420
|
+
hash[attribute.to_sym] = match[:attributes][attribute.to_s]
|
421
|
+
hash
|
422
|
+
end
|
403
423
|
else
|
404
|
-
|
405
|
-
add_excerpter
|
406
|
-
add_sphinx_attributes
|
407
|
-
add_matching_fields if client.rank_mode == :fieldmask
|
424
|
+
raise "Unexpected object for :only argument. String or Array is expected, #{only.class} was received."
|
408
425
|
end
|
409
|
-
|
426
|
+
}
|
410
427
|
end
|
411
428
|
|
412
429
|
def add_excerpter
|
@@ -903,7 +920,7 @@ module ThinkingSphinx
|
|
903
920
|
end
|
904
921
|
|
905
922
|
def scoped_count
|
906
|
-
return self.total_entries if
|
923
|
+
return self.total_entries if(@options[:ids_only] || @options[:only])
|
907
924
|
|
908
925
|
@options[:ids_only] = true
|
909
926
|
results_count = self.total_entries
|
@@ -867,6 +867,36 @@ describe ThinkingSphinx::Search do
|
|
867
867
|
end
|
868
868
|
end
|
869
869
|
|
870
|
+
describe ':only option' do
|
871
|
+
it "returns the requested attribute as an array" do
|
872
|
+
ThinkingSphinx::Search.new(:only => :class_crc).first.
|
873
|
+
should == Alpha.to_crc32
|
874
|
+
end
|
875
|
+
|
876
|
+
it "returns multiple attributes as hashes with values" do
|
877
|
+
ThinkingSphinx::Search.new(
|
878
|
+
:only => [:class_crc, :sphinx_internal_id]
|
879
|
+
).first.should == {
|
880
|
+
:class_crc => Alpha.to_crc32,
|
881
|
+
:sphinx_internal_id => @alpha_a.id
|
882
|
+
}
|
883
|
+
end
|
884
|
+
|
885
|
+
it "handles strings for a single attribute name" do
|
886
|
+
ThinkingSphinx::Search.new(:only => 'class_crc').first.
|
887
|
+
should == Alpha.to_crc32
|
888
|
+
end
|
889
|
+
|
890
|
+
it "handles strings for multiple attribute names" do
|
891
|
+
ThinkingSphinx::Search.new(
|
892
|
+
:only => ['class_crc', 'sphinx_internal_id']
|
893
|
+
).first.should == {
|
894
|
+
:class_crc => Alpha.to_crc32,
|
895
|
+
:sphinx_internal_id => @alpha_a.id
|
896
|
+
}
|
897
|
+
end
|
898
|
+
end
|
899
|
+
|
870
900
|
context 'result objects' do
|
871
901
|
describe '#excerpts' do
|
872
902
|
before :each do
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thinking-sphinx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 1
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 4
|
9
|
-
-
|
10
|
-
version: 1.4.
|
9
|
+
- 3
|
10
|
+
version: 1.4.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Pat Allan
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-01-
|
18
|
+
date: 2011-01-29 00:00:00 +11:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -303,6 +303,7 @@ files:
|
|
303
303
|
- lib/thinking_sphinx/active_record/attribute_updates.rb
|
304
304
|
- lib/thinking_sphinx/active_record/delta.rb
|
305
305
|
- lib/thinking_sphinx/active_record/has_many_association.rb
|
306
|
+
- lib/thinking_sphinx/active_record/has_many_association_with_scopes.rb
|
306
307
|
- lib/thinking_sphinx/active_record/scopes.rb
|
307
308
|
- lib/thinking_sphinx/adapters/abstract_adapter.rb
|
308
309
|
- lib/thinking_sphinx/adapters/mysql_adapter.rb
|