DrMark-thinking-sphinx 1.1.6 → 1.1.14

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.
Files changed (40) hide show
  1. data/{README → README.textile} +84 -84
  2. data/lib/thinking_sphinx/active_record/attribute_updates.rb +48 -0
  3. data/lib/thinking_sphinx/active_record/delta.rb +10 -1
  4. data/lib/thinking_sphinx/active_record.rb +10 -3
  5. data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +1 -1
  6. data/lib/thinking_sphinx/attribute.rb +44 -134
  7. data/lib/thinking_sphinx/class_facet.rb +15 -0
  8. data/lib/thinking_sphinx/collection.rb +1 -0
  9. data/lib/thinking_sphinx/configuration.rb +7 -3
  10. data/lib/thinking_sphinx/deltas/datetime_delta.rb +1 -1
  11. data/lib/thinking_sphinx/deltas/default_delta.rb +3 -2
  12. data/lib/thinking_sphinx/deltas/delayed_delta.rb +4 -2
  13. data/lib/thinking_sphinx/deltas.rb +9 -6
  14. data/lib/thinking_sphinx/deploy/capistrano.rb +82 -0
  15. data/lib/thinking_sphinx/facet.rb +68 -18
  16. data/lib/thinking_sphinx/facet_collection.rb +16 -17
  17. data/lib/thinking_sphinx/field.rb +7 -97
  18. data/lib/thinking_sphinx/index/builder.rb +255 -232
  19. data/lib/thinking_sphinx/index.rb +37 -349
  20. data/lib/thinking_sphinx/property.rb +160 -0
  21. data/lib/thinking_sphinx/search/facets.rb +98 -0
  22. data/lib/thinking_sphinx/search.rb +4 -73
  23. data/lib/thinking_sphinx/source/internal_properties.rb +46 -0
  24. data/lib/thinking_sphinx/source/sql.rb +124 -0
  25. data/lib/thinking_sphinx/source.rb +150 -0
  26. data/lib/thinking_sphinx/tasks.rb +1 -1
  27. data/lib/thinking_sphinx.rb +3 -1
  28. data/spec/unit/thinking_sphinx/active_record_spec.rb +14 -12
  29. data/spec/unit/thinking_sphinx/attribute_spec.rb +16 -11
  30. data/spec/unit/thinking_sphinx/facet_collection_spec.rb +64 -0
  31. data/spec/unit/thinking_sphinx/facet_spec.rb +278 -0
  32. data/spec/unit/thinking_sphinx/field_spec.rb +18 -9
  33. data/spec/unit/thinking_sphinx/index/builder_spec.rb +347 -1
  34. data/spec/unit/thinking_sphinx/index_spec.rb +22 -27
  35. data/spec/unit/thinking_sphinx/rails_additions_spec.rb +183 -0
  36. data/spec/unit/thinking_sphinx/search_spec.rb +71 -0
  37. data/spec/unit/thinking_sphinx/source_spec.rb +156 -0
  38. data/tasks/distribution.rb +1 -1
  39. data/tasks/testing.rb +7 -15
  40. metadata +19 -3
@@ -1,12 +1,12 @@
1
- = Thinking Sphinx
1
+ h1. Thinking Sphinx
2
2
 
3
- == Usage
3
+ h2. Usage
4
4
 
5
- First, if you haven't done so already, check out the main usage[http://ts.freelancing-gods.com/usage.html] page. Once you've done that, the next place to look for information is the specific method docs - ThinkingSphinx::Search and ThinkingSphinx::Index::Builder in particular.
5
+ First, if you haven't done so already, check out the main "usage":http://ts.freelancing-gods.com/usage.html page. Once you've done that, the next place to look for information is the specific method docs - ThinkingSphinx::Search and ThinkingSphinx::Index::Builder in particular.
6
6
 
7
7
  Keep in mind that while Thinking Sphinx works for ActiveRecord with Merb, it doesn't yet support DataMapper (although that is planned).
8
8
 
9
- == Contributing
9
+ h2. Contributing
10
10
 
11
11
  Fork on GitHub and after you've committed tested patches, send a pull request.
12
12
 
@@ -26,102 +26,102 @@ Then install the ginger gem. The steps are the same, except that you might need
26
26
  rake gem
27
27
  sudo gem install pkg/ginger-1.1.0.gem
