thinking-sphinx 2.0.5 → 2.0.6

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 (70) hide show
  1. data/README.textile +7 -1
  2. data/features/searching_by_model.feature +24 -30
  3. data/features/step_definitions/common_steps.rb +5 -5
  4. data/features/thinking_sphinx/db/.gitignore +1 -0
  5. data/features/thinking_sphinx/db/fixtures/post_keywords.txt +1 -0
  6. data/spec/fixtures/data.sql +32 -0
  7. data/spec/fixtures/database.yml.default +3 -0
  8. data/spec/fixtures/models.rb +161 -0
  9. data/spec/fixtures/structure.sql +146 -0
  10. data/spec/spec_helper.rb +62 -0
  11. data/spec/sphinx_helper.rb +61 -0
  12. data/spec/support/rails.rb +18 -0
  13. data/spec/thinking_sphinx/active_record/delta_spec.rb +24 -24
  14. data/spec/thinking_sphinx/active_record/has_many_association_spec.rb +27 -0
  15. data/spec/thinking_sphinx/active_record/scopes_spec.rb +25 -25
  16. data/spec/thinking_sphinx/active_record_spec.rb +108 -107
  17. data/spec/thinking_sphinx/adapters/abstract_adapter_spec.rb +38 -38
  18. data/spec/thinking_sphinx/association_spec.rb +69 -35
  19. data/spec/thinking_sphinx/context_spec.rb +61 -64
  20. data/spec/thinking_sphinx/search_spec.rb +7 -0
  21. data/spec/thinking_sphinx_spec.rb +47 -46
  22. metadata +49 -141
  23. data/VERSION +0 -1
  24. data/lib/cucumber/thinking_sphinx/external_world.rb +0 -12
  25. data/lib/cucumber/thinking_sphinx/internal_world.rb +0 -127
  26. data/lib/cucumber/thinking_sphinx/sql_logger.rb +0 -20
  27. data/lib/thinking-sphinx.rb +0 -1
  28. data/lib/thinking_sphinx.rb +0 -301
  29. data/lib/thinking_sphinx/action_controller.rb +0 -31
  30. data/lib/thinking_sphinx/active_record.rb +0 -384
  31. data/lib/thinking_sphinx/active_record/attribute_updates.rb +0 -52
  32. data/lib/thinking_sphinx/active_record/delta.rb +0 -65
  33. data/lib/thinking_sphinx/active_record/has_many_association.rb +0 -36
  34. data/lib/thinking_sphinx/active_record/has_many_association_with_scopes.rb +0 -21
  35. data/lib/thinking_sphinx/active_record/log_subscriber.rb +0 -61
  36. data/lib/thinking_sphinx/active_record/scopes.rb +0 -93
  37. data/lib/thinking_sphinx/adapters/abstract_adapter.rb +0 -87
  38. data/lib/thinking_sphinx/adapters/mysql_adapter.rb +0 -62
  39. data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +0 -157
  40. data/lib/thinking_sphinx/association.rb +0 -219
  41. data/lib/thinking_sphinx/attribute.rb +0 -396
  42. data/lib/thinking_sphinx/auto_version.rb +0 -38
  43. data/lib/thinking_sphinx/bundled_search.rb +0 -44
  44. data/lib/thinking_sphinx/class_facet.rb +0 -20
  45. data/lib/thinking_sphinx/configuration.rb +0 -339
  46. data/lib/thinking_sphinx/context.rb +0 -76
  47. data/lib/thinking_sphinx/core/string.rb +0 -15
  48. data/lib/thinking_sphinx/deltas.rb +0 -28
  49. data/lib/thinking_sphinx/deltas/default_delta.rb +0 -62
  50. data/lib/thinking_sphinx/deploy/capistrano.rb +0 -101
  51. data/lib/thinking_sphinx/excerpter.rb +0 -23
  52. data/lib/thinking_sphinx/facet.rb +0 -128
  53. data/lib/thinking_sphinx/facet_search.rb +0 -170
  54. data/lib/thinking_sphinx/field.rb +0 -98
  55. data/lib/thinking_sphinx/index.rb +0 -157
  56. data/lib/thinking_sphinx/index/builder.rb +0 -312
  57. data/lib/thinking_sphinx/index/faux_column.rb +0 -118
  58. data/lib/thinking_sphinx/join.rb +0 -37
  59. data/lib/thinking_sphinx/property.rb +0 -185
  60. data/lib/thinking_sphinx/railtie.rb +0 -46
  61. data/lib/thinking_sphinx/search.rb +0 -972
  62. data/lib/thinking_sphinx/search_methods.rb +0 -439
  63. data/lib/thinking_sphinx/sinatra.rb +0 -7
  64. data/lib/thinking_sphinx/source.rb +0 -194
  65. data/lib/thinking_sphinx/source/internal_properties.rb +0 -51
  66. data/lib/thinking_sphinx/source/sql.rb +0 -157
  67. data/lib/thinking_sphinx/tasks.rb +0 -130
  68. data/lib/thinking_sphinx/test.rb +0 -55
  69. data/tasks/distribution.rb +0 -33
  70. data/tasks/testing.rb +0 -80
