thinking-sphinx 1.5.0 → 2.0.0.rc1
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 +15 -48
- data/VERSION +1 -0
- data/features/attribute_transformation.feature +7 -7
- data/features/attribute_updates.feature +16 -18
- data/features/deleting_instances.feature +13 -16
- data/features/excerpts.feature +0 -8
- data/features/facets.feature +19 -25
- data/features/handling_edits.feature +20 -25
- data/features/searching_across_models.feature +1 -1
- data/features/searching_by_index.feature +5 -6
- data/features/searching_by_model.feature +29 -29
- data/features/sphinx_scopes.feature +0 -26
- data/features/step_definitions/common_steps.rb +6 -18
- data/features/step_definitions/scope_steps.rb +0 -4
- data/features/step_definitions/search_steps.rb +4 -9
- data/features/support/env.rb +10 -3
- data/features/thinking_sphinx/db/fixtures/alphas.rb +10 -8
- data/features/thinking_sphinx/db/fixtures/cats.rb +1 -1
- data/features/thinking_sphinx/db/fixtures/dogs.rb +1 -1
- data/features/thinking_sphinx/db/fixtures/foxes.rb +1 -1
- data/features/thinking_sphinx/db/fixtures/people.rb +1 -1
- data/features/thinking_sphinx/db/fixtures/posts.rb +1 -5
- data/features/thinking_sphinx/db/migrations/create_posts.rb +0 -1
- data/features/thinking_sphinx/models/alpha.rb +0 -1
- data/features/thinking_sphinx/models/beta.rb +0 -5
- data/features/thinking_sphinx/models/developer.rb +1 -6
- data/features/thinking_sphinx/models/music.rb +1 -3
- data/features/thinking_sphinx/models/person.rb +1 -2
- data/features/thinking_sphinx/models/post.rb +0 -1
- data/lib/cucumber/thinking_sphinx/external_world.rb +4 -8
- data/lib/cucumber/thinking_sphinx/internal_world.rb +27 -36
- data/lib/thinking_sphinx.rb +60 -132
- data/lib/thinking_sphinx/active_record.rb +98 -124
- data/lib/thinking_sphinx/active_record/attribute_updates.rb +13 -17
- data/lib/thinking_sphinx/active_record/delta.rb +15 -21
- data/lib/thinking_sphinx/active_record/has_many_association.rb +23 -16
- data/lib/thinking_sphinx/active_record/scopes.rb +0 -18
- data/lib/thinking_sphinx/adapters/abstract_adapter.rb +15 -63
- data/lib/thinking_sphinx/adapters/mysql_adapter.rb +0 -4
- data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +24 -65
- data/lib/thinking_sphinx/association.rb +11 -36
- data/lib/thinking_sphinx/attribute.rb +85 -92
- data/lib/thinking_sphinx/auto_version.rb +3 -21
- data/lib/thinking_sphinx/class_facet.rb +3 -8
- data/lib/thinking_sphinx/configuration.rb +58 -114
- data/lib/thinking_sphinx/context.rb +20 -22
- data/lib/thinking_sphinx/core/array.rb +13 -0
- data/lib/thinking_sphinx/deltas.rb +0 -2
- data/lib/thinking_sphinx/deltas/default_delta.rb +22 -18
- data/lib/thinking_sphinx/deploy/capistrano.rb +31 -30
- data/lib/thinking_sphinx/excerpter.rb +1 -2
- data/lib/thinking_sphinx/facet.rb +35 -45
- data/lib/thinking_sphinx/facet_search.rb +24 -58
- data/lib/thinking_sphinx/field.rb +0 -18
- data/lib/thinking_sphinx/index.rb +36 -38
- data/lib/thinking_sphinx/index/builder.rb +59 -74
- data/lib/thinking_sphinx/property.rb +45 -66
- data/lib/thinking_sphinx/railtie.rb +35 -0
- data/lib/thinking_sphinx/search.rb +250 -506
- data/lib/thinking_sphinx/source.rb +31 -50
- data/lib/thinking_sphinx/source/internal_properties.rb +3 -8
- data/lib/thinking_sphinx/source/sql.rb +31 -71
- data/lib/thinking_sphinx/tasks.rb +27 -48
- data/spec/thinking_sphinx/active_record/delta_spec.rb +41 -36
- data/spec/thinking_sphinx/active_record/has_many_association_spec.rb +0 -96
- data/spec/thinking_sphinx/active_record/scopes_spec.rb +29 -29
- data/spec/thinking_sphinx/active_record_spec.rb +169 -140
- data/spec/thinking_sphinx/association_spec.rb +2 -20
- data/spec/thinking_sphinx/attribute_spec.rb +97 -101
- data/spec/thinking_sphinx/auto_version_spec.rb +11 -75
- data/spec/thinking_sphinx/configuration_spec.rb +62 -63
- data/spec/thinking_sphinx/context_spec.rb +66 -66
- data/spec/thinking_sphinx/facet_search_spec.rb +99 -99
- data/spec/thinking_sphinx/facet_spec.rb +4 -30
- data/spec/thinking_sphinx/field_spec.rb +3 -17
- data/spec/thinking_sphinx/index/builder_spec.rb +132 -169
- data/spec/thinking_sphinx/index_spec.rb +39 -45
- data/spec/thinking_sphinx/search_methods_spec.rb +33 -37
- data/spec/thinking_sphinx/search_spec.rb +269 -491
- data/spec/thinking_sphinx/source_spec.rb +48 -62
- data/spec/thinking_sphinx_spec.rb +49 -49
- data/tasks/distribution.rb +46 -0
- data/tasks/testing.rb +74 -0
- metadata +123 -199
- data/features/field_sorting.feature +0 -18
- data/features/thinking_sphinx/db/.gitignore +0 -1
- data/features/thinking_sphinx/db/fixtures/post_keywords.txt +0 -1
- data/features/thinking_sphinx/models/andrew.rb +0 -17
- data/lib/thinking-sphinx.rb +0 -1
- data/lib/thinking_sphinx/active_record/has_many_association_with_scopes.rb +0 -21
- data/lib/thinking_sphinx/bundled_search.rb +0 -40
- data/lib/thinking_sphinx/connection.rb +0 -71
- data/lib/thinking_sphinx/deltas/delete_job.rb +0 -16
- data/lib/thinking_sphinx/deltas/index_job.rb +0 -17
- data/lib/thinking_sphinx/rails_additions.rb +0 -181
- data/spec/fixtures/data.sql +0 -32
- data/spec/fixtures/database.yml.default +0 -3
- data/spec/fixtures/models.rb +0 -161
- data/spec/fixtures/structure.sql +0 -146
- data/spec/spec_helper.rb +0 -54
- data/spec/sphinx_helper.rb +0 -67
- data/spec/thinking_sphinx/adapters/abstract_adapter_spec.rb +0 -163
- data/spec/thinking_sphinx/connection_spec.rb +0 -77
- data/spec/thinking_sphinx/rails_additions_spec.rb +0 -203
|
@@ -1,7 +1,6 @@
|
|
|
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'
|
|
5
4
|
require 'thinking_sphinx/active_record/scopes'
|
|
6
5
|
|
|
7
6
|
module ThinkingSphinx
|
|
@@ -13,98 +12,63 @@ module ThinkingSphinx
|
|
|
13
12
|
def self.included(base)
|
|
14
13
|
base.class_eval do
|
|
15
14
|
class_inheritable_array :sphinx_indexes, :sphinx_facets
|
|
16
|
-
|
|
15
|
+
|
|
17
16
|
extend ThinkingSphinx::ActiveRecord::ClassMethods
|
|
18
|
-
|
|
17
|
+
|
|
19
18
|
class << self
|
|
20
|
-
attr_accessor :sphinx_index_blocks
|
|
21
|
-
|
|
19
|
+
attr_accessor :sphinx_index_blocks
|
|
20
|
+
|
|
22
21
|
def set_sphinx_primary_key(attribute)
|
|
23
22
|
@sphinx_primary_key_attribute = attribute
|
|
24
23
|
end
|
|
25
|
-
|
|
24
|
+
|
|
26
25
|
def primary_key_for_sphinx
|
|
27
|
-
@
|
|
28
|
-
if custom_primary_key_for_sphinx?
|
|
29
|
-
@sphinx_primary_key_attribute ||
|
|
30
|
-
superclass.primary_key_for_sphinx
|
|
31
|
-
else
|
|
32
|
-
primary_key || 'id'
|
|
33
|
-
end
|
|
34
|
-
end
|
|
26
|
+
@sphinx_primary_key_attribute || primary_key
|
|
35
27
|
end
|
|
36
|
-
|
|
37
|
-
def custom_primary_key_for_sphinx?
|
|
38
|
-
(
|
|
39
|
-
superclass.respond_to?(:custom_primary_key_for_sphinx?) &&
|
|
40
|
-
superclass.custom_primary_key_for_sphinx?
|
|
41
|
-
) || !@sphinx_primary_key_attribute.nil?
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def clear_primary_key_for_sphinx
|
|
45
|
-
@primary_key_for_sphinx = nil
|
|
46
|
-
end
|
|
47
|
-
|
|
28
|
+
|
|
48
29
|
def sphinx_index_options
|
|
49
30
|
sphinx_indexes.last.options
|
|
50
31
|
end
|
|
51
|
-
|
|
52
|
-
def set_sphinx_types(types)
|
|
53
|
-
@sphinx_types = types
|
|
54
|
-
end
|
|
55
|
-
|
|
32
|
+
|
|
56
33
|
# Generate a unique CRC value for the model's name, to use to
|
|
57
34
|
# determine which Sphinx documents belong to which AR records.
|
|
58
|
-
#
|
|
35
|
+
#
|
|
59
36
|
# Really only written for internal use - but hey, if it's useful to
|
|
60
37
|
# you in some other way, awesome.
|
|
61
|
-
#
|
|
38
|
+
#
|
|
62
39
|
def to_crc32
|
|
63
40
|
self.name.to_crc32
|
|
64
41
|
end
|
|
65
|
-
|
|
42
|
+
|
|
66
43
|
def to_crc32s
|
|
67
44
|
(subclasses << self).collect { |klass| klass.to_crc32 }
|
|
68
45
|
end
|
|
69
|
-
|
|
46
|
+
|
|
70
47
|
def sphinx_database_adapter
|
|
71
|
-
|
|
48
|
+
@sphinx_database_adapter ||=
|
|
49
|
+
ThinkingSphinx::AbstractAdapter.detect(self)
|
|
72
50
|
end
|
|
73
|
-
|
|
51
|
+
|
|
74
52
|
def sphinx_name
|
|
75
53
|
self.name.underscore.tr(':/\\', '_')
|
|
76
54
|
end
|
|
77
|
-
|
|
78
|
-
#
|
|
79
|
-
# The above method to_crc32s is dependant on the subclasses being loaded consistently
|
|
80
|
-
# After a reset_subclasses is called (during a Dispatcher.cleanup_application in development)
|
|
81
|
-
# Our subclasses will be lost but our context will not reload them for us.
|
|
82
|
-
#
|
|
83
|
-
# We reset the context which causes the subclasses to be reloaded next time the context is called.
|
|
84
|
-
#
|
|
85
|
-
def reset_subclasses_with_thinking_sphinx
|
|
86
|
-
reset_subclasses_without_thinking_sphinx
|
|
87
|
-
ThinkingSphinx.reset_context!
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
alias_method_chain :reset_subclasses, :thinking_sphinx
|
|
91
|
-
|
|
55
|
+
|
|
92
56
|
private
|
|
93
|
-
|
|
57
|
+
|
|
94
58
|
def defined_indexes?
|
|
95
59
|
@defined_indexes
|
|
96
60
|
end
|
|
97
|
-
|
|
61
|
+
|
|
98
62
|
def defined_indexes=(value)
|
|
99
63
|
@defined_indexes = value
|
|
100
64
|
end
|
|
101
|
-
|
|
65
|
+
|
|
102
66
|
def sphinx_delta?
|
|
103
67
|
self.sphinx_indexes.any? { |index| index.delta? }
|
|
104
68
|
end
|
|
105
69
|
end
|
|
106
70
|
end
|
|
107
|
-
|
|
71
|
+
|
|
108
72
|
::ActiveRecord::Associations::HasManyAssociation.send(
|
|
109
73
|
:include, ThinkingSphinx::ActiveRecord::HasManyAssociation
|
|
110
74
|
)
|
|
@@ -112,7 +76,7 @@ module ThinkingSphinx
|
|
|
112
76
|
:include, ThinkingSphinx::ActiveRecord::HasManyAssociation
|
|
113
77
|
)
|
|
114
78
|
end
|
|
115
|
-
|
|
79
|
+
|
|
116
80
|
module ClassMethods
|
|
117
81
|
# Allows creation of indexes for Sphinx. If you don't do this, there
|
|
118
82
|
# isn't much point trying to search (or using this plugin at all,
|
|
@@ -146,7 +110,7 @@ module ThinkingSphinx
|
|
|
146
110
|
#
|
|
147
111
|
# define_index do
|
|
148
112
|
# # fields ...
|
|
149
|
-
#
|
|
113
|
+
#
|
|
150
114
|
# has created_at, updated_at
|
|
151
115
|
# end
|
|
152
116
|
#
|
|
@@ -156,58 +120,58 @@ module ThinkingSphinx
|
|
|
156
120
|
# define_index do
|
|
157
121
|
# # fields ...
|
|
158
122
|
# # attributes ...
|
|
159
|
-
#
|
|
123
|
+
#
|
|
160
124
|
# set_property :delta => true
|
|
161
125
|
# end
|
|
162
126
|
#
|
|
163
127
|
# Check out the more detailed documentation for each of these methods
|
|
164
128
|
# at ThinkingSphinx::Index::Builder.
|
|
165
|
-
#
|
|
129
|
+
#
|
|
166
130
|
def define_index(name = nil, &block)
|
|
167
131
|
self.sphinx_index_blocks ||= []
|
|
168
132
|
self.sphinx_indexes ||= []
|
|
169
133
|
self.sphinx_facets ||= []
|
|
170
|
-
|
|
134
|
+
|
|
171
135
|
ThinkingSphinx.context.add_indexed_model self
|
|
172
|
-
|
|
136
|
+
|
|
173
137
|
if sphinx_index_blocks.empty?
|
|
174
138
|
before_validation :define_indexes
|
|
175
139
|
before_destroy :define_indexes
|
|
176
140
|
end
|
|
177
|
-
|
|
141
|
+
|
|
178
142
|
self.sphinx_index_blocks << lambda {
|
|
179
143
|
add_sphinx_index name, &block
|
|
180
144
|
}
|
|
181
|
-
|
|
145
|
+
|
|
182
146
|
include ThinkingSphinx::ActiveRecord::Scopes
|
|
183
147
|
include ThinkingSphinx::SearchMethods
|
|
184
148
|
end
|
|
185
|
-
|
|
149
|
+
|
|
186
150
|
def define_indexes
|
|
187
151
|
superclass.define_indexes unless superclass == ::ActiveRecord::Base
|
|
188
|
-
|
|
152
|
+
|
|
189
153
|
return if sphinx_index_blocks.nil? ||
|
|
190
154
|
defined_indexes? ||
|
|
191
155
|
!ThinkingSphinx.define_indexes?
|
|
192
|
-
|
|
156
|
+
|
|
193
157
|
sphinx_index_blocks.each do |block|
|
|
194
158
|
block.call
|
|
195
159
|
end
|
|
196
|
-
|
|
160
|
+
|
|
197
161
|
self.defined_indexes = true
|
|
198
|
-
|
|
162
|
+
|
|
199
163
|
# We want to make sure that if the database doesn't exist, then Thinking
|
|
200
164
|
# Sphinx doesn't mind when running non-TS tasks (like db:create, db:drop
|
|
201
165
|
# and db:migrate). It's a bit hacky, but I can't think of a better way.
|
|
202
166
|
rescue StandardError => err
|
|
203
167
|
case err.class.name
|
|
204
|
-
when "Mysql::Error", "
|
|
168
|
+
when "Mysql::Error", "Java::JavaSql::SQLException", "ActiveRecord::StatementInvalid"
|
|
205
169
|
return
|
|
206
170
|
else
|
|
207
171
|
raise err
|
|
208
172
|
end
|
|
209
173
|
end
|
|
210
|
-
|
|
174
|
+
|
|
211
175
|
def add_sphinx_index(name, &block)
|
|
212
176
|
index = ThinkingSphinx::Index::Builder.generate self, name, &block
|
|
213
177
|
|
|
@@ -216,50 +180,50 @@ module ThinkingSphinx
|
|
|
216
180
|
insert_sphinx_index index
|
|
217
181
|
end
|
|
218
182
|
end
|
|
219
|
-
|
|
183
|
+
|
|
220
184
|
def insert_sphinx_index(index)
|
|
221
185
|
self.sphinx_indexes << index
|
|
222
186
|
subclasses.each { |klass| klass.insert_sphinx_index(index) }
|
|
223
187
|
end
|
|
224
|
-
|
|
188
|
+
|
|
225
189
|
def has_sphinx_indexes?
|
|
226
|
-
sphinx_indexes &&
|
|
190
|
+
sphinx_indexes &&
|
|
227
191
|
sphinx_index_blocks &&
|
|
228
192
|
(sphinx_indexes.length > 0 || sphinx_index_blocks.length > 0)
|
|
229
193
|
end
|
|
230
|
-
|
|
194
|
+
|
|
231
195
|
def indexed_by_sphinx?
|
|
232
196
|
sphinx_indexes && sphinx_indexes.length > 0
|
|
233
197
|
end
|
|
234
|
-
|
|
198
|
+
|
|
235
199
|
def delta_indexed_by_sphinx?
|
|
236
200
|
sphinx_indexes && sphinx_indexes.any? { |index| index.delta? }
|
|
237
201
|
end
|
|
238
|
-
|
|
202
|
+
|
|
239
203
|
def sphinx_index_names
|
|
240
204
|
define_indexes
|
|
241
205
|
sphinx_indexes.collect(&:all_names).flatten
|
|
242
206
|
end
|
|
243
|
-
|
|
207
|
+
|
|
244
208
|
def core_index_names
|
|
245
209
|
define_indexes
|
|
246
210
|
sphinx_indexes.collect(&:core_name)
|
|
247
211
|
end
|
|
248
|
-
|
|
212
|
+
|
|
249
213
|
def delta_index_names
|
|
250
214
|
define_indexes
|
|
251
215
|
sphinx_indexes.select(&:delta?).collect(&:delta_name)
|
|
252
216
|
end
|
|
253
|
-
|
|
217
|
+
|
|
254
218
|
def to_riddle
|
|
255
219
|
define_indexes
|
|
256
220
|
sphinx_database_adapter.setup
|
|
257
|
-
|
|
221
|
+
|
|
258
222
|
local_sphinx_indexes.collect { |index|
|
|
259
223
|
index.to_riddle(sphinx_offset)
|
|
260
224
|
}.flatten
|
|
261
225
|
end
|
|
262
|
-
|
|
226
|
+
|
|
263
227
|
def source_of_sphinx_index
|
|
264
228
|
define_indexes
|
|
265
229
|
possible_models = self.sphinx_indexes.collect { |index| index.model }
|
|
@@ -272,31 +236,29 @@ module ThinkingSphinx
|
|
|
272
236
|
|
|
273
237
|
return parent
|
|
274
238
|
end
|
|
275
|
-
|
|
239
|
+
|
|
276
240
|
def delete_in_index(index, document_id)
|
|
277
|
-
return unless ThinkingSphinx.sphinx_running?
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
ThinkingSphinx::SphinxError, Errno::ETIMEDOUT, Timeout::Error
|
|
284
|
-
# Not the end of the world if Sphinx isn't running.
|
|
241
|
+
return unless ThinkingSphinx.sphinx_running? &&
|
|
242
|
+
search_for_id(document_id, index)
|
|
243
|
+
|
|
244
|
+
ThinkingSphinx::Configuration.instance.client.update(
|
|
245
|
+
index, ['sphinx_deleted'], {document_id => [1]}
|
|
246
|
+
)
|
|
285
247
|
end
|
|
286
|
-
|
|
248
|
+
|
|
287
249
|
def sphinx_offset
|
|
288
250
|
ThinkingSphinx.context.superclass_indexed_models.
|
|
289
251
|
index eldest_indexed_ancestor
|
|
290
252
|
end
|
|
291
|
-
|
|
292
|
-
# Temporarily disable delta indexing inside a block, then perform a
|
|
293
|
-
#
|
|
253
|
+
|
|
254
|
+
# Temporarily disable delta indexing inside a block, then perform a single
|
|
255
|
+
# rebuild of index at the end.
|
|
294
256
|
#
|
|
295
257
|
# Useful when performing updates to batches of models to prevent
|
|
296
258
|
# the delta index being rebuilt after each individual update.
|
|
297
259
|
#
|
|
298
|
-
# In the following example, the delta index will only be rebuilt
|
|
299
|
-
#
|
|
260
|
+
# In the following example, the delta index will only be rebuilt once,
|
|
261
|
+
# not 10 times.
|
|
300
262
|
#
|
|
301
263
|
# SomeModel.suspended_delta do
|
|
302
264
|
# 10.times do
|
|
@@ -306,74 +268,86 @@ module ThinkingSphinx
|
|
|
306
268
|
#
|
|
307
269
|
def suspended_delta(reindex_after = true, &block)
|
|
308
270
|
define_indexes
|
|
309
|
-
original_setting = ThinkingSphinx.
|
|
310
|
-
ThinkingSphinx.
|
|
271
|
+
original_setting = ThinkingSphinx.deltas_enabled?
|
|
272
|
+
ThinkingSphinx.deltas_enabled = false
|
|
311
273
|
begin
|
|
312
274
|
yield
|
|
313
275
|
ensure
|
|
314
|
-
ThinkingSphinx.
|
|
315
|
-
self.index_delta if reindex_after
|
|
276
|
+
ThinkingSphinx.deltas_enabled = original_setting
|
|
277
|
+
self.index_delta if reindex_after
|
|
316
278
|
end
|
|
317
279
|
end
|
|
318
|
-
|
|
280
|
+
|
|
319
281
|
private
|
|
320
|
-
|
|
282
|
+
|
|
321
283
|
def local_sphinx_indexes
|
|
322
|
-
|
|
284
|
+
sphinx_indexes.select { |index|
|
|
323
285
|
index.model == self
|
|
324
286
|
}
|
|
325
287
|
end
|
|
326
|
-
|
|
288
|
+
|
|
327
289
|
def add_sphinx_callbacks_and_extend(delta = false)
|
|
328
290
|
unless indexed_by_sphinx?
|
|
329
291
|
after_destroy :toggle_deleted
|
|
330
|
-
|
|
292
|
+
|
|
331
293
|
include ThinkingSphinx::ActiveRecord::AttributeUpdates
|
|
332
294
|
end
|
|
333
|
-
|
|
295
|
+
|
|
334
296
|
if delta && !delta_indexed_by_sphinx?
|
|
335
297
|
include ThinkingSphinx::ActiveRecord::Delta
|
|
336
|
-
|
|
337
|
-
before_save
|
|
338
|
-
after_commit
|
|
298
|
+
|
|
299
|
+
before_save :toggle_delta
|
|
300
|
+
after_commit :index_delta
|
|
339
301
|
end
|
|
340
302
|
end
|
|
341
|
-
|
|
303
|
+
|
|
342
304
|
def eldest_indexed_ancestor
|
|
343
305
|
ancestors.reverse.detect { |ancestor|
|
|
344
306
|
ThinkingSphinx.context.indexed_models.include?(ancestor.name)
|
|
345
307
|
}.name
|
|
346
308
|
end
|
|
347
309
|
end
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
310
|
+
|
|
311
|
+
def in_index?(suffix)
|
|
312
|
+
self.class.search_for_id self.sphinx_document_id, sphinx_index_name(suffix)
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
def in_core_index?
|
|
316
|
+
in_index? "core"
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
def in_delta_index?
|
|
320
|
+
in_index? "delta"
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
def in_both_indexes?
|
|
324
|
+
in_core_index? && in_delta_index?
|
|
325
|
+
end
|
|
326
|
+
|
|
353
327
|
def toggle_deleted
|
|
354
328
|
return unless ThinkingSphinx.updates_enabled?
|
|
355
|
-
|
|
329
|
+
|
|
356
330
|
self.class.core_index_names.each do |index_name|
|
|
357
331
|
self.class.delete_in_index index_name, self.sphinx_document_id
|
|
358
332
|
end
|
|
359
333
|
self.class.delta_index_names.each do |index_name|
|
|
360
334
|
self.class.delete_in_index index_name, self.sphinx_document_id
|
|
361
335
|
end if self.class.delta_indexed_by_sphinx? && toggled_delta?
|
|
362
|
-
|
|
336
|
+
|
|
363
337
|
rescue ::ThinkingSphinx::ConnectionError
|
|
364
338
|
# nothing
|
|
365
339
|
end
|
|
366
|
-
|
|
340
|
+
|
|
367
341
|
# Returns the unique integer id for the object. This method uses the
|
|
368
342
|
# attribute hash to get around ActiveRecord always mapping the #id method
|
|
369
343
|
# to whatever the real primary key is (which may be a unique string hash).
|
|
370
|
-
#
|
|
344
|
+
#
|
|
371
345
|
# @return [Integer] Unique record id for the purposes of Sphinx.
|
|
372
|
-
#
|
|
346
|
+
#
|
|
373
347
|
def primary_key_for_sphinx
|
|
374
|
-
read_attribute(self.class.primary_key_for_sphinx)
|
|
348
|
+
@primary_key_for_sphinx ||= read_attribute(self.class.primary_key_for_sphinx)
|
|
375
349
|
end
|
|
376
|
-
|
|
350
|
+
|
|
377
351
|
def sphinx_document_id
|
|
378
352
|
primary_key_for_sphinx * ThinkingSphinx.context.indexed_models.size +
|
|
379
353
|
self.class.sphinx_offset
|
|
@@ -384,7 +358,7 @@ module ThinkingSphinx
|
|
|
384
358
|
def sphinx_index_name(suffix)
|
|
385
359
|
"#{self.class.source_of_sphinx_index.name.underscore.tr(':/\\', '_')}_#{suffix}"
|
|
386
360
|
end
|
|
387
|
-
|
|
361
|
+
|
|
388
362
|
def define_indexes
|
|
389
363
|
self.class.define_indexes
|
|
390
364
|
end
|
|
@@ -3,51 +3,47 @@ module ThinkingSphinx
|
|
|
3
3
|
module AttributeUpdates
|
|
4
4
|
def self.included(base)
|
|
5
5
|
base.class_eval do
|
|
6
|
-
|
|
6
|
+
after_save :update_attribute_values
|
|
7
7
|
end
|
|
8
8
|
end
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
private
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
def update_attribute_values
|
|
13
13
|
return true unless ThinkingSphinx.updates_enabled? &&
|
|
14
14
|
ThinkingSphinx.sphinx_running?
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
self.class.sphinx_indexes.each do |index|
|
|
17
17
|
attribute_pairs = attribute_values_for_index(index)
|
|
18
18
|
attribute_names = attribute_pairs.keys
|
|
19
19
|
attribute_values = attribute_names.collect { |key|
|
|
20
20
|
attribute_pairs[key]
|
|
21
21
|
}
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
update_index index.core_name, attribute_names, attribute_values
|
|
24
24
|
next unless index.delta?
|
|
25
25
|
update_index index.delta_name, attribute_names, attribute_values
|
|
26
26
|
end
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
true
|
|
29
29
|
end
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
def updatable_attributes(index)
|
|
32
32
|
index.attributes.select { |attrib| attrib.updatable? }
|
|
33
33
|
end
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
def attribute_values_for_index(index)
|
|
36
36
|
updatable_attributes(index).inject({}) { |hash, attrib|
|
|
37
37
|
hash[attrib.unique_name.to_s] = attrib.live_value self
|
|
38
38
|
hash
|
|
39
39
|
}
|
|
40
40
|
end
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
def update_index(index_name, attribute_names, attribute_values)
|
|
43
|
-
ThinkingSphinx::
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
end
|
|
48
|
-
rescue Riddle::ConnectionError, Riddle::ResponseError,
|
|
49
|
-
ThinkingSphinx::SphinxError, Errno::ETIMEDOUT
|
|
50
|
-
# Not the end of the world if Sphinx isn't running.
|
|
43
|
+
config = ThinkingSphinx::Configuration.instance
|
|
44
|
+
config.client.update index_name, attribute_names, {
|
|
45
|
+
sphinx_document_id => attribute_values
|
|
46
|
+
} if self.class.search_for_id(sphinx_document_id, index_name)
|
|
51
47
|
end
|
|
52
48
|
end
|
|
53
49
|
end
|