jaikoo-thinking-sphinx 0.9.10
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENCE +20 -0
- data/README +76 -0
- data/lib/thinking_sphinx.rb +112 -0
- data/lib/thinking_sphinx/active_record.rb +153 -0
- data/lib/thinking_sphinx/active_record/delta.rb +80 -0
- data/lib/thinking_sphinx/active_record/has_many_association.rb +29 -0
- data/lib/thinking_sphinx/active_record/search.rb +50 -0
- data/lib/thinking_sphinx/adapters/abstract_adapter.rb +27 -0
- data/lib/thinking_sphinx/adapters/mysql_adapter.rb +9 -0
- data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +84 -0
- data/lib/thinking_sphinx/association.rb +144 -0
- data/lib/thinking_sphinx/attribute.rb +284 -0
- data/lib/thinking_sphinx/collection.rb +105 -0
- data/lib/thinking_sphinx/configuration.rb +314 -0
- data/lib/thinking_sphinx/field.rb +206 -0
- data/lib/thinking_sphinx/index.rb +432 -0
- data/lib/thinking_sphinx/index/builder.rb +220 -0
- data/lib/thinking_sphinx/index/faux_column.rb +110 -0
- data/lib/thinking_sphinx/rails_additions.rb +68 -0
- data/lib/thinking_sphinx/search.rb +436 -0
- data/spec/unit/thinking_sphinx/active_record/delta_spec.rb +132 -0
- data/spec/unit/thinking_sphinx/active_record/has_many_association_spec.rb +53 -0
- data/spec/unit/thinking_sphinx/active_record/search_spec.rb +107 -0
- data/spec/unit/thinking_sphinx/active_record_spec.rb +295 -0
- data/spec/unit/thinking_sphinx/association_spec.rb +247 -0
- data/spec/unit/thinking_sphinx/attribute_spec.rb +360 -0
- data/spec/unit/thinking_sphinx/collection_spec.rb +71 -0
- data/spec/unit/thinking_sphinx/configuration_spec.rb +512 -0
- data/spec/unit/thinking_sphinx/field_spec.rb +224 -0
- data/spec/unit/thinking_sphinx/index/builder_spec.rb +34 -0
- data/spec/unit/thinking_sphinx/index/faux_column_spec.rb +68 -0
- data/spec/unit/thinking_sphinx/index_spec.rb +317 -0
- data/spec/unit/thinking_sphinx/search_spec.rb +203 -0
- data/spec/unit/thinking_sphinx_spec.rb +129 -0
- data/tasks/thinking_sphinx_tasks.rake +1 -0
- data/tasks/thinking_sphinx_tasks.rb +100 -0
- metadata +103 -0
@@ -0,0 +1,224 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe ThinkingSphinx::Field do
|
4
|
+
describe '#initialize' do
|
5
|
+
it 'raises if no columns are provided so that configuration errors are easier to track down' do
|
6
|
+
lambda {
|
7
|
+
ThinkingSphinx::Field.new([])
|
8
|
+
}.should raise_error(RuntimeError)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'raises if an element of the columns param is an integer - as happens when you use id instead of :id - so that configuration errors are easier to track down' do
|
12
|
+
lambda {
|
13
|
+
ThinkingSphinx::Field.new([1234])
|
14
|
+
}.should raise_error(RuntimeError)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "to_select_sql method with MySQL" do
|
19
|
+
before :each do
|
20
|
+
@index = Person.sphinx_indexes.first
|
21
|
+
@index.link!
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should concat with spaces if there are multiple columns" do
|
25
|
+
@index.fields.first.to_select_sql.should match(/CONCAT_WS\(' ', /)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should concat with spaces if a column has more than one association" do
|
29
|
+
@index.fields[1].to_select_sql.should match(/CONCAT_WS\(' ', /)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should group if any association for any column is a has_many or has_and_belongs_to_many" do
|
33
|
+
@index.fields[2].to_select_sql.should match(/GROUP_CONCAT/)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "to_select_sql method with PostgreSQL" do
|
38
|
+
before :each do
|
39
|
+
@index = Person.sphinx_indexes.first
|
40
|
+
Person.connection.class.stub_method(
|
41
|
+
:name => "ActiveRecord::ConnectionAdapters::PostgreSQLAdapter"
|
42
|
+
)
|
43
|
+
@index.link!
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should concat with spaces if there are multiple columns" do
|
47
|
+
@index.fields.first.to_select_sql.should match(/|| ' ' ||/)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should concat with spaces if a column has more than one association" do
|
51
|
+
@index.fields[1].to_select_sql.should match(/|| ' ' ||/)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should group if any association for any column is a has_many or has_and_belongs_to_many" do
|
55
|
+
@index.fields[2].to_select_sql.should match(/array_to_string\(array_accum\(/)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "to_group_sql method" do
|
60
|
+
before :each do
|
61
|
+
@field = ThinkingSphinx::Field.new([Object.stub_instance(:__stack => [])])
|
62
|
+
@field.stub_methods(:is_many? => false)
|
63
|
+
|
64
|
+
ThinkingSphinx.stub_method(:use_group_by_shortcut? => false)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should return nil if is_many?" do
|
68
|
+
@field.stub_method(:is_many? => true)
|
69
|
+
|
70
|
+
@field.to_group_sql.should be_nil
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should return nil if group_by shortcut is allowed" do
|
74
|
+
ThinkingSphinx.stub_method(:use_group_by_shortcut? => true)
|
75
|
+
|
76
|
+
@field.to_group_sql.should be_nil
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should return an array if neither is_many? or shortcut allowed" do
|
80
|
+
@field.stub_method(:column_with_prefix => 'hello')
|
81
|
+
@field.to_group_sql.should be_a_kind_of(Array)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "unique_name method" do
|
86
|
+
before :each do
|
87
|
+
@field = ThinkingSphinx::Field.new [
|
88
|
+
Object.stub_instance(:__stack => [], :__name => "col_name")
|
89
|
+
]
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should use the alias if there is one" do
|
93
|
+
@field.alias = "alias"
|
94
|
+
@field.unique_name.should == "alias"
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should use the alias if there's multiple columns" do
|
98
|
+
@field.columns << Object.stub_instance(:__stack => [], :__name => "col_name")
|
99
|
+
@field.unique_name.should be_nil
|
100
|
+
|
101
|
+
@field.alias = "alias"
|
102
|
+
@field.unique_name.should == "alias"
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should use the column name if there's no alias and just one column" do
|
106
|
+
@field.unique_name.should == "col_name"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "prefixes method" do
|
111
|
+
it "should default to false" do
|
112
|
+
@field = ThinkingSphinx::Field.new([Object.stub_instance(:__stack => [])])
|
113
|
+
@field.prefixes.should be_false
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should be true if the corresponding option is set" do
|
117
|
+
@field = ThinkingSphinx::Field.new(
|
118
|
+
[Object.stub_instance(:__stack => [])], :prefixes => true
|
119
|
+
)
|
120
|
+
@field.prefixes.should be_true
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "infixes method" do
|
125
|
+
it "should default to false" do
|
126
|
+
@field = ThinkingSphinx::Field.new([Object.stub_instance(:__stack => [])])
|
127
|
+
@field.infixes.should be_false
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should be true if the corresponding option is set" do
|
131
|
+
@field = ThinkingSphinx::Field.new(
|
132
|
+
[Object.stub_instance(:__stack => [])], :infixes => true
|
133
|
+
)
|
134
|
+
@field.infixes.should be_true
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe "quote_column_name method" do
|
139
|
+
it "should delegate the call to the model's connection" do
|
140
|
+
@field = ThinkingSphinx::Field.new [
|
141
|
+
ThinkingSphinx::Index::FauxColumn.new(:col_name)
|
142
|
+
]
|
143
|
+
@field.model = Person
|
144
|
+
Person.connection.stub_method(:quote_column_name => "quoted!")
|
145
|
+
|
146
|
+
@field.send(:quote_column, "blah").should == "quoted!"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe "column_with_prefix method" do
|
151
|
+
before :each do
|
152
|
+
@field = ThinkingSphinx::Field.new [
|
153
|
+
ThinkingSphinx::Index::FauxColumn.new(:col_name)
|
154
|
+
]
|
155
|
+
@field.columns.each { |col| @field.associations[col] = [] }
|
156
|
+
@field.model = Person
|
157
|
+
|
158
|
+
@first_join = Object.stub_instance(:aliased_table_name => "tabular")
|
159
|
+
@second_join = Object.stub_instance(:aliased_table_name => "data")
|
160
|
+
|
161
|
+
@first_assoc = ThinkingSphinx::Association.stub_instance(
|
162
|
+
:join => @first_join, :has_column? => true
|
163
|
+
)
|
164
|
+
@second_assoc = ThinkingSphinx::Association.stub_instance(
|
165
|
+
:join => @second_join, :has_column? => true
|
166
|
+
)
|
167
|
+
end
|
168
|
+
|
169
|
+
it "should return the column name if the column is a string" do
|
170
|
+
@field.columns = [ThinkingSphinx::Index::FauxColumn.new("string")]
|
171
|
+
@field.send(:column_with_prefix, @field.columns.first).should == "string"
|
172
|
+
end
|
173
|
+
|
174
|
+
it "should return the column with model's table prefix if there's no associations for the column" do
|
175
|
+
@field.send(:column_with_prefix, @field.columns.first).should == "`people`.`col_name`"
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should return the column with its join table prefix if an association exists" do
|
179
|
+
column = @field.columns.first
|
180
|
+
@field.associations[column] = [@first_assoc]
|
181
|
+
@field.send(:column_with_prefix, column).should == "`tabular`.`col_name`"
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should return multiple columns concatenated if more than one association exists" do
|
185
|
+
column = @field.columns.first
|
186
|
+
@field.associations[column] = [@first_assoc, @second_assoc]
|
187
|
+
@field.send(:column_with_prefix, column).should == "`tabular`.`col_name`, `data`.`col_name`"
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
describe "is_many? method" do
|
192
|
+
before :each do
|
193
|
+
@assoc_a = Object.stub_instance(:is_many? => true)
|
194
|
+
@assoc_b = Object.stub_instance(:is_many? => true)
|
195
|
+
@assoc_c = Object.stub_instance(:is_many? => true)
|
196
|
+
|
197
|
+
@field = ThinkingSphinx::Field.new(
|
198
|
+
[ThinkingSphinx::Index::FauxColumn.new(:col_name)]
|
199
|
+
)
|
200
|
+
@field.associations = {
|
201
|
+
:a => @assoc_a, :b => @assoc_b, :c => @assoc_c
|
202
|
+
}
|
203
|
+
end
|
204
|
+
|
205
|
+
it "should return true if all associations return true to is_many?" do
|
206
|
+
@field.send(:is_many?).should be_true
|
207
|
+
end
|
208
|
+
|
209
|
+
it "should return true if one association returns true to is_many?" do
|
210
|
+
@assoc_b.stub_method(:is_many? => false)
|
211
|
+
@assoc_c.stub_method(:is_many? => false)
|
212
|
+
|
213
|
+
@field.send(:is_many?).should be_true
|
214
|
+
end
|
215
|
+
|
216
|
+
it "should return false if all associations return false to is_many?" do
|
217
|
+
@assoc_a.stub_method(:is_many? => false)
|
218
|
+
@assoc_b.stub_method(:is_many? => false)
|
219
|
+
@assoc_c.stub_method(:is_many? => false)
|
220
|
+
|
221
|
+
@field.send(:is_many?).should be_false
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe ThinkingSphinx::Index::Builder do
|
4
|
+
before :each do
|
5
|
+
@builder = Class.new(ThinkingSphinx::Index::Builder)
|
6
|
+
@builder.setup
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "setup method" do
|
10
|
+
it "should set up the information arrays and properties hash" do
|
11
|
+
@builder.fields.should == []
|
12
|
+
@builder.attributes.should == []
|
13
|
+
@builder.conditions.should == []
|
14
|
+
@builder.groupings.should == []
|
15
|
+
@builder.properties.should == {}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "indexes method" do
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "has method" do
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "where method" do
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "set_property method" do
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe ThinkingSphinx::Index::FauxColumn do
|
4
|
+
it "should use the last argument as the name, with preceeding ones going into the stack" do
|
5
|
+
#
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should access the name through __name" do
|
9
|
+
#
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should access the stack through __stack" do
|
13
|
+
#
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should return true from is_string? if the name is a string and the stack is empty" do
|
17
|
+
#
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "coerce class method" do
|
21
|
+
before :each do
|
22
|
+
@column = ThinkingSphinx::Index::FauxColumn.stub_instance
|
23
|
+
ThinkingSphinx::Index::FauxColumn.stub_method(:new => @column)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should return a single faux column if passed a string" do
|
27
|
+
ThinkingSphinx::Index::FauxColumn.coerce("string").should == @column
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should return a single faux column if passed a symbol" do
|
31
|
+
ThinkingSphinx::Index::FauxColumn.coerce(:string).should == @column
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should return an array of faux columns if passed an array of strings" do
|
35
|
+
ThinkingSphinx::Index::FauxColumn.coerce(["one", "two"]).should == [
|
36
|
+
@column, @column
|
37
|
+
]
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should return an array of faux columns if passed an array of symbols" do
|
41
|
+
ThinkingSphinx::Index::FauxColumn.coerce([:one, :two]).should == [
|
42
|
+
@column, @column
|
43
|
+
]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "method_missing calls with no arguments" do
|
48
|
+
it "should push any further method calls into name, and the old name goes into the stack" do
|
49
|
+
#
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should return itself" do
|
53
|
+
#
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "method_missing calls with one argument" do
|
58
|
+
it "should act as if calling method missing with method, then argument" do
|
59
|
+
#
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "method_missing calls with more than one argument" do
|
64
|
+
it "should return a collection of Faux Columns sharing the same stack, but with each argument as the name" do
|
65
|
+
#
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,317 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe ThinkingSphinx::Index do
|
4
|
+
describe "to_config method" do
|
5
|
+
before :each do
|
6
|
+
@index = ThinkingSphinx::Index.new(Person)
|
7
|
+
|
8
|
+
@index.stub_methods(
|
9
|
+
:attributes => [
|
10
|
+
ThinkingSphinx::Attribute.stub_instance(:to_sphinx_clause => "attr a"),
|
11
|
+
ThinkingSphinx::Attribute.stub_instance(:to_sphinx_clause => "attr b")
|
12
|
+
],
|
13
|
+
:link! => true,
|
14
|
+
:adapter => :mysql,
|
15
|
+
:to_sql_query_pre => "sql_query_pre",
|
16
|
+
:to_sql => "SQL",
|
17
|
+
:to_sql_query_range => "sql_query_range",
|
18
|
+
:to_sql_query_info => "sql_query_info",
|
19
|
+
:delta? => false
|
20
|
+
)
|
21
|
+
|
22
|
+
@database = {
|
23
|
+
:host => "localhost",
|
24
|
+
:username => "username",
|
25
|
+
:password => "blank",
|
26
|
+
:database => "db"
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should call link!" do
|
31
|
+
@index.to_config(Person, 0, @database, 0)
|
32
|
+
|
33
|
+
@index.should have_received(:link!)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should raise an exception if the adapter isn't mysql or postgres" do
|
37
|
+
@index.stub_method(:adapter => :sqlite)
|
38
|
+
|
39
|
+
lambda { @index.to_config(Person, 0, @database, 0) }.should raise_error
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should set the core source name to {model}_{index}_core" do
|
43
|
+
@index.to_config(Person, 0, @database, 0).should match(
|
44
|
+
/source person_0_core/
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should include the database config supplied" do
|
49
|
+
conf = @index.to_config(Person, 0, @database, 0)
|
50
|
+
conf.should match(/type\s+= mysql/)
|
51
|
+
conf.should match(/sql_host\s+= localhost/)
|
52
|
+
conf.should match(/sql_user\s+= username/)
|
53
|
+
conf.should match(/sql_pass\s+= blank/)
|
54
|
+
conf.should match(/sql_db\s+= db/)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should use 'user' if 'username' doesn't exist in database configuration" do
|
58
|
+
conf = @index.to_config(Person, 0,
|
59
|
+
@database.except(:username).merge(:user => "username"),
|
60
|
+
0
|
61
|
+
)
|
62
|
+
conf.should match(/sql_user\s+= username/)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should include the database socket if set" do
|
66
|
+
conf = @index.to_config(Person, 0, @database.merge(:socket => "dbsocket"), 0)
|
67
|
+
conf.should match(/sql_sock\s+= dbsocket/)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should not include the database socket if not set" do
|
71
|
+
conf = @index.to_config(Person, 0, @database, 0)
|
72
|
+
conf.should_not match(/sql_sock/)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should include the database port if set" do
|
76
|
+
conf = @index.to_config(Person, 0, @database.merge(:port => "dbport"), 0)
|
77
|
+
conf.should match(/sql_port\s+= dbport/)
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should not include the database socket if not set" do
|
81
|
+
conf = @index.to_config(Person, 0, @database, 0)
|
82
|
+
conf.should_not match(/sql_port/)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should have a pre query 'SET NAMES utf8' if using mysql and utf8 charset" do
|
86
|
+
@index.options[:charset_type] = "utf-8"
|
87
|
+
@index.to_config(Person, 0, @database, 0).should match(
|
88
|
+
/sql_query_pre\s+= SET NAMES utf8/
|
89
|
+
)
|
90
|
+
|
91
|
+
@index.stub_method(:delta? => true)
|
92
|
+
@index.to_config(Person, 0, @database, 0).should match(
|
93
|
+
/source person_0_delta.+sql_query_pre\s+= SET NAMES utf8/m
|
94
|
+
)
|
95
|
+
|
96
|
+
@index.options[:charset_type] = "non-utf-8"
|
97
|
+
@index.stub_method(:delta? => false)
|
98
|
+
@index.to_config(Person, 0, @database, 0).should_not match(
|
99
|
+
/SET NAMES utf8/
|
100
|
+
)
|
101
|
+
|
102
|
+
@index.options[:charset_type] = "utf-8"
|
103
|
+
@index.stub_method(:adapter => :postgres)
|
104
|
+
@index.to_config(Person, 0, @database, 0).should_not match(
|
105
|
+
/SET NAMES utf8/
|
106
|
+
)
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should use the pre query from the index" do
|
110
|
+
@index.to_config(Person, 0, @database, 0).should match(
|
111
|
+
/sql_query_pre\s+= sql_query_pre/
|
112
|
+
)
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should not set group_concat_max_len if not specified" do
|
116
|
+
@index.to_config(Person, 0, @database, 0).should_not match(
|
117
|
+
/group_concat_max_len/
|
118
|
+
)
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should set group_concat_max_len if specified" do
|
122
|
+
@index.options.merge! :group_concat_max_len => 2056
|
123
|
+
@index.to_config(Person, 0, @database, 0).should match(
|
124
|
+
/sql_query_pre\s+= SET SESSION group_concat_max_len = 2056/
|
125
|
+
)
|
126
|
+
|
127
|
+
@index.stub_method(:delta? => true)
|
128
|
+
@index.to_config(Person, 0, @database, 0).should match(
|
129
|
+
/source person_0_delta.+sql_query_pre\s+= SET SESSION group_concat_max_len = 2056/m
|
130
|
+
)
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should use the main query from the index" do
|
134
|
+
@index.to_config(Person, 0, @database, 0).should match(
|
135
|
+
/sql_query\s+= SQL/
|
136
|
+
)
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should use the range query from the index" do
|
140
|
+
@index.to_config(Person, 0, @database, 0).should match(
|
141
|
+
/sql_query_range\s+= sql_query_range/
|
142
|
+
)
|
143
|
+
end
|
144
|
+
|
145
|
+
it "should use the info query from the index" do
|
146
|
+
@index.to_config(Person, 0, @database, 0).should match(
|
147
|
+
/sql_query_info\s+= sql_query_info/
|
148
|
+
)
|
149
|
+
end
|
150
|
+
|
151
|
+
it "should include the attribute sources" do
|
152
|
+
@index.to_config(Person, 0, @database, 0).should match(
|
153
|
+
/attr a\n\s+attr b/
|
154
|
+
)
|
155
|
+
end
|
156
|
+
|
157
|
+
it "should add a delta index with name {model}_{index}_delta if requested" do
|
158
|
+
@index.stub_method(:delta? => true)
|
159
|
+
|
160
|
+
@index.to_config(Person, 0, @database, 0).should match(
|
161
|
+
/source person_0_delta/
|
162
|
+
)
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should not add a delta index unless requested" do
|
166
|
+
@index.to_config(Person, 0, @database, 0).should_not match(
|
167
|
+
/source person_0_delta/
|
168
|
+
)
|
169
|
+
end
|
170
|
+
|
171
|
+
it "should have the delta index inherit from the core index" do
|
172
|
+
@index.stub_method(:delta? => true)
|
173
|
+
|
174
|
+
@index.to_config(Person, 0, @database, 0).should match(
|
175
|
+
/source person_0_delta : person_0_core/
|
176
|
+
)
|
177
|
+
end
|
178
|
+
|
179
|
+
it "should redefine the main query for the delta index" do
|
180
|
+
@index.stub_method(:delta? => true)
|
181
|
+
|
182
|
+
@index.to_config(Person, 0, @database, 0).should match(
|
183
|
+
/source person_0_delta.+sql_query\s+= SQL/m
|
184
|
+
)
|
185
|
+
end
|
186
|
+
|
187
|
+
it "should redefine the range query for the delta index" do
|
188
|
+
@index.stub_method(:delta? => true)
|
189
|
+
|
190
|
+
@index.to_config(Person, 0, @database, 0).should match(
|
191
|
+
/source person_0_delta.+sql_query_range\s+= sql_query_range/m
|
192
|
+
)
|
193
|
+
end
|
194
|
+
|
195
|
+
it "should redefine the pre query for the delta index" do
|
196
|
+
@index.stub_method(:delta? => true)
|
197
|
+
|
198
|
+
@index.to_config(Person, 0, @database, 0).should match(
|
199
|
+
/source person_0_delta.+sql_query_pre\s+=\s*\n/m
|
200
|
+
)
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
describe "to_sql method" do
|
205
|
+
it "should include explicit groupings if requested" do
|
206
|
+
@index = ThinkingSphinx::Index.new(Person)
|
207
|
+
|
208
|
+
@index.groupings << "custom_sql"
|
209
|
+
@index.to_sql.should match(/GROUP BY.+custom_sql/)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
describe "to_sql_query_range method" do
|
214
|
+
before :each do
|
215
|
+
@index = ThinkingSphinx::Index.new(Person)
|
216
|
+
end
|
217
|
+
|
218
|
+
it "should add COALESCE around MIN and MAX calls if using PostgreSQL" do
|
219
|
+
@index.stub_method(:adapter => :postgres)
|
220
|
+
|
221
|
+
@index.to_sql_query_range.should match(/COALESCE\(MIN.+COALESCE\(MAX/)
|
222
|
+
end
|
223
|
+
|
224
|
+
it "shouldn't add COALESCE if using MySQL" do
|
225
|
+
@index.to_sql_query_range.should_not match(/COALESCE/)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
describe "prefix_fields method" do
|
230
|
+
before :each do
|
231
|
+
@index = ThinkingSphinx::Index.new(Person)
|
232
|
+
|
233
|
+
@field_a = ThinkingSphinx::Field.stub_instance(:prefixes => true)
|
234
|
+
@field_b = ThinkingSphinx::Field.stub_instance(:prefixes => false)
|
235
|
+
@field_c = ThinkingSphinx::Field.stub_instance(:prefixes => true)
|
236
|
+
|
237
|
+
@index.fields = [@field_a, @field_b, @field_c]
|
238
|
+
end
|
239
|
+
|
240
|
+
it "should return fields that are flagged as prefixed" do
|
241
|
+
@index.prefix_fields.should include(@field_a)
|
242
|
+
@index.prefix_fields.should include(@field_c)
|
243
|
+
end
|
244
|
+
|
245
|
+
it "should not return fields that aren't flagged as prefixed" do
|
246
|
+
@index.prefix_fields.should_not include(@field_b)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
describe "infix_fields method" do
|
251
|
+
before :each do
|
252
|
+
@index = ThinkingSphinx::Index.new(Person)
|
253
|
+
|
254
|
+
@field_a = ThinkingSphinx::Field.stub_instance(:infixes => true)
|
255
|
+
@field_b = ThinkingSphinx::Field.stub_instance(:infixes => false)
|
256
|
+
@field_c = ThinkingSphinx::Field.stub_instance(:infixes => true)
|
257
|
+
|
258
|
+
@index.fields = [@field_a, @field_b, @field_c]
|
259
|
+
end
|
260
|
+
|
261
|
+
it "should return fields that are flagged as infixed" do
|
262
|
+
@index.infix_fields.should include(@field_a)
|
263
|
+
@index.infix_fields.should include(@field_c)
|
264
|
+
end
|
265
|
+
|
266
|
+
it "should not return fields that aren't flagged as infixed" do
|
267
|
+
@index.infix_fields.should_not include(@field_b)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
describe "empty? method" do
|
272
|
+
before :each do
|
273
|
+
@index = ThinkingSphinx::Index.new(Contact)
|
274
|
+
config = ThinkingSphinx::Configuration.instance
|
275
|
+
|
276
|
+
`mkdir -p #{config.searchd_file_path}`
|
277
|
+
@file_path = "#{config.searchd_file_path}/#{@index.name}_core.spa"
|
278
|
+
end
|
279
|
+
|
280
|
+
after :each do
|
281
|
+
FileUtils.rm(@file_path, :force => true)
|
282
|
+
end
|
283
|
+
|
284
|
+
it "should return true if the core index files are empty" do
|
285
|
+
`touch #{@file_path}`
|
286
|
+
@index.should be_empty
|
287
|
+
end
|
288
|
+
|
289
|
+
it "should return true if the core index files don't exist" do
|
290
|
+
@index.should be_empty
|
291
|
+
end
|
292
|
+
|
293
|
+
it "should return false if the core index files aren't empty" do
|
294
|
+
`echo 'a' > #{@file_path}`
|
295
|
+
@index.should_not be_empty
|
296
|
+
end
|
297
|
+
|
298
|
+
it "should check the delta files if specified" do
|
299
|
+
delta_path = @file_path.gsub(/_core.spa$/, '_delta.spa')
|
300
|
+
|
301
|
+
@index.should be_empty(:delta)
|
302
|
+
`echo 'a' > #{delta_path}`
|
303
|
+
@index.should_not be_empty(:delta)
|
304
|
+
|
305
|
+
FileUtils.rm(delta_path)
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
describe "initialize_from_builder method" do
|
310
|
+
it "should copy groupings across from the builder to the index" do
|
311
|
+
@index = ThinkingSphinx::Index.new(Person) do
|
312
|
+
group_by "custom_grouping"
|
313
|
+
end
|
314
|
+
@index.groupings.should include("custom_grouping")
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|