thinking-sphinx 1.4.2 → 1.4.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|