28
28
 
29
- Then install the faker gem:
30
-
31
- sudo gem install faker
32
-
33
29
  Then set up your database:
34
30
 
35
31
  cp spec/fixtures/database.yml.default spec/fixtures/database.yml
36
- cp spec/fixtures/database.yml.default features/support/db/database.yml
37
32
  mysqladmin -u root create thinking_sphinx
38
-
33
+
39
34
  Make sure you don't have another Sphinx daemon (searchd) running. If you do, quit it with "rake ts:stop"
40
35
  in the app root.
41
36
 
42
37
  You should now have a passing test suite from which to build your patch on.
43
38
 
44
39
  rake spec
45
- rake features (Note: You will need MySQL and Postgres gems to run the full suite. You may want to tweak your rakefile)
46
-
40
+
47
41
  If you get the message "Failed to start searchd daemon", run the spec with sudo:
48
42
 
49
43
  sudo rake spec
50
- sudo rake features
51
-
44
+
52
45
  If you quit the spec suite before it's completed, you may be left with data in the test
53
46
  database, causing the next run to have failures. Let that run complete and then try again.
54
47
 
55
- == Contributors
48
+ h2. Contributors
56
49
 
57
50
  Since I first released this library, there's been quite a few people who have submitted patches, to my immense gratitude. Others have suggested syntax changes and general improvements. So my thanks to the following people:
58
51
 
