thinking-sphinx 3.0.3 → 3.0.4
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.
- checksums.yaml +7 -0
- data/.gitignore +2 -1
- data/HISTORY +25 -0
- data/lib/thinking_sphinx.rb +1 -0
- data/lib/thinking_sphinx/active_record/association_proxy.rb +13 -55
- data/lib/thinking_sphinx/active_record/association_proxy/attribute_finder.rb +47 -0
- data/lib/thinking_sphinx/active_record/base.rb +16 -15
- data/lib/thinking_sphinx/active_record/callbacks/delete_callbacks.rb +1 -12
- data/lib/thinking_sphinx/active_record/database_adapters.rb +41 -42
- data/lib/thinking_sphinx/active_record/polymorpher.rb +7 -2
- data/lib/thinking_sphinx/active_record/property_query.rb +23 -19
- data/lib/thinking_sphinx/active_record/sql_builder.rb +108 -129
- data/lib/thinking_sphinx/active_record/sql_builder/clause_builder.rb +28 -0
- data/lib/thinking_sphinx/active_record/sql_builder/query.rb +43 -0
- data/lib/thinking_sphinx/active_record/sql_builder/statement.rb +110 -0
- data/lib/thinking_sphinx/active_record/sql_source.rb +143 -138
- data/lib/thinking_sphinx/capistrano.rb +11 -8
- data/lib/thinking_sphinx/configuration.rb +57 -35
- data/lib/thinking_sphinx/connection.rb +15 -6
- data/lib/thinking_sphinx/core.rb +1 -0
- data/lib/thinking_sphinx/core/index.rb +18 -10
- data/lib/thinking_sphinx/core/settings.rb +9 -0
- data/lib/thinking_sphinx/deletion.rb +48 -0
- data/lib/thinking_sphinx/errors.rb +7 -0
- data/lib/thinking_sphinx/excerpter.rb +1 -0
- data/lib/thinking_sphinx/facet_search.rb +42 -19
- data/lib/thinking_sphinx/masks/scopes_mask.rb +7 -0
- data/lib/thinking_sphinx/middlewares.rb +27 -33
- data/lib/thinking_sphinx/middlewares/active_record_translator.rb +18 -18
- data/lib/thinking_sphinx/middlewares/geographer.rb +49 -16
- data/lib/thinking_sphinx/middlewares/sphinxql.rb +128 -58
- data/lib/thinking_sphinx/panes/excerpts_pane.rb +7 -3
- data/lib/thinking_sphinx/rake_interface.rb +10 -0
- data/lib/thinking_sphinx/real_time.rb +7 -1
- data/lib/thinking_sphinx/real_time/attribute.rb +4 -0
- data/lib/thinking_sphinx/real_time/callbacks/real_time_callbacks.rb +14 -10
- data/lib/thinking_sphinx/real_time/index.rb +20 -12
- data/lib/thinking_sphinx/search/glaze.rb +5 -0
- data/lib/thinking_sphinx/search/query.rb +4 -8
- data/lib/thinking_sphinx/tasks.rb +8 -0
- data/spec/acceptance/excerpts_spec.rb +22 -0
- data/spec/acceptance/remove_deleted_records_spec.rb +10 -0
- data/spec/acceptance/searching_across_models_spec.rb +10 -0
- data/spec/acceptance/searching_with_filters_spec.rb +15 -0
- data/spec/acceptance/specifying_sql_spec.rb +3 -3
- data/spec/acceptance/sphinx_scopes_spec.rb +11 -0
- data/spec/internal/app/indices/product_index.rb +2 -0
- data/spec/internal/app/models/categorisation.rb +6 -0
- data/spec/internal/app/models/category.rb +3 -0
- data/spec/internal/app/models/product.rb +4 -1
- data/spec/internal/db/schema.rb +10 -0
- data/spec/thinking_sphinx/active_record/base_spec.rb +33 -0
- data/spec/thinking_sphinx/active_record/callbacks/delete_callbacks_spec.rb +4 -35
- data/spec/thinking_sphinx/active_record/sql_builder_spec.rb +5 -10
- data/spec/thinking_sphinx/active_record/sql_source_spec.rb +4 -3
- data/spec/thinking_sphinx/configuration_spec.rb +26 -6
- data/spec/thinking_sphinx/connection_spec.rb +4 -1
- data/spec/thinking_sphinx/deletion_spec.rb +76 -0
- data/spec/thinking_sphinx/facet_search_spec.rb +54 -5
- data/spec/thinking_sphinx/panes/excerpts_pane_spec.rb +4 -6
- data/spec/thinking_sphinx/rake_interface_spec.rb +35 -0
- data/spec/thinking_sphinx/real_time/callbacks/real_time_callbacks_spec.rb +68 -28
- data/spec/thinking_sphinx/search/glaze_spec.rb +19 -0
- data/spec/thinking_sphinx/search/query_spec.rb +39 -2
- data/thinking-sphinx.gemspec +2 -2
- metadata +31 -45
@@ -4,13 +4,16 @@ describe ThinkingSphinx::Connection do
|
|
4
4
|
describe '.take' do
|
5
5
|
let(:pool) { double 'pool' }
|
6
6
|
let(:connection) { double 'connection' }
|
7
|
-
let(:error) {
|
7
|
+
let(:error) { ThinkingSphinx::QueryExecutionError.new 'failed' }
|
8
8
|
let(:translated_error) { ThinkingSphinx::SphinxError.new }
|
9
9
|
|
10
10
|
before :each do
|
11
11
|
ThinkingSphinx::Connection.stub :pool => pool
|
12
12
|
ThinkingSphinx::SphinxError.stub :new_from_mysql => translated_error
|
13
13
|
pool.stub(:take).and_yield(connection)
|
14
|
+
|
15
|
+
error.statement = 'SELECT * FROM article_core'
|
16
|
+
translated_error.statement = 'SELECT * FROM article_core'
|
14
17
|
end
|
15
18
|
|
16
19
|
it "yields a connection from the pool" do
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ThinkingSphinx::Deletion do
|
4
|
+
describe '.perform' do
|
5
|
+
let(:connection) { double('connection', :execute => nil) }
|
6
|
+
let(:index) { double('index', :name => 'foo_core',
|
7
|
+
:document_id_for_key => 14, :type => 'plain') }
|
8
|
+
let(:instance) { double('instance', :id => 7) }
|
9
|
+
let(:pool) { double 'pool' }
|
10
|
+
|
11
|
+
before :each do
|
12
|
+
ThinkingSphinx::Connection.stub :pool => pool
|
13
|
+
Riddle::Query.stub :update => 'UPDATE STATEMENT'
|
14
|
+
|
15
|
+
pool.stub(:take).and_yield(connection)
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'index is SQL-backed' do
|
19
|
+
it "updates the deleted flag to false" do
|
20
|
+
connection.should_receive(:execute).with('UPDATE STATEMENT')
|
21
|
+
|
22
|
+
ThinkingSphinx::Deletion.perform index, instance
|
23
|
+
end
|
24
|
+
|
25
|
+
it "builds the update query for the given index" do
|
26
|
+
Riddle::Query.should_receive(:update).
|
27
|
+
with('foo_core', anything, anything).and_return('')
|
28
|
+
|
29
|
+
ThinkingSphinx::Deletion.perform index, instance
|
30
|
+
end
|
31
|
+
|
32
|
+
it "builds the update query for the sphinx document id" do
|
33
|
+
Riddle::Query.should_receive(:update).
|
34
|
+
with(anything, 14, anything).and_return('')
|
35
|
+
|
36
|
+
ThinkingSphinx::Deletion.perform index, instance
|
37
|
+
end
|
38
|
+
|
39
|
+
it "builds the update query for setting sphinx_deleted to true" do
|
40
|
+
Riddle::Query.should_receive(:update).
|
41
|
+
with(anything, anything, :sphinx_deleted => true).and_return('')
|
42
|
+
|
43
|
+
ThinkingSphinx::Deletion.perform index, instance
|
44
|
+
end
|
45
|
+
|
46
|
+
it "doesn't care about Sphinx errors" do
|
47
|
+
connection.stub(:execute).and_raise(Mysql2::Error.new(''))
|
48
|
+
|
49
|
+
lambda {
|
50
|
+
ThinkingSphinx::Deletion.perform index, instance
|
51
|
+
}.should_not raise_error
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "index is real-time" do
|
56
|
+
before :each do
|
57
|
+
index.stub :type => 'rt'
|
58
|
+
end
|
59
|
+
|
60
|
+
it "deletes the record to false" do
|
61
|
+
connection.should_receive(:execute).
|
62
|
+
with('DELETE FROM foo_core WHERE id = 14')
|
63
|
+
|
64
|
+
ThinkingSphinx::Deletion.perform index, instance
|
65
|
+
end
|
66
|
+
|
67
|
+
it "doesn't care about Sphinx errors" do
|
68
|
+
connection.stub(:execute).and_raise(Mysql2::Error.new(''))
|
69
|
+
|
70
|
+
lambda {
|
71
|
+
ThinkingSphinx::Deletion.perform index, instance
|
72
|
+
}.should_not raise_error
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -7,15 +7,21 @@ describe ThinkingSphinx::FacetSearch do
|
|
7
7
|
let(:facet_search) { ThinkingSphinx::FacetSearch.new '', {} }
|
8
8
|
let(:batch) { double('batch', :searches => [], :populate => true) }
|
9
9
|
let(:index_set) { [] }
|
10
|
-
let(:index) { double('index', :facets => [
|
10
|
+
let(:index) { double('index', :facets => [property_a, property_b],
|
11
11
|
:name => 'foo_core') }
|
12
|
-
let(:
|
13
|
-
:multi? => false)}
|
12
|
+
let(:property_a) { double('property', :name => 'price_bracket',
|
13
|
+
:multi? => false) }
|
14
|
+
let(:property_b) { double('property', :name => 'category_id',
|
15
|
+
:multi? => false) }
|
16
|
+
let(:configuration) { double 'configuration', :settings => {} }
|
14
17
|
|
15
18
|
before :each do
|
16
19
|
stub_const 'ThinkingSphinx::IndexSet', double(:new => index_set)
|
17
20
|
stub_const 'ThinkingSphinx::BatchedSearch', double(:new => batch)
|
18
21
|
stub_const 'ThinkingSphinx::Search', DumbSearch
|
22
|
+
stub_const 'ThinkingSphinx::Middlewares::RAW_ONLY', double
|
23
|
+
stub_const 'ThinkingSphinx::Configuration',
|
24
|
+
double(:instance => configuration)
|
19
25
|
|
20
26
|
index_set << index << double('index', :facets => [], :name => 'bar_core')
|
21
27
|
end
|
@@ -26,6 +32,7 @@ describe ThinkingSphinx::FacetSearch do
|
|
26
32
|
'sphinx_internal_class' => 'Foo',
|
27
33
|
'price_bracket' => 3,
|
28
34
|
'tag_ids' => '1,2',
|
35
|
+
'category_id' => 11,
|
29
36
|
'@count' => 5,
|
30
37
|
'@groupby' => 2
|
31
38
|
}]
|
@@ -55,8 +62,18 @@ describe ThinkingSphinx::FacetSearch do
|
|
55
62
|
}.should_not be_nil
|
56
63
|
end
|
57
64
|
|
65
|
+
it "limits facets to the specified set" do
|
66
|
+
facet_search.options[:facets] = [:category_id]
|
67
|
+
|
68
|
+
facet_search.populate
|
69
|
+
|
70
|
+
batch.searches.collect { |search|
|
71
|
+
search.options[:group_by]
|
72
|
+
}.should == ['category_id']
|
73
|
+
end
|
74
|
+
|
58
75
|
it "aliases the class facet from sphinx_internal_class" do
|
59
|
-
|
76
|
+
property_a.stub :name => 'sphinx_internal_class'
|
60
77
|
|
61
78
|
facet_search.populate
|
62
79
|
|
@@ -64,11 +81,43 @@ describe ThinkingSphinx::FacetSearch do
|
|
64
81
|
end
|
65
82
|
|
66
83
|
it "uses the @groupby value for MVAs" do
|
67
|
-
|
84
|
+
property_a.stub :name => 'tag_ids', :multi? => true
|
68
85
|
|
69
86
|
facet_search.populate
|
70
87
|
|
71
88
|
facet_search[:tag_ids].should == {2 => 5}
|
72
89
|
end
|
90
|
+
|
91
|
+
[:max_matches, :limit].each do |setting|
|
92
|
+
it "sets #{setting} in each search" do
|
93
|
+
facet_search.populate
|
94
|
+
|
95
|
+
batch.searches.each { |search|
|
96
|
+
search.options[setting].should == 1000
|
97
|
+
}
|
98
|
+
end
|
99
|
+
|
100
|
+
it "respects configured max_matches values for #{setting}" do
|
101
|
+
configuration.settings['max_matches'] = 1234
|
102
|
+
|
103
|
+
facet_search.populate
|
104
|
+
|
105
|
+
batch.searches.each { |search|
|
106
|
+
search.options[setting].should == 1234
|
107
|
+
}
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
[:limit, :per_page].each do |setting|
|
112
|
+
it "respects #{setting} option if set" do
|
113
|
+
facet_search = ThinkingSphinx::FacetSearch.new '', {setting => 42}
|
114
|
+
|
115
|
+
facet_search.populate
|
116
|
+
|
117
|
+
batch.searches.each { |search|
|
118
|
+
search.options[setting].should == 42
|
119
|
+
}
|
120
|
+
end
|
121
|
+
end
|
73
122
|
end
|
74
123
|
end
|
@@ -7,11 +7,10 @@ require 'thinking_sphinx/panes/excerpts_pane'
|
|
7
7
|
describe ThinkingSphinx::Panes::ExcerptsPane do
|
8
8
|
let(:pane) {
|
9
9
|
ThinkingSphinx::Panes::ExcerptsPane.new context, object, raw }
|
10
|
-
let(:context) { {:indices => [double(:name => 'foo_core')]
|
11
|
-
:meta => {}} }
|
10
|
+
let(:context) { {:indices => [double(:name => 'foo_core')]} }
|
12
11
|
let(:object) { double('object') }
|
13
12
|
let(:raw) { {} }
|
14
|
-
let(:search) { double('search', :options => {}) }
|
13
|
+
let(:search) { double('search', :query => 'foo', :options => {}) }
|
15
14
|
|
16
15
|
before :each do
|
17
16
|
context.stub :search => search
|
@@ -30,10 +29,9 @@ describe ThinkingSphinx::Panes::ExcerptsPane do
|
|
30
29
|
pane.excerpts.should == excerpts
|
31
30
|
end
|
32
31
|
|
33
|
-
it "creates an excerpter with the first index and
|
32
|
+
it "creates an excerpter with the first index and the query and conditions values" do
|
34
33
|
context[:indices] = [double(:name => 'alpha'), double(:name => 'beta')]
|
35
|
-
context[:
|
36
|
-
context[:meta]['keyword[1]'] = 'bar'
|
34
|
+
context.search.options[:conditions] = {:baz => 'bar'}
|
37
35
|
|
38
36
|
ThinkingSphinx::Excerpter.should_receive(:new).
|
39
37
|
with('alpha', 'foo bar', anything).and_return(excerpter)
|
@@ -9,6 +9,32 @@ describe ThinkingSphinx::RakeInterface do
|
|
9
9
|
interface.stub(:puts => nil)
|
10
10
|
end
|
11
11
|
|
12
|
+
describe '#clear' do
|
13
|
+
let(:controller) { double 'controller' }
|
14
|
+
|
15
|
+
before :each do
|
16
|
+
configuration.stub(
|
17
|
+
:indices_location => '/path/to/indices',
|
18
|
+
:searchd => double(:binlog_path => '/path/to/binlog')
|
19
|
+
)
|
20
|
+
|
21
|
+
FileUtils.stub :rm_r => true
|
22
|
+
File.stub :exists? => true
|
23
|
+
end
|
24
|
+
|
25
|
+
it "removes the directory for the index files" do
|
26
|
+
FileUtils.should_receive(:rm_r).with('/path/to/indices')
|
27
|
+
|
28
|
+
interface.clear
|
29
|
+
end
|
30
|
+
|
31
|
+
it "removes the directory for the binlog files" do
|
32
|
+
FileUtils.should_receive(:rm_r).with('/path/to/binlog')
|
33
|
+
|
34
|
+
interface.clear
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
12
38
|
describe '#configure' do
|
13
39
|
let(:controller) { double('controller') }
|
14
40
|
|
@@ -86,6 +112,15 @@ describe ThinkingSphinx::RakeInterface do
|
|
86
112
|
|
87
113
|
before :each do
|
88
114
|
controller.stub(:running?).and_return(false, true)
|
115
|
+
configuration.stub :indices_location => 'my/index/files'
|
116
|
+
|
117
|
+
FileUtils.stub :mkdir_p => true
|
118
|
+
end
|
119
|
+
|
120
|
+
it "creates the index files directory" do
|
121
|
+
FileUtils.should_receive(:mkdir_p).with('my/index/files')
|
122
|
+
|
123
|
+
interface.start
|
89
124
|
end
|
90
125
|
|
91
126
|
it "starts the daemon" do
|
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe ThinkingSphinx::RealTime::Callbacks::RealTimeCallbacks do
|
4
4
|
let(:callbacks) {
|
5
|
-
ThinkingSphinx::RealTime::Callbacks::RealTimeCallbacks.new
|
5
|
+
ThinkingSphinx::RealTime::Callbacks::RealTimeCallbacks.new :article
|
6
6
|
}
|
7
7
|
let(:instance) { double('instance', :id => 12) }
|
8
8
|
let(:config) { double('config', :indices_for_references => [index]) }
|
@@ -16,30 +16,6 @@ describe ThinkingSphinx::RealTime::Callbacks::RealTimeCallbacks do
|
|
16
16
|
ThinkingSphinx::Connection.stub_chain(:pool, :take).and_yield connection
|
17
17
|
end
|
18
18
|
|
19
|
-
describe '.after_save' do
|
20
|
-
let(:callbacks) { double('callbacks', :after_save => nil) }
|
21
|
-
|
22
|
-
before :each do
|
23
|
-
ThinkingSphinx::RealTime::Callbacks::RealTimeCallbacks.
|
24
|
-
stub :new => callbacks
|
25
|
-
end
|
26
|
-
|
27
|
-
it "builds an object from the instance" do
|
28
|
-
ThinkingSphinx::RealTime::Callbacks::RealTimeCallbacks.
|
29
|
-
should_receive(:new).with(instance).and_return(callbacks)
|
30
|
-
|
31
|
-
ThinkingSphinx::RealTime::Callbacks::RealTimeCallbacks.
|
32
|
-
after_save(instance)
|
33
|
-
end
|
34
|
-
|
35
|
-
it "invokes after_save on the object" do
|
36
|
-
callbacks.should_receive(:after_save)
|
37
|
-
|
38
|
-
ThinkingSphinx::RealTime::Callbacks::RealTimeCallbacks.
|
39
|
-
after_save(instance)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
19
|
describe '#after_save' do
|
44
20
|
let(:insert) { double('insert', :to_sql => 'REPLACE INTO my_index') }
|
45
21
|
let(:time) { 1.day.ago }
|
@@ -59,19 +35,83 @@ describe ThinkingSphinx::RealTime::Callbacks::RealTimeCallbacks do
|
|
59
35
|
with('my_index', ['id', 'name', 'created_at'], [123, 'Foo', time]).
|
60
36
|
and_return(insert)
|
61
37
|
|
62
|
-
callbacks.after_save
|
38
|
+
callbacks.after_save instance
|
63
39
|
end
|
64
40
|
|
65
41
|
it "switches the insert to a replace statement" do
|
66
42
|
insert.should_receive(:replace!).and_return(insert)
|
67
43
|
|
68
|
-
callbacks.after_save
|
44
|
+
callbacks.after_save instance
|
69
45
|
end
|
70
46
|
|
71
47
|
it "sends the insert through to the server" do
|
72
48
|
connection.should_receive(:execute).with('REPLACE INTO my_index')
|
73
49
|
|
74
|
-
callbacks.after_save
|
50
|
+
callbacks.after_save instance
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'with a given path' do
|
54
|
+
let(:callbacks) {
|
55
|
+
ThinkingSphinx::RealTime::Callbacks::RealTimeCallbacks.new(
|
56
|
+
:article, [:user]
|
57
|
+
)
|
58
|
+
}
|
59
|
+
let(:instance) { double('instance', :id => 12, :user => user) }
|
60
|
+
let(:user) { double('user', :id => 13) }
|
61
|
+
|
62
|
+
it "creates an insert statement with all fields and attributes" do
|
63
|
+
Riddle::Query::Insert.should_receive(:new).
|
64
|
+
with('my_index', ['id', 'name', 'created_at'], [123, 'Foo', time]).
|
65
|
+
and_return(insert)
|
66
|
+
|
67
|
+
callbacks.after_save instance
|
68
|
+
end
|
69
|
+
|
70
|
+
it "gets the document id for the user object" do
|
71
|
+
index.should_receive(:document_id_for_key).with(13).and_return(123)
|
72
|
+
|
73
|
+
callbacks.after_save instance
|
74
|
+
end
|
75
|
+
|
76
|
+
it "translates values for the user object" do
|
77
|
+
field.should_receive(:translate).with(user).and_return('Foo')
|
78
|
+
|
79
|
+
callbacks.after_save instance
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'with a path returning multiple objects' do
|
84
|
+
let(:callbacks) {
|
85
|
+
ThinkingSphinx::RealTime::Callbacks::RealTimeCallbacks.new(
|
86
|
+
:article, [:readers]
|
87
|
+
)
|
88
|
+
}
|
89
|
+
let(:instance) { double('instance', :id => 12,
|
90
|
+
:readers => [user_a, user_b]) }
|
91
|
+
let(:user_a) { double('user', :id => 13) }
|
92
|
+
let(:user_b) { double('user', :id => 14) }
|
93
|
+
|
94
|
+
it "creates insert statements with all fields and attributes" do
|
95
|
+
Riddle::Query::Insert.should_receive(:new).twice.
|
96
|
+
with('my_index', ['id', 'name', 'created_at'], [123, 'Foo', time]).
|
97
|
+
and_return(insert)
|
98
|
+
|
99
|
+
callbacks.after_save instance
|
100
|
+
end
|
101
|
+
|
102
|
+
it "gets the document id for each reader" do
|
103
|
+
index.should_receive(:document_id_for_key).with(13).and_return(123)
|
104
|
+
index.should_receive(:document_id_for_key).with(14).and_return(123)
|
105
|
+
|
106
|
+
callbacks.after_save instance
|
107
|
+
end
|
108
|
+
|
109
|
+
it "translates values for each reader" do
|
110
|
+
field.should_receive(:translate).with(user_a).and_return('Foo')
|
111
|
+
field.should_receive(:translate).with(user_b).and_return('Foo')
|
112
|
+
|
113
|
+
callbacks.after_save instance
|
114
|
+
end
|
75
115
|
end
|
76
116
|
end
|
77
117
|
end
|
@@ -50,6 +50,25 @@ describe ThinkingSphinx::Search::Glaze do
|
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
53
|
+
describe '#respond_to?' do
|
54
|
+
it "responds to underlying object methods" do
|
55
|
+
object.stub :foo => true
|
56
|
+
|
57
|
+
glaze.respond_to?(:foo).should be_true
|
58
|
+
end
|
59
|
+
|
60
|
+
it "responds to underlying pane methods" do
|
61
|
+
pane = double('Pane Class', :new => double('pane', :bar => true))
|
62
|
+
glaze = ThinkingSphinx::Search::Glaze.new context, object, raw, [pane]
|
63
|
+
|
64
|
+
glaze.respond_to?(:bar).should be_true
|
65
|
+
end
|
66
|
+
|
67
|
+
it "does not to respond to methods that don't exist" do
|
68
|
+
glaze.respond_to?(:something).should be_false
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
53
72
|
describe '#unglazed' do
|
54
73
|
it "returns the original object" do
|
55
74
|
glaze.unglazed.should == object
|
@@ -39,9 +39,34 @@ describe ThinkingSphinx::Search::Query do
|
|
39
39
|
|
40
40
|
it "does not star the sphinx_internal_class field keyword" do
|
41
41
|
query = ThinkingSphinx::Search::Query.new '',
|
42
|
-
{:
|
42
|
+
{:sphinx_internal_class_name => 'article'}, true
|
43
43
|
|
44
|
-
query.to_s.should == '@
|
44
|
+
query.to_s.should == '@sphinx_internal_class_name article'
|
45
|
+
end
|
46
|
+
|
47
|
+
it "treats escapes as word characters" do
|
48
|
+
query = ThinkingSphinx::Search::Query.new '', {:title => 'sauce\\@pan'},
|
49
|
+
true
|
50
|
+
|
51
|
+
query.to_s.should == '@title *sauce\\@pan*'
|
52
|
+
end
|
53
|
+
|
54
|
+
it "does not star manually provided field tags" do
|
55
|
+
query = ThinkingSphinx::Search::Query.new "@title pan", {}, true
|
56
|
+
|
57
|
+
query.to_s.should == "@title *pan*"
|
58
|
+
end
|
59
|
+
|
60
|
+
it "does not star manually provided arrays of field tags" do
|
61
|
+
query = ThinkingSphinx::Search::Query.new "@(title, body) pan", {}, true
|
62
|
+
|
63
|
+
query.to_s.should == "@(title, body) *pan*"
|
64
|
+
end
|
65
|
+
|
66
|
+
it "stars keywords that begin with an escaped @" do
|
67
|
+
query = ThinkingSphinx::Search::Query.new "\\@pan", {}, true
|
68
|
+
|
69
|
+
query.to_s.should == "*\\@pan*"
|
45
70
|
end
|
46
71
|
|
47
72
|
it "handles null values by removing them from the conditions hash" do
|
@@ -56,6 +81,18 @@ describe ThinkingSphinx::Search::Query do
|
|
56
81
|
query.to_s.should == ''
|
57
82
|
end
|
58
83
|
|
84
|
+
it "handles nil queries" do
|
85
|
+
query = ThinkingSphinx::Search::Query.new nil, {}
|
86
|
+
|
87
|
+
query.to_s.should == ''
|
88
|
+
end
|
89
|
+
|
90
|
+
it "handles nil queries when starring" do
|
91
|
+
query = ThinkingSphinx::Search::Query.new nil, {}, true
|
92
|
+
|
93
|
+
query.to_s.should == ''
|
94
|
+
end
|
95
|
+
|
59
96
|
it "allows mixing of blank and non-blank conditions" do
|
60
97
|
query = ThinkingSphinx::Search::Query.new 'tasty', :title => 'pancakes',
|
61
98
|
:ingredients => nil
|