@@ -1,439 +0,0 @@
1
- module ThinkingSphinx
2
- module SearchMethods
3
- def self.included(base)
4
- base.class_eval do
5
- extend ThinkingSphinx::SearchMethods::ClassMethods
6
- end
7
- end
8
-
9
- module ClassMethods
10
- def search_context
11
- # Comparing to name string to avoid class inheritance complications
12
- case self.class.name
13
- when 'Class'
14
- self
15
- else
16
- nil
17
- end
18
- end
19
-
20
- # Searches through the Sphinx indexes for relevant matches. There's
21
- # various ways to search, sort, group and filter - which are covered
22
- # below.
23
- #
24
- # Also, if you have WillPaginate installed, the search method can be used
25
- # just like paginate. The same parameters - :page and :per_page - work as
26
- # expected, and the returned result set can be used by the will_paginate
27
- # helper.
28
- #
29
- # == Basic Searching
30
- #
31
- # The simplest way of searching is straight text.
32
- #
33
- # ThinkingSphinx.search "pat"
34
- # ThinkingSphinx.search "google"
35
- # User.search "pat", :page => (params[:page] || 1)
36
- # Article.search "relevant news issue of the day"
37
- #
38
- # If you specify :include, like in an #find call, this will be respected
39
- # when loading the relevant models from the search results.
40
- #
41
- # User.search "pat", :include => :posts
42
- #
43
- # == Match Modes
44
- #
45
- # Sphinx supports 5 different matching modes. By default Thinking Sphinx
46
- # uses :all, which unsurprisingly requires all the supplied search terms
47
- # to match a result.
48
- #
49
- # Alternative modes include:
50
- #
51
- # User.search "pat allan", :match_mode => :any
52
- # User.search "pat allan", :match_mode => :phrase
53
- # User.search "pat | allan", :match_mode => :boolean
54
- # User.search "@name pat | @username pat", :match_mode => :extended
55
- #
56
- # Any will find results with any of the search terms. Phrase treats the
57
- # search terms a single phrase instead of individual words. Boolean and
58
- # extended allow for more complex query syntax, refer to the sphinx
59
- # documentation for further details.
60
- #
61
- # == Weighting
62
- #
63
- # Sphinx has support for weighting, where matches in one field can be
64
- # considered more important than in another. Weights are integers, with 1
65
- # as the default. They can be set per-search like this:
66
- #
67
- # User.search "pat allan", :field_weights => { :alias => 4, :aka => 2 }
68
- #
69
- # If you're searching multiple models, you can set per-index weights:
70
- #
71
- # ThinkingSphinx.search "pat", :index_weights => { User => 10 }
72
- #
73
- # See http://sphinxsearch.com/doc.html#weighting for further details.
74
- #
75
- # == Searching by Fields
76
- #
77
- # If you want to step it up a level, you can limit your search terms to
78
- # specific fields:
79
- #
80
- # User.search :conditions => {:name => "pat"}
81
- #
82
- # This uses Sphinx's extended match mode, unless you specify a different
83
- # match mode explicitly (but then this way of searching won't work). Also
84
- # note that you don't need to put in a search string.
85
- #
86
- # == Searching by Attributes
87
- #
88
- # Also known as filters, you can limit your searches to documents that
89
- # have specific values for their attributes. There are three ways to do
90
- # this. The first two techniques work in all scenarios - using the :with
91
- # or :with_all options.
92
- #
93
- # ThinkingSphinx.search :with => {:tag_ids => 10}
94
- # ThinkingSphinx.search :with => {:tag_ids => [10,12]}
95
- # ThinkingSphinx.search :with_all => {:tag_ids => [10,12]}
96
- #
97
- # The first :with search will match records with a tag_id attribute of 10.
98
- # The second :with will match records with a tag_id attribute of 10 OR 12.
99
- # If you need to find records that are tagged with ids 10 AND 12, you
100
- # will need to use the :with_all search parameter. This is particuarly
101
- # useful in conjunction with Multi Value Attributes (MVAs).
102
- #
103
- # The third filtering technique is only viable if you're searching with a
104
- # specific model (not multi-model searching). With a single model,
105
- # Thinking Sphinx can figure out what attributes and fields are available,
106
- # so you can put it all in the :conditions hash, and it will sort it out.
107
- #
108
- # Node.search :conditions => {:parent_id => 10}
109
- #
110
- # Filters can be single values, arrays of values, or ranges.
111
- #
112
- # Article.search "East Timor", :conditions => {:rating => 3..5}
113
- #
114
- # == Excluding by Attributes
115
- #
116
- # Sphinx also supports negative filtering - where the filters are of
117
- # attribute values to exclude. This is done with the :without option:
118
- #
119
- # User.search :without => {:role_id => 1}
120
- #
121
- # == Excluding by Primary Key
122
- #
123
- # There is a shortcut to exclude records by their ActiveRecord primary
124
- # key:
125
- #
126
- # User.search :without_ids => 1
127
- #
128
- # Pass an array or a single value.
129
- #
130
- # The primary key must be an integer as a negative filter is used. Note
131
- # that for multi-model search, an id may occur in more than one model.
132
- #
133
- # == Infix (Star) Searching
134
- #
135
- # Enable infix searching by something like this in config/sphinx.yml:
136
- #
137
- # development:
138
- # enable_star: 1
139
- # min_infix_len: 2
140
- #
141
- # Note that this will make indexing take longer.
142
- #
143
- # With those settings (and after reindexing), wildcard asterisks can be
144
- # used in queries:
145
- #
146
- # Location.search "*elbourn*"
147
- #
148
- # To automatically add asterisks around every token (but not operators),
149
- # pass the :star option:
150
- #
151
- # Location.search "elbourn -ustrali", :star => true,
152
- # :match_mode => :boolean
153
- #
154
- # This would become "*elbourn* -*ustrali*". The :star option only adds the
155
- # asterisks. You need to make the config/sphinx.yml changes yourself.
156
- #
157
- # By default, the tokens are assumed to match the regular expression
158
- # /\w\+/u\+. If you've modified the charset_table, pass another regular
159
- # expression, e.g.
160
- #
161
- # User.search("oo@bar.c", :star => /[\w@.]+/u)
162
- #
163
- # to search for "*oo@bar.c*" and not "*oo*@*bar*.*c*".
164
- #
165
- # == Sorting
166
- #
167
- # Sphinx can only sort by attributes, so generally you will need to avoid
168
- # using field names in your :order option. However, if you're searching
169
- # on a single model, and have specified some fields as sortable, you can
170
- # use those field names and Thinking Sphinx will interpret accordingly.
171
- # Remember: this will only happen for single-model searches, and only
172
- # through the :order option.
173
- #
174
- # Location.search "Melbourne", :order => :state
175
- # User.search :conditions => {:role_id => 2}, :order => "name ASC"
176
- #
177
- # Keep in mind that if you use a string, you *must* specify the direction
178
- # (ASC or DESC) else Sphinx won't return any results. If you use a symbol
179
- # then Thinking Sphinx assumes ASC, but if you wish to state otherwise,
180
- # use the :sort_mode option:
181
- #
182
- # Location.search "Melbourne", :order => :state, :sort_mode => :desc
183
- #
184
- # Of course, there are other sort modes - check out the Sphinx
185
- # documentation[http://sphinxsearch.com/doc.html] for that level of
186
- # detail though.
187
- #
188
- # If desired, you can sort by a column in your model instead of a sphinx
189
- # field or attribute. This sort only applies to the current page, so is
190
- # most useful when performing a search with a single page of results.
191
- #
192
- # User.search("pat", :sql_order => "name")
193
- #
194
- # == Grouping
195
- #
196
- # For this you can use the group_by, group_clause and group_function
197
- # options - which are all directly linked to Sphinx's expectations. No
198
- # magic from Thinking Sphinx. It can get a little tricky, so make sure
199
- # you read all the relevant
200
- # documentation[http://sphinxsearch.com/doc.html#clustering] first.
201
- #
202
- # Grouping is done via three parameters within the options hash
203
- # * <tt>:group_function</tt> determines the way grouping is done
204
- # * <tt>:group_by</tt> determines the field which is used for grouping
205
- # * <tt>:group_clause</tt> determines the sorting order
206
- #
207
- # As a convenience, you can also use
208
- # * <tt>:group</tt>
209
- # which sets :group_by and defaults to :group_function of :attr
210
- #
211
- # === group_function
212
- #
213
- # Valid values for :group_function are
214
- # * <tt>:day</tt>, <tt>:week</tt>, <tt>:month</tt>, <tt>:year</tt> - Grouping is done by the respective timeframes.
215
- # * <tt>:attr</tt>, <tt>:attrpair</tt> - Grouping is done by the specified attributes(s)
216
- #
217
- # === group_by
218
- #
219
- # This parameter denotes the field by which grouping is done. Note that
220
- # the specified field must be a sphinx attribute or index.
221
- #
222
- # === group_clause
223
- #
224
- # This determines the sorting order of the groups. In a grouping search,
225
- # the matches within a group will sorted by the <tt>:sort_mode</tt> and
226
- # <tt>:order</tt> parameters. The group matches themselves however, will
227
- # be sorted by <tt>:group_clause</tt>.
228
- #
229
- # The syntax for this is the same as an order parameter in extended sort
230
- # mode. Namely, you can specify an SQL-like sort expression with up to 5
231
- # attributes (including internal attributes), eg: "@relevance DESC, price
232
- # ASC, @id DESC"
233
- #
234
- # === Grouping by timestamp
235
- #
236
- # Timestamp grouping groups off items by the day, week, month or year of
237
- # the attribute given. In order to do this you need to define a timestamp
238
- # attribute, which pretty much looks like the standard defintion for any
239
- # attribute.
240
- #
241
- # define_index do
242
- # #
243
- # # All your other stuff
244
- # #
245
- # has :created_at
246
- # end
247
- #
248
- # When you need to fire off your search, it'll go something to the tune of
249
- #
250
- # Fruit.search "apricot", :group_function => :day,
251
- # :group_by => 'created_at'
252
- #
253
- # The <tt>@groupby</tt> special attribute will contain the date for that
254
- # group. Depending on the <tt>:group_function</tt> parameter, the date
255
- # format will be:
256
- #
257
- # * <tt>:day</tt> - YYYYMMDD
258
- # * <tt>:week</tt> - YYYYNNN (NNN is the first day of the week in question,
259
- # counting from the start of the year )
260
- # * <tt>:month</tt> - YYYYMM
261
- # * <tt>:year</tt> - YYYY
262
- #
263
- # === Grouping by attribute
264
- #
265
- # The syntax is the same as grouping by timestamp, except for the fact
266
- # that the <tt>:group_function</tt> parameter is changed.
267
- #
268
- # Fruit.search "apricot", :group_function => :attr, :group_by => 'size'
269
- #
270
- # == Geo/Location Searching
271
- #
272
- # Sphinx - and therefore Thinking Sphinx - has the facility to search
273
- # around a geographical point, using a given latitude and longitude. To
274
- # take advantage of this, you will need to have both of those values in
275
- # attributes. To search with that point, you can then use one of the
276
- # following syntax examples:
277
- #
278
- # Address.search "Melbourne", :geo => [1.4, -2.217],
279
- # :order => "@geodist asc"
280
- # Address.search "Australia", :geo => [-0.55, 3.108],
281
- # :order => "@geodist asc" :latitude_attr => "latit",
282
- # :longitude_attr => "longit"
283
- #
284
- # The first example applies when your latitude and longitude attributes
285
- # are named any of lat, latitude, lon, long or longitude. If that's not
286
- # the case, you will need to explicitly state them in your search, _or_
287
- # you can do so in your model:
288
- #
289
- # define_index do
290
- # has :latit # Float column, stored in radians
291
- # has :longit # Float column, stored in radians
292
- #
293
- # set_property :latitude_attr => "latit"
294
- # set_property :longitude_attr => "longit"
295
- # end
296
- #
297
- # Now, geo-location searching really only has an affect if you have a
298
- # filter, sort or grouping clause related to it - otherwise it's just a
299
- # normal search, and _will not_ return a distance value otherwise. To
300
- # make use of the positioning difference, use the special attribute
301
- # "@geodist" in any of your filters or sorting or grouping clauses.
302
- #
303
- # And don't forget - both the latitude and longitude you use in your
304
- # search, and the values in your indexes, need to be stored as a float in
305
- # radians, _not_ degrees. Keep in mind that if you do this conversion in
306
- # SQL you will need to explicitly declare a column type of :float.
307
- #
308
- # define_index do
309
- # has 'RADIANS(lat)', :as => :lat, :type => :float
310
- # # ...
311
- # end
312
- #
313
- # Once you've got your results set, you can access the distances as
314
- # follows:
315
- #
316
- # @results.each_with_geodist do |result, distance|
317
- # # ...
318
- # end
319
- #
320
- # The distance value is returned as a float, representing the distance in
321
- # metres.
322
- #
323
- # == Filtering by custom attributes
324
- #
325
- # Do note that this applies only to sphinx 0.9.9
326
- #
327
- # Should you find yourself in desperate need of a filter that involves
328
- # selecting either one of multiple conditions, one solution could be
329
- # provided by the :sphinx_select option within the search.
330
- # This handles which fields are selected by sphinx from its store.
331
- #
332
- # The default value is "*", and you can add custom fields using syntax
333
- # similar to sql:
334
- #
335
- # Flower.search "foo",
336
- # :sphinx_select => "*, petals < 1 or color = 2 as grass"
337
- #
338
- # This will add the 'grass' attribute, which will now be usable in your
339
- # filters.
340
- #
341
- # == Handling a Stale Index
342
- #
343
- # Especially if you don't use delta indexing, you risk having records in
344
- # the Sphinx index that are no longer in the database. By default, those
345
- # will simply come back as nils:
346
- #
347
- # >> pat_user.delete
348
- # >> User.search("pat")
349
- # Sphinx Result: [1,2]
350
- # => [nil, <#User id: 2>]
351
- #
352
- # (If you search across multiple models, you'll get
353
- # ActiveRecord::RecordNotFound.)
354
- #
355
- # You can simply Array#compact these results or handle the nils in some
356
- # other way, but Sphinx will still report two results, and the missing
357
- # records may upset your layout.
358
- #
359
- # If you pass :retry_stale => true to a single-model search, missing
360
- # records will cause Thinking Sphinx to retry the query but excluding
361
- # those records. Since search is paginated, the new search could
362
- # potentially include missing records as well, so by default Thinking
363
- # Sphinx will retry three times. Pass :retry_stale => 5 to retry five
364
- # times, and so on. If there are still missing ids on the last retry, they
365
- # are shown as nils.
366
- #
367
- def search(*args)
368
- ThinkingSphinx::Search.new *search_options(args)
369
- end
370
-
371
- # Searches for results that match the parameters provided. Will only
372
- # return the ids for the matching objects. See #search for syntax
373
- # examples.
374
- #
375
- # Note that this only searches the Sphinx index, with no ActiveRecord
376
- # queries. Thus, if your index is not in sync with the database, this
377
- # method may return ids that no longer exist there.
378
- #
379
- def search_for_ids(*args)
380
- ThinkingSphinx::Search.new *search_options(args, :ids_only => true)
381
- end
382
-
383
- # Checks if a document with the given id exists within a specific index.
384
- # Expected parameters:
385
- #
386
- # - ID of the document
387
- # - Index to check within
388
- # - Options hash (defaults to {})
389
- #
390
- # Example:
391
- #
392
- # ThinkingSphinx.search_for_id(10, "user_core", :class => User)
393
- #
394
- def search_for_id(id, index, options = {})
395
- ThinkingSphinx::Search.new(
396
- *search_options([],
397
- :ids_only => true,
398
- :index => index,
399
- :id_range => id..id
400
- )
401
- ).any?
402
- end
403
-
404
- def count(*args)
405
- search_context ? super : search_count(*args)
406
- end
407
-
408
- def search_count(*args)
409
- search = ThinkingSphinx::Search.new(
410
- *search_options(args, :ids_only => true)
411
- )
412
- search.first # forces the query
413
- search.total_entries
414
- end
415
-
416
- # Model.facets *args
417
- # ThinkingSphinx.facets *args
418
- # ThinkingSphinx.facets *args, :all_facets => true
419
- # ThinkingSphinx.facets *args, :class_facet => false
420
- #
421
- def facets(*args)
422
- ThinkingSphinx::FacetSearch.new *search_options(args)
423
- end
424
-
425
- private
426
-
427
- def search_options(args, options = {})
428
- options = args.extract_options!.merge(options)
429
- options[:classes] ||= classes_option
430
- args << options
431
- end
432
-
433
- def classes_option
434
- classes_option = [search_context].compact
435
- classes_option.empty? ? nil : classes_option
436
- end
437
- end
438
- end
439
- end
@@ -1,7 +0,0 @@
1
- require 'thinking_sphinx'
2
-
3
- ThinkingSphinx::Configuration.instance
4
-
5
- ActiveSupport.on_load :active_record do
6
- include ThinkingSphinx::ActiveRecord
7
- end
@@ -1,194 +0,0 @@
1
- require 'thinking_sphinx/source/internal_properties'
2
- require 'thinking_sphinx/source/sql'
3
-
4
- module ThinkingSphinx
5
- class Source
6
- include ThinkingSphinx::Source::InternalProperties
7
- include ThinkingSphinx::Source::SQL
8
-
9
- attr_accessor :model, :fields, :attributes, :joins, :conditions, :groupings,
10
- :options
11
- attr_reader :base, :index, :database_configuration
12
-
13
- def initialize(index, options = {})
14
- @index = index
15
- @model = index.model
16
- @fields = []
17
- @attributes = []
18
- @joins = []
19
- @conditions = []
20
- @groupings = []
21
- @options = options
22
- @associations = {}
23
- @database_configuration = @model.connection.
24
- instance_variable_get(:@config).clone
25
-
26
- @base = join_dependency_class.new(
27
- @model, [], initial_joins
28
- )
29
-
30
- unless @model.descends_from_active_record?
31
- stored_class = @model.store_full_sti_class ? @model.name : @model.name.demodulize
32
- @conditions << "#{@model.quoted_table_name}.#{quote_column(@model.inheritance_column)} = '#{stored_class}'"
33
- end
34
-
35
- add_internal_attributes_and_facets
36
- end
37
-
38
- def name
39
- index.name
40
- end
41
-
42
- def to_riddle_for_core(offset, position)
43
- source = Riddle::Configuration::SQLSource.new(
44
- "#{index.core_name}_#{position}", adapter.sphinx_identifier
45
- )
46
-
47
- set_source_database_settings source
48
- set_source_fields source
49
- set_source_attributes source, offset
50
- set_source_settings source
51
- set_source_sql source, offset
52
-
53
- source
54
- end
55
-
56
- def to_riddle_for_delta(offset, position)
57
- source = Riddle::Configuration::SQLSource.new(
58
- "#{index.delta_name}_#{position}", adapter.sphinx_identifier
59
- )
60
- source.parent = "#{index.core_name}_#{position}"
61
-
62
- set_source_database_settings source
63
- set_source_fields source
64
- set_source_attributes source, offset, true
65
- set_source_settings source
66
- set_source_sql source, offset, true
67
-
68
- source
69
- end
70
-
71
- def delta?
72
- !@index.delta_object.nil?
73
- end
74
-
75
- # Gets the association stack for a specific key.
76
- #
77
- def association(key)
78
- @associations[key] ||= Association.children(@model, key)
79
- end
80
-
81
- private
82
-
83
- def adapter
84
- @adapter ||= @model.sphinx_database_adapter
85
- end
86
-
87
- def available_attributes
88
- attributes.select { |attrib| attrib.available? }
89
- end
90
-
91
- def set_source_database_settings(source)
92
- config = @database_configuration
93
-
94
- source.sql_host = config[:host] || "localhost"
95
- source.sql_user = config[:username] || config[:user] || 'root'
96
- source.sql_pass = (config[:password].to_s || "").gsub('#', '\#')
97
- source.sql_db = config[:database]
98
- source.sql_port = config[:port]
99
- source.sql_sock = config[:socket]
100
- end
101
-
102
- def set_source_fields(source)
103
- fields.each do |field|
104
- source.sql_file_field << field.unique_name if field.file?
105
- source.sql_field_string << field.unique_name if field.with_attribute?
106
- source.sql_field_str2wordcount << field.unique_name if field.with_wordcount?
107
- end
108
- end
109
-
110
- def set_source_attributes(source, offset, delta = false)
111
- available_attributes.each do |attrib|
112
- source.send(attrib.type_to_config) << attrib.config_value(offset, delta)
113
- end
114
- end
115
-
116
- def set_source_sql(source, offset, delta = false)
117
- source.sql_query = to_sql(:offset => offset, :delta => delta).gsub(/\n/, ' ')
118
- source.sql_query_range = to_sql_query_range(:delta => delta)
119
- source.sql_query_info = to_sql_query_info(offset)
120
-
121
- source.sql_query_pre += send(!delta ? :sql_query_pre_for_core : :sql_query_pre_for_delta)
122
-
123
- if @index.local_options[:group_concat_max_len]
124
- source.sql_query_pre << "SET SESSION group_concat_max_len = #{@index.local_options[:group_concat_max_len]}"
125
- end
126
-
127
- source.sql_query_pre += [adapter.utf8_query_pre].compact if utf8?
128
- source.sql_query_pre << adapter.utc_query_pre
129
- end
130
-
131
- def set_source_settings(source)
132
- config = ThinkingSphinx::Configuration.instance
133
- config.source_options.each do |key, value|
134
- source.send("#{key}=".to_sym, value)
135
- end
136
-
137
- source_options = ThinkingSphinx::Configuration::SourceOptions
138
- @options.each do |key, value|
139
- if source_options.include?(key.to_s) && !value.nil?
140
- source.send("#{key}=".to_sym, value)
141
- end
142
- end
143
- end
144
-
145
- # Returns all associations used amongst all the fields and attributes.
146
- # This includes all associations between the model and what the actual
147
- # columns are from.
148
- #
149
- def all_associations
150
- @all_associations ||= (
151
- # field associations
152
- @fields.collect { |field|
153
- field.associations.values
154
- }.flatten +
155
- # attribute associations
156
- @attributes.collect { |attrib|
157
- attrib.associations.values if attrib.include_as_association?
158
- }.compact.flatten +
159
- # explicit joins
160
- @joins.collect { |join|
161
- join.associations
162
- }.flatten
163
- ).uniq.collect { |assoc|
164
- # get ancestors as well as column-level associations
165
- assoc.ancestors
166
- }.flatten.uniq
167
- end
168
-
169
- def utf8?
170
- @index.options[:charset_type] =~ /utf-8|zh_cn.utf-8/
171
- end
172
-
173
- def join_dependency_class
174
- if rails_3_1?
175
- ::ActiveRecord::Associations::JoinDependency
176
- else
177
- ::ActiveRecord::Associations::ClassMethods::JoinDependency
178
- end
179
- end
180
-
181
- def initial_joins
182
- if rails_3_1?
183
- []
184
- else
185
- nil
186
- end
187
- end
188
-
189
- def rails_3_1?
190
- ::ActiveRecord::Associations.constants.include?(:JoinDependency) ||
191
- ::ActiveRecord::Associations.constants.include?('JoinDependency')
192
- end
193
- end
194
- end