59
- - Joost Hietbrink
60
- - Jonathan Conway
61
- - Gregory Mirzayantz
62
- - Tung Nguyen
63
- - Sean Cribbs
64
- - Benoit Caccinolo
65
- - John Barton
66
- - Oliver Beddows
67
- - Arthur Zapparoli
68
- - Dusty Doris
69
- - Marcus Crafter
70
- - Patrick Lenz
71
- - Björn Andreasson
72
- - James Healy
73
- - Jae-Jun Hwang
74
- - Xavier Shay
75
- - Jason Rust
76
- - Gopal Patel
77
- - Chris Heald
78
- - Peter Vandenberk
79
- - Josh French
80
- - Andrew Bennett
81
- - Jordan Fowler
82
- - Seth Walker
83
- - Joe Noon
84
- - Wolfgang Postler
85
- - Rick Olson
86
- - Killian Murphy
87
- - Morten Primdahl
88
- - Ryan Bates
89
- - David Eisinger
90
- - Shay Arnett
91
- - Minh Tran
92
- - Jeremy Durham
93
- - Piotr Sarnacki
94
- - Matt Johnson
95
- - Nicolas Blanco
96
- - Max Lapshin
97
- - Josh Natanson
98
- - Philip Hallstrom
99
- - Christian Rishøj
100
- - Mike Flester
101
- - Jim Remsik
102
- - Kennon Ballou
103
- - Henrik Nyh
104
- - Emil Tin
105
- - Doug Cole
106
- - Ed Hickey
107
- - Evan Weaver
108
- - Thibaut Barrere
109
- - Kristopher Chambers
110
- - Dmitrij Smalko
111
- - Aleksey Yeschenko
112
- - Lachie Cox
113
- - Lourens Naude
114
- - Tom Davies
115
- - Dan Pickett
116
- - Alex Caudill
117
- - Jim Benton
118
- - John Aughey
119
- - Keith Pitty
120
- - Jeff Talbot
121
- - Dana Contreras
122
- - Menno van der Sman
123
- - Bill Harding
124
- - Isaac Feliu
125
- - Andrei Bocan
126
- - László Bácsi
127
- - Peter Wagenet
52
+ * Joost Hietbrink
53
+ * Jonathan Conway
54
+ * Gregory Mirzayantz
55
+ * Tung Nguyen
56
+ * Sean Cribbs
57
+ * Benoit Caccinolo
58
+ * John Barton
59
+ * Oliver Beddows
60
+ * Arthur Zapparoli
61
+ * Dusty Doris
62
+ * Marcus Crafter
63
+ * Patrick Lenz
64
+ * Björn Andreasson
65
+ * James Healy
66
+ * Jae-Jun Hwang
67
+ * Xavier Shay
68
+ * Jason Rust
69
+ * Gopal Patel
70
+ * Chris Heald
71
+ * Peter Vandenberk
72
+ * Josh French
73
+ * Andrew Bennett
74
+ * Jordan Fowler
75
+ * Seth Walker
76
+ * Joe Noon
77
+ * Wolfgang Postler
78
+ * Rick Olson
79
+ * Killian Murphy
80
+ * Morten Primdahl
81
+ * Ryan Bates
82
+ * David Eisinger
83
+ * Shay Arnett
84
+ * Minh Tran
85
+ * Jeremy Durham
86
+ * Piotr Sarnacki
87
+ * Matt Johnson
88
+ * Nicolas Blanco
89
+ * Max Lapshin
90
+ * Josh Natanson
91
+ * Philip Hallstrom
92
+ * Christian Rishøj
93
+ * Mike Flester
94
+ * Jim Remsik
95
+ * Kennon Ballou
96
+ * Henrik Nyh
97
+ * Emil Tin
98
+ * Doug Cole
99
+ * Ed Hickey
100
+ * Evan Weaver
101
+ * Thibaut Barrere
102
+ * Kristopher Chambers
103
+ * Dmitrij Smalko
104
+ * Aleksey Yeschenko
105
+ * Lachie Cox
106
+ * Lourens Naude
107
+ * Tom Davies
108
+ * Dan Pickett
109
+ * Alex Caudill
110
+ * Jim Benton
111
+ * John Aughey
112
+ * Keith Pitty
113
+ * Jeff Talbot
114
+ * Dana Contreras
115
+ * Menno van der Sman
116
+ * Bill Harding
117
+ * Isaac Feliu
118
+ * Andrei Bocan
119
+ * László Bácsi
120
+ * Peter Wagenet
121
+ * Max Lapshin
122
+ * Martin Emde
123
+ * David Wennergren
124
+ * Mark Lane
125
+ * Eric Lindvall
126
+ * Lawrence Pit
127
+ * Mike Bailey
@@ -0,0 +1,48 @@
1
+ module ThinkingSphinx
2
+ module ActiveRecord
3
+ module AttributeUpdates
4
+ def self.included(base)
5
+ base.class_eval do
6
+ after_commit :update_attribute_values
7
+ end
8
+ end
9
+
10
+ private
11
+
12
+ def update_attribute_values
13
+ return unless ThinkingSphinx.updates_enabled? && ThinkingSphinx.sphinx_running?
14
+
15
+ config = ThinkingSphinx::Configuration.instance
16
+ client = Riddle::Client.new config.address, config.port
17
+
18
+ self.sphinx_indexes.each do |index|
19
+ attribute_pairs = attribute_values_for_index(index)
20
+ attribute_names = attribute_pairs.keys
21
+ attribute_values = attribute_names.collect { |key|
22
+ attribute_pairs[key]
23
+ }
24
+
25
+ client.update "#{index.name}_core", attribute_names, {
26
+ sphinx_document_id => attribute_values
27
+ } if in_core_index?
28
+ end
29
+ end
30
+
31
+ def updatable_attributes(index)
32
+ index.attributes.select { |attrib| attrib.updatable? }
33
+ end
34
+
35
+ def attribute_values_for_index(index)
36
+ updatable_attributes(index).inject({}) { |hash, attrib|
37
+ if attrib.type == :datetime
38
+ hash[attrib.unique_name.to_s] = attrib.live_value(self).to_time.to_i
39
+ else
40
+ hash[attrib.unique_name.to_s] = attrib.live_value self
41
+ end
42
+
43
+ hash
44
+ }
45
+ end
46
+ end
47
+ end
48
+ end
@@ -69,7 +69,16 @@ module ThinkingSphinx
69
69
  end
70
70
 
71
71
  def should_toggle_delta?
72
- !self.respond_to?(:changed?) || self.changed? || self.new_record?
72
+ self.new_record? || indexed_data_changed?
73
+ end
74
+
75
+ def indexed_data_changed?
76
+ sphinx_indexes.any? { |index|
77
+ index.fields.any? { |field| field.changed?(self) } ||
78
+ index.attributes.any? { |attrib|
79
+ attrib.public? && attrib.changed?(self) && !attrib.updatable?
80
+ }
81
+ }
73
82
  end
74
83
  end
75
84
  end
@@ -1,3 +1,4 @@
1
+ require 'thinking_sphinx/active_record/attribute_updates'
1
2
  require 'thinking_sphinx/active_record/delta'
2
3
  require 'thinking_sphinx/active_record/search'
3
4
  require 'thinking_sphinx/active_record/has_many_association'
@@ -65,7 +66,7 @@ module ThinkingSphinx
65
66
  return unless ThinkingSphinx.define_indexes?
66
67
 
67
68
  self.sphinx_indexes ||= []
68
- index = Index.new(self, &block)
69
+ index = ThinkingSphinx::Index::Builder.generate(self, &block)
69
70
 
70
71
  self.sphinx_indexes << index
71
72
  unless ThinkingSphinx.indexed_models.include?(self.name)
@@ -79,6 +80,8 @@ module ThinkingSphinx
79
80
 
80
81
  after_destroy :toggle_deleted
81
82
 
83
+ include ThinkingSphinx::ActiveRecord::AttributeUpdates
84
+
82
85
  index
83
86
  end
84
87
  alias_method :sphinx_index, :define_index
@@ -148,7 +151,9 @@ module ThinkingSphinx
148
151
  self.sphinx_indexes.select { |ts_index|
149
152
  ts_index.model == self
150
153
  }.each_with_index do |ts_index, i|
151
- index.sources << ts_index.to_riddle_for_core(offset, i)
154
+ index.sources += ts_index.sources.collect { |source|
155
+ source.to_riddle_for_core(offset, i)
156
+ }
152
157
  end
153
158
 
154
159
  index
@@ -160,7 +165,9 @@ module ThinkingSphinx
160
165
  index.path = File.join(ThinkingSphinx::Configuration.instance.searchd_file_path, index.name)
161
166
 
162
167
  self.sphinx_indexes.each_with_index do |ts_index, i|
163
- index.sources << ts_index.to_riddle_for_delta(offset, i) if ts_index.delta?
168
+ index.sources += ts_index.sources.collect { |source|
169
+ source.to_riddle_for_delta(offset, i)
170
+ } if ts_index.delta?
164
171
  end
165
172
 
166
173
  index
@@ -11,7 +11,7 @@ module ThinkingSphinx
11
11
 
12
12
  def concatenate(clause, separator = ' ')
13
13
  clause.split(', ').collect { |field|
14
- "COALESCE(CAST(#{field} as varchar), '')"
14
+ field[/COALESCE/] ? field : "COALESCE(CAST(#{field} as varchar), '')"
15
15
  }.join(" || '#{separator}' || ")
16
16
  end
17
17
 
@@ -8,8 +8,8 @@ module ThinkingSphinx
8
8
  # generate SQL statements, you'll need to set the base model, and all the
9
9
  # associations. Which can get messy. Use Index.link!, it really helps.
10
10
  #
11
- class Attribute
12
- attr_accessor :alias, :columns, :associations, :model, :faceted, :source
11
+ class Attribute < ThinkingSphinx::Property
12
+ attr_accessor :query_source
13
13
 
14
14
  # To create a new attribute, you'll need to pass in either a single Column
15
15
  # or an array of them, and some (optional) options.
@@ -67,20 +67,17 @@ module ThinkingSphinx
67
67
  # If you're creating attributes for latitude and longitude, don't forget
68
68
  # that Sphinx expects these values to be in radians.
69
69
  #
70
- def initialize(columns, options = {})
71
- @columns = Array(columns)
72
- @associations = {}
70
+ def initialize(source, columns, options = {})
71
+ super
73
72
 
74
- raise "Cannot define a field with no columns. Maybe you are trying to index a field with a reserved name (id, name). You can fix this error by using a symbol rather than a bare name (:id instead of id)." if @columns.empty? || @columns.any? { |column| !column.respond_to?(:__stack) }
73
+ @type = options[:type]
74
+ @query_source = options[:source]
75
+ @crc = options[:crc]
75
76
 
76
- @alias = options[:as]
77
- @type = options[:type]
78
- @faceted = options[:facet]
79
- @source = options[:source]
80
- @crc = options[:crc]
77
+ @type ||= :multi unless @query_source.nil?
78
+ @type = :integer if @type == :string && @crc
81
79
 
82
- @type ||= :multi unless @source.nil?
83
- @type = :integer if @type == :string && @crc
80
+ source.attributes << self
84
81
  end
85
82
 
86
83
  # Get the part of the SELECT clause related to this attribute. Don't forget
@@ -93,37 +90,20 @@ module ThinkingSphinx
93
90
  return nil unless include_as_association?
94
91
 
95
92
  clause = @columns.collect { |column|
96
- column_with_prefix(column)
93
+ part = column_with_prefix(column)
94
+ type == :string ? adapter.convert_nulls(part) : part
97
95
  }.join(', ')
98
96
 
99
- separator = all_ints? ? ',' : ' '
97
+ separator = all_ints? || @crc ? ',' : ' '
100
98
 
101
- clause = adapter.concatenate(clause, separator) if concat_ws?
102
- clause = adapter.group_concatenate(clause, separator) if is_many?
103
99
  clause = adapter.cast_to_datetime(clause) if type == :datetime
104
- clause = adapter.convert_nulls(clause) if type == :string
105
100
  clause = adapter.crc(clause) if @crc
101
+ clause = adapter.concatenate(clause, separator) if concat_ws?
102
+ clause = adapter.group_concatenate(clause, separator) if is_many?
106
103
 
107
104
  "#{clause} AS #{quote_column(unique_name)}"
108
105
  end
109
106
 
110
- # Get the part of the GROUP BY clause related to this attribute - if one is
111
- # needed. If not, all you'll get back is nil. The latter will happen if
112
- # there isn't actually a real column to get data from, or if there's
113
- # multiple data values (read: a has_many or has_and_belongs_to_many
114
- # association).
115
- #
116
- def to_group_sql
117
- case
118
- when is_many?, is_string?, ThinkingSphinx.use_group_by_shortcut?
119
- nil
120
- else
121
- @columns.collect { |column|
122
- column_with_prefix(column)
123
- }
124
- end
125
- end
126
-
127
107
  def type_to_config
128
108
  {
129
109
  :multi => :sql_attr_multi,
@@ -136,7 +116,7 @@ module ThinkingSphinx
136
116
  end
137
117
 
138
118
  def include_as_association?
139
- ! (type == :multi && (source == :query || source == :ranged_query))
119
+ ! (type == :multi && (query_source == :query || query_source == :ranged_query))
140
120
  end
141
121
 
142
122
  # Returns the configuration value that should be used for
@@ -153,20 +133,7 @@ module ThinkingSphinx
153
133
  unique_name
154
134
  end
155
135
  end
156
-
157
- # Returns the unique name of the attribute - which is either the alias of
158
- # the attribute, or the name of the only column - if there is only one. If
159
- # there isn't, there should be an alias. Else things probably won't work.
160
- # Consider yourself warned.
161
- #
162
- def unique_name
163
- if @columns.length == 1
164
- @alias || @columns.first.__name
165
- else
166
- @alias
167
- end
168
- end
169
-
136
+
170
137
  # Returns the type of the column. If that's not already set, it returns
171
138
  # :multi if there's the possibility of more than one value, :string if
172
139
  # there's more than one association, otherwise it figures out what the
@@ -192,18 +159,34 @@ module ThinkingSphinx
192
159
  end
193
160
  end
194
161
 
195
- def to_facet
196
- return nil unless @faceted
197
-
198
- ThinkingSphinx::Facet.new(self)
162
+ def updatable?
163
+ [:integer, :datetime, :boolean].include?(type) && !is_string?
164
+ end
165
+
166
+ def live_value(instance)
167
+ object = instance
168
+ column = @columns.first
169
+ column.__stack.each { |method| object = object.send(method) }
170
+ object.send(column.__name)
171
+ end
172
+
173
+ def all_ints?
174
+ @columns.all? { |col|
175
+ klasses = @associations[col].empty? ? [@model] :
176
+ @associations[col].collect { |assoc| assoc.reflection.klass }
177
+ klasses.all? { |klass|
178
+ column = klass.columns.detect { |column| column.name == col.__name.to_s }
179
+ !column.nil? && column.type == :integer
180
+ }
181
+ }
199
182
  end
200
183
 
201
184
  private
202
185
 
203
186
  def source_value(offset)
204
187
  if is_string?
205
- "#{source.to_s.dasherize}; #{columns.first.__name}"
206
- elsif source == :ranged_query
188
+ "#{query_source.to_s.dasherize}; #{columns.first.__name}"
189
+ elsif query_source == :ranged_query
207
190
  "ranged-query; #{query offset} #{query_clause}; #{range_query}"
208
191
  else
209
192
  "query; #{query offset}"
@@ -249,84 +232,10 @@ FROM #{quote_table_name assoc.table}
249
232
  }
250
233
  end
251
234
 
252
- def adapter
253
- @adapter ||= @model.sphinx_database_adapter
254
- end
255
-
256
- def quote_with_table(table, column)
257
- "#{quote_table_name(table)}.#{quote_column(column)}"
258
- end
259
-
260
- def quote_column(column)
261
- @model.connection.quote_column_name(column)
262
- end
263
-
264
- def quote_table_name(table_name)
265
- @model.connection.quote_table_name(table_name)
266
- end
267
-
268
- # Indication of whether the columns should be concatenated with a space
269
- # between each value. True if there's either multiple sources or multiple
270
- # associations.
271
- #
272
- def concat_ws?
273
- multiple_associations? || @columns.length > 1
274
- end
275
-
276
- # Checks whether any column requires multiple associations (which only
277
- # happens for polymorphic situations).
278
- #
279
- def multiple_associations?
280
- associations.any? { |col,assocs| assocs.length > 1 }
281
- end
282
-
283
- # Builds a column reference tied to the appropriate associations. This
284
- # dives into the associations hash and their corresponding joins to
285
- # figure out how to correctly reference a column in SQL.
286
- #
287
- def column_with_prefix(column)
288
- if column.is_string?
289
- column.__name
290
- elsif associations[column].empty?
291
- "#{@model.quoted_table_name}.#{quote_column(column.__name)}"
292
- else
293
- associations[column].collect { |assoc|
294
- assoc.has_column?(column.__name) ?
295
- "#{quote_table_name(assoc.join.aliased_table_name)}" +
296
- ".#{quote_column(column.__name)}" :
297
- nil
298
- }.compact.join(', ')
299
- end
300
- end
301
-
302
- # Could there be more than one value related to the parent record? If so,
303
- # then this will return true. If not, false. It's that simple.
304
- #
305
- def is_many?
306
- associations.values.flatten.any? { |assoc| assoc.is_many? }
307
- end
308
-
309
235
  def is_many_ints?
310
236
  concat_ws? && all_ints?
311
237
  end
312
-
313
- # Returns true if any of the columns are string values, instead of database
314
- # column references.
315
- def is_string?
316
- columns.all? { |col| col.is_string? }
317
- end
318
-
319
- def all_ints?
320
- @columns.all? { |col|
321
- klasses = @associations[col].empty? ? [@model] :
322
- @associations[col].collect { |assoc| assoc.reflection.klass }
323
- klasses.all? { |klass|
324
- column = klass.columns.detect { |column| column.name == col.__name.to_s }
325
- !column.nil? && column.type == :integer
326
- }
327
- }
328
- end
329
-
238
+
330
239
  def type_from_database
331
240
  klass = @associations.values.flatten.first ?
332
241
  @associations.values.flatten.first.reflection.klass : @model
@@ -347,9 +256,10 @@ FROM #{quote_table_name assoc.table}
347
256
  else
348
257
  raise <<-MESSAGE
349
258
 
350
- Cannot automatically map column type #{type_from_db} to an equivalent Sphinx
351
- type (integer, float, boolean, datetime, string as ordinal). You could try to
352
- explicitly convert the column's value in your define_index block:
259
+ Cannot automatically map attribute #{unique_name} in #{@model.name} to an
260
+ equivalent Sphinx type (integer, float, boolean, datetime, string as ordinal).
261
+ You could try to explicitly convert the column's value in your define_index
262
+ block:
353
263
  has "CAST(column AS INT)", :type => :integer, :as => :column
354
264
  MESSAGE
355
265
  end
@@ -0,0 +1,15 @@
1
+ module ThinkingSphinx
2
+ class ClassFacet < ThinkingSphinx::Facet
3
+ def name
4
+ :class
5
+ end
6
+
7
+ def attribute_name
8
+ "class_crc"
9
+ end
10
+
11
+ def value(object, attribute_value)
12
+ object.class.name
13
+ end
14
+ end
15
+ end
@@ -46,6 +46,7 @@ module ThinkingSphinx
46
46
  ids = matches.collect { |match| match[:attributes]["sphinx_internal_id"] }
47
47
  instances = ids.length > 0 ? klass.find(
48
48
  :all,
49
+ :joins => options[:joins],
49
50
  :conditions => {klass.primary_key.to_sym => ids},
50
51
  :include => (options[:include] || index_options[:include]),
51
52
  :select => (options[:select] || index_options[:select]),
@@ -31,8 +31,10 @@ module ThinkingSphinx
31
31
  # fashion to database.yml - using the following keys: config_file,
32
32
  # searchd_log_file, query_log_file, pid_file, searchd_file_path, port,
33
33
  # allow_star, enable_star, min_prefix_len, min_infix_len, mem_limit,
34
- # max_matches, # morphology, charset_type, charset_table, ignore_chars,
35
- # html_strip, # html_remove_elements. I think you've got the idea.
34
+ # max_matches, morphology, charset_type, charset_table, ignore_chars,
35
+ # html_strip, html_remove_elements, delayed_job_priority.
36
+ #
37
+ # I think you've got the idea.
36
38
  #
37
39
  # Each setting in the YAML file is optional - so only put in the ones you
38
40
  # want to change.
@@ -55,7 +57,8 @@ module ThinkingSphinx
55
57
 
56
58
  attr_accessor :config_file, :searchd_log_file, :query_log_file,
57
59
  :pid_file, :searchd_file_path, :address, :port, :allow_star,
58
- :database_yml_file, :app_root, :bin_path, :model_directories
60
+ :database_yml_file, :app_root, :bin_path, :model_directories,
61
+ :delayed_job_priority
59
62
 
60
63
  attr_accessor :source_options, :index_options
61
64
 
@@ -87,6 +90,7 @@ module ThinkingSphinx
87
90
  self.bin_path = ""
88
91
  self.model_directories = ["#{app_root}/app/models/"] +
89
92
  Dir.glob("#{app_root}/vendor/plugins/*/app/models/")
93
+ self.delayed_job_priority = 0
90
94
 
91
95
  self.source_options = {}
92
96
  self.index_options = {
@@ -39,7 +39,7 @@ module ThinkingSphinx
39
39
 
40
40
  def clause(model, toggled)
41
41
  if toggled
42
- "#{model.quoted_table_name}.#{@index.quote_column(@column.to_s)}" +
42
+ "#{model.quoted_table_name}.#{model.connection.quote_column_name(@column.to_s)}" +
43
43
  " > #{adapter.time_difference(@threshold)}"
44
44
  else
45
45
  nil
@@ -39,11 +39,12 @@ module ThinkingSphinx
39
39
 
40
40
  def reset_query(model)
41
41
  "UPDATE #{model.quoted_table_name} SET " +
42
- "#{@index.quote_column(@column.to_s)} = #{adapter.boolean(false)}"
42
+ "#{model.connection.quote_column_name(@column.to_s)} = #{adapter.boolean(false)} " +
43
+ "WHERE #{model.connection.quote_column_name(@column.to_s)} = #{adapter.boolean(true)}"
43
44
  end
44
45
 
45
46
  def clause(model, toggled)
46
- "#{model.quoted_table_name}.#{@index.quote_column(@column.to_s)}" +
47
+ "#{model.quoted_table_name}.#{model.connection.quote_column_name(@column.to_s)}" +
47
48
  " = #{adapter.boolean(toggled)}"
48
49
  end
49
50
 
@@ -9,13 +9,15 @@ module ThinkingSphinx
9
9
  class DelayedDelta < ThinkingSphinx::Deltas::DefaultDelta
10
10
  def index(model, instance = nil)
11
11
  ThinkingSphinx::Deltas::Job.enqueue(
12
- ThinkingSphinx::Deltas::DeltaJob.new(delta_index_name(model))
12
+ ThinkingSphinx::Deltas::DeltaJob.new(delta_index_name(model)),
13
+ ThinkingSphinx::Configuration.instance.delayed_job_priority
13
14
  )
14
15
 
15
16
  Delayed::Job.enqueue(
16
17
  ThinkingSphinx::Deltas::FlagAsDeletedJob.new(
17
18
  core_index_name(model), instance.sphinx_document_id
18
- )
19
+ ),
20
+ ThinkingSphinx::Configuration.instance.delayed_job_priority
19
21
  ) if instance
20
22
 
21
23
  true