thinking-sphinx 1.2.13 → 1.4.0

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 (204) hide show
  1. data/README.textile +37 -4
  2. data/VERSION +1 -0
  3. data/features/abstract_inheritance.feature +10 -0
  4. data/features/alternate_primary_key.feature +1 -1
  5. data/features/attribute_updates.feature +49 -5
  6. data/features/deleting_instances.feature +3 -0
  7. data/features/excerpts.feature +8 -0
  8. data/features/facets.feature +15 -1
  9. data/features/facets_across_model.feature +2 -2
  10. data/features/field_sorting.feature +18 -0
  11. data/features/handling_edits.feature +1 -1
  12. data/features/searching_across_models.feature +2 -2
  13. data/features/searching_by_index.feature +40 -0
  14. data/features/searching_by_model.feature +1 -8
  15. data/features/sphinx_scopes.feature +33 -0
  16. data/features/step_definitions/alpha_steps.rb +14 -1
  17. data/features/step_definitions/beta_steps.rb +1 -1
  18. data/features/step_definitions/common_steps.rb +21 -2
  19. data/features/step_definitions/facet_steps.rb +4 -0
  20. data/features/step_definitions/scope_steps.rb +8 -0
  21. data/features/step_definitions/search_steps.rb +5 -0
  22. data/features/step_definitions/sphinx_steps.rb +8 -4
  23. data/features/sti_searching.feature +5 -0
  24. data/features/support/env.rb +7 -6
  25. data/features/{support → thinking_sphinx}/db/fixtures/betas.rb +1 -0
  26. data/features/{support → thinking_sphinx}/db/fixtures/comments.rb +1 -1
  27. data/features/{support → thinking_sphinx}/db/fixtures/developers.rb +2 -0
  28. data/features/thinking_sphinx/db/fixtures/foxes.rb +3 -0
  29. data/features/thinking_sphinx/db/fixtures/music.rb +4 -0
  30. data/features/{support → thinking_sphinx}/db/fixtures/people.rb +1 -1
  31. data/features/{support → thinking_sphinx}/db/fixtures/tags.rb +1 -1
  32. data/features/{support → thinking_sphinx}/db/migrations/create_alphas.rb +1 -0
  33. data/features/{support → thinking_sphinx}/db/migrations/create_developers.rb +0 -2
  34. data/features/thinking_sphinx/db/migrations/create_genres.rb +3 -0
  35. data/features/thinking_sphinx/db/migrations/create_music.rb +6 -0
  36. data/features/thinking_sphinx/models/alpha.rb +23 -0
  37. data/features/thinking_sphinx/models/andrew.rb +17 -0
  38. data/features/{support → thinking_sphinx}/models/beta.rb +1 -1
  39. data/features/{support → thinking_sphinx}/models/developer.rb +2 -2
  40. data/features/{support → thinking_sphinx}/models/extensible_beta.rb +1 -1
  41. data/features/thinking_sphinx/models/fox.rb +5 -0
  42. data/features/thinking_sphinx/models/genre.rb +3 -0
  43. data/features/thinking_sphinx/models/medium.rb +5 -0
  44. data/features/thinking_sphinx/models/music.rb +8 -0
  45. data/features/{support → thinking_sphinx}/models/person.rb +2 -1
  46. data/features/{support → thinking_sphinx}/models/post.rb +2 -1
  47. data/lib/cucumber/thinking_sphinx/external_world.rb +12 -0
  48. data/lib/cucumber/thinking_sphinx/internal_world.rb +13 -11
  49. data/lib/thinking_sphinx/active_record/attribute_updates.rb +17 -15
  50. data/lib/thinking_sphinx/active_record/delta.rb +0 -26
  51. data/lib/thinking_sphinx/active_record/has_many_association.rb +34 -11
  52. data/lib/thinking_sphinx/active_record/scopes.rb +46 -3
  53. data/lib/thinking_sphinx/active_record.rb +271 -193
  54. data/lib/thinking_sphinx/adapters/abstract_adapter.rb +45 -9
  55. data/lib/thinking_sphinx/adapters/mysql_adapter.rb +5 -1
  56. data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +9 -1
  57. data/lib/thinking_sphinx/attribute.rb +67 -23
  58. data/lib/thinking_sphinx/auto_version.rb +24 -0
  59. data/lib/thinking_sphinx/bundled_search.rb +44 -0
  60. data/lib/thinking_sphinx/class_facet.rb +3 -2
  61. data/lib/thinking_sphinx/configuration.rb +78 -64
  62. data/lib/thinking_sphinx/context.rb +76 -0
  63. data/lib/thinking_sphinx/deltas/default_delta.rb +14 -20
  64. data/lib/thinking_sphinx/deltas.rb +0 -2
  65. data/lib/thinking_sphinx/deploy/capistrano.rb +1 -1
  66. data/lib/thinking_sphinx/excerpter.rb +1 -1
  67. data/lib/thinking_sphinx/facet.rb +6 -5
  68. data/lib/thinking_sphinx/facet_search.rb +54 -24
  69. data/lib/thinking_sphinx/field.rb +2 -4
  70. data/lib/thinking_sphinx/index/builder.rb +36 -20
  71. data/lib/thinking_sphinx/index/faux_column.rb +8 -0
  72. data/lib/thinking_sphinx/index.rb +77 -19
  73. data/lib/thinking_sphinx/join.rb +37 -0
  74. data/lib/thinking_sphinx/property.rb +9 -2
  75. data/lib/thinking_sphinx/rails_additions.rb +4 -4
  76. data/lib/thinking_sphinx/search.rb +212 -66
  77. data/lib/thinking_sphinx/search_methods.rb +22 -4
  78. data/lib/thinking_sphinx/source/internal_properties.rb +2 -2
  79. data/lib/thinking_sphinx/source/sql.rb +5 -3
  80. data/lib/thinking_sphinx/source.rb +21 -12
  81. data/lib/thinking_sphinx/tasks.rb +26 -58
  82. data/lib/thinking_sphinx/test.rb +55 -0
  83. data/lib/thinking_sphinx.rb +70 -38
  84. data/rails/init.rb +4 -2
  85. data/spec/{lib/thinking_sphinx → thinking_sphinx}/active_record/delta_spec.rb +6 -8
  86. data/spec/{lib/thinking_sphinx → thinking_sphinx}/active_record/has_many_association_spec.rb +26 -3
  87. data/spec/thinking_sphinx/active_record/scopes_spec.rb +176 -0
  88. data/spec/thinking_sphinx/active_record_spec.rb +618 -0
  89. data/spec/thinking_sphinx/adapters/abstract_adapter_spec.rb +134 -0
  90. data/spec/{lib/thinking_sphinx → thinking_sphinx}/association_spec.rb +1 -1
  91. data/spec/{lib/thinking_sphinx → thinking_sphinx}/attribute_spec.rb +87 -46
  92. data/spec/thinking_sphinx/auto_version_spec.rb +47 -0
  93. data/spec/{lib/thinking_sphinx → thinking_sphinx}/configuration_spec.rb +73 -63
  94. data/spec/thinking_sphinx/context_spec.rb +127 -0
  95. data/spec/{lib/thinking_sphinx → thinking_sphinx}/core/array_spec.rb +1 -1
  96. data/spec/{lib/thinking_sphinx → thinking_sphinx}/core/string_spec.rb +1 -1
  97. data/spec/{lib/thinking_sphinx → thinking_sphinx}/excerpter_spec.rb +1 -9
  98. data/spec/{lib/thinking_sphinx → thinking_sphinx}/facet_search_spec.rb +76 -82
  99. data/spec/{lib/thinking_sphinx → thinking_sphinx}/facet_spec.rb +5 -5
  100. data/spec/{lib/thinking_sphinx → thinking_sphinx}/field_spec.rb +1 -42
  101. data/spec/{lib/thinking_sphinx → thinking_sphinx}/index/builder_spec.rb +71 -31
  102. data/spec/{lib/thinking_sphinx → thinking_sphinx}/index/faux_column_spec.rb +8 -2
  103. data/spec/thinking_sphinx/index_spec.rb +183 -0
  104. data/spec/{lib/thinking_sphinx → thinking_sphinx}/rails_additions_spec.rb +5 -5
  105. data/spec/{lib/thinking_sphinx → thinking_sphinx}/search_methods_spec.rb +5 -1
  106. data/spec/{lib/thinking_sphinx → thinking_sphinx}/search_spec.rb +183 -31
  107. data/spec/{lib/thinking_sphinx → thinking_sphinx}/source_spec.rb +18 -2
  108. data/spec/thinking_sphinx/test_spec.rb +20 -0
  109. data/spec/thinking_sphinx_spec.rb +204 -0
  110. data/tasks/distribution.rb +7 -26
  111. data/tasks/testing.rb +32 -20
  112. metadata +488 -147
  113. data/VERSION.yml +0 -5
  114. data/features/datetime_deltas.feature +0 -66
  115. data/features/delayed_delta_indexing.feature +0 -37
  116. data/features/step_definitions/datetime_delta_steps.rb +0 -15
  117. data/features/step_definitions/delayed_delta_indexing_steps.rb +0 -7
  118. data/features/support/database.yml +0 -5
  119. data/features/support/db/active_record.rb +0 -40
  120. data/features/support/db/database.yml +0 -5
  121. data/features/support/db/fixtures/delayed_betas.rb +0 -10
  122. data/features/support/db/fixtures/thetas.rb +0 -10
  123. data/features/support/db/migrations/create_delayed_betas.rb +0 -17
  124. data/features/support/db/migrations/create_thetas.rb +0 -5
  125. data/features/support/db/mysql.rb +0 -3
  126. data/features/support/db/postgresql.rb +0 -3
  127. data/features/support/models/alpha.rb +0 -10
  128. data/features/support/models/delayed_beta.rb +0 -7
  129. data/features/support/models/theta.rb +0 -7
  130. data/features/support/post_database.rb +0 -43
  131. data/lib/thinking_sphinx/deltas/datetime_delta.rb +0 -50
  132. data/lib/thinking_sphinx/deltas/delayed_delta/delta_job.rb +0 -24
  133. data/lib/thinking_sphinx/deltas/delayed_delta/flag_as_deleted_job.rb +0 -27
  134. data/lib/thinking_sphinx/deltas/delayed_delta/job.rb +0 -26
  135. data/lib/thinking_sphinx/deltas/delayed_delta.rb +0 -30
  136. data/spec/lib/thinking_sphinx/active_record/scopes_spec.rb +0 -96
  137. data/spec/lib/thinking_sphinx/active_record_spec.rb +0 -353
  138. data/spec/lib/thinking_sphinx/deltas/job_spec.rb +0 -32
  139. data/spec/lib/thinking_sphinx/index_spec.rb +0 -45
  140. data/spec/lib/thinking_sphinx_spec.rb +0 -162
  141. data/vendor/after_commit/LICENSE +0 -20
  142. data/vendor/after_commit/README +0 -16
  143. data/vendor/after_commit/Rakefile +0 -22
  144. data/vendor/after_commit/init.rb +0 -8
  145. data/vendor/after_commit/lib/after_commit/active_record.rb +0 -114
  146. data/vendor/after_commit/lib/after_commit/connection_adapters.rb +0 -103
  147. data/vendor/after_commit/lib/after_commit.rb +0 -45
  148. data/vendor/after_commit/test/after_commit_test.rb +0 -53
  149. data/vendor/delayed_job/lib/delayed/job.rb +0 -251
  150. data/vendor/delayed_job/lib/delayed/message_sending.rb +0 -7
  151. data/vendor/delayed_job/lib/delayed/performable_method.rb +0 -55
  152. data/vendor/delayed_job/lib/delayed/worker.rb +0 -54
  153. data/vendor/riddle/lib/riddle/client/filter.rb +0 -53
  154. data/vendor/riddle/lib/riddle/client/message.rb +0 -66
  155. data/vendor/riddle/lib/riddle/client/response.rb +0 -84
  156. data/vendor/riddle/lib/riddle/client.rb +0 -635
  157. data/vendor/riddle/lib/riddle/configuration/distributed_index.rb +0 -48
  158. data/vendor/riddle/lib/riddle/configuration/index.rb +0 -142
  159. data/vendor/riddle/lib/riddle/configuration/indexer.rb +0 -19
  160. data/vendor/riddle/lib/riddle/configuration/remote_index.rb +0 -17
  161. data/vendor/riddle/lib/riddle/configuration/searchd.rb +0 -25
  162. data/vendor/riddle/lib/riddle/configuration/section.rb +0 -43
  163. data/vendor/riddle/lib/riddle/configuration/source.rb +0 -23
  164. data/vendor/riddle/lib/riddle/configuration/sql_source.rb +0 -34
  165. data/vendor/riddle/lib/riddle/configuration/xml_source.rb +0 -28
  166. data/vendor/riddle/lib/riddle/configuration.rb +0 -33
  167. data/vendor/riddle/lib/riddle/controller.rb +0 -53
  168. data/vendor/riddle/lib/riddle.rb +0 -30
  169. data/features/{support → thinking_sphinx}/database.example.yml +0 -0
  170. data/features/{support → thinking_sphinx}/db/fixtures/alphas.rb +0 -0
  171. data/features/{support → thinking_sphinx}/db/fixtures/authors.rb +0 -0
  172. data/features/{support → thinking_sphinx}/db/fixtures/boxes.rb +0 -0
  173. data/features/{support → thinking_sphinx}/db/fixtures/categories.rb +0 -0
  174. data/features/{support → thinking_sphinx}/db/fixtures/cats.rb +0 -0
  175. data/features/{support → thinking_sphinx}/db/fixtures/dogs.rb +0 -0
  176. data/features/{support → thinking_sphinx}/db/fixtures/extensible_betas.rb +0 -0
  177. data/features/{support → thinking_sphinx}/db/fixtures/gammas.rb +0 -0
  178. data/features/{support → thinking_sphinx}/db/fixtures/posts.rb +0 -0
  179. data/features/{support → thinking_sphinx}/db/fixtures/robots.rb +0 -0
  180. data/features/{support → thinking_sphinx}/db/migrations/create_animals.rb +0 -0
  181. data/features/{support → thinking_sphinx}/db/migrations/create_authors.rb +0 -0
  182. data/features/{support → thinking_sphinx}/db/migrations/create_authors_posts.rb +0 -0
  183. data/features/{support → thinking_sphinx}/db/migrations/create_betas.rb +0 -0
  184. data/features/{support → thinking_sphinx}/db/migrations/create_boxes.rb +0 -0
  185. data/features/{support → thinking_sphinx}/db/migrations/create_categories.rb +0 -0
  186. data/features/{support → thinking_sphinx}/db/migrations/create_comments.rb +0 -0
  187. data/features/{support → thinking_sphinx}/db/migrations/create_extensible_betas.rb +0 -0
  188. data/features/{support → thinking_sphinx}/db/migrations/create_gammas.rb +0 -0
  189. data/features/{support → thinking_sphinx}/db/migrations/create_people.rb +0 -0
  190. data/features/{support → thinking_sphinx}/db/migrations/create_posts.rb +0 -0
  191. data/features/{support → thinking_sphinx}/db/migrations/create_robots.rb +0 -0
  192. data/features/{support → thinking_sphinx}/db/migrations/create_taggings.rb +0 -0
  193. data/features/{support → thinking_sphinx}/db/migrations/create_tags.rb +0 -0
  194. data/features/{support → thinking_sphinx}/models/animal.rb +0 -0
  195. data/features/{support → thinking_sphinx}/models/author.rb +0 -0
  196. data/features/{support → thinking_sphinx}/models/box.rb +0 -0
  197. data/features/{support → thinking_sphinx}/models/cat.rb +0 -0
  198. data/features/{support → thinking_sphinx}/models/category.rb +0 -0
  199. data/features/{support → thinking_sphinx}/models/comment.rb +3 -3
  200. /data/features/{support → thinking_sphinx}/models/dog.rb +0 -0
  201. /data/features/{support → thinking_sphinx}/models/gamma.rb +0 -0
  202. /data/features/{support → thinking_sphinx}/models/robot.rb +0 -0
  203. /data/features/{support → thinking_sphinx}/models/tag.rb +0 -0
  204. /data/features/{support → thinking_sphinx}/models/tagging.rb +0 -0
@@ -0,0 +1,23 @@
1
+ class Alpha < ActiveRecord::Base
2
+ define_index do
3
+ indexes :name, :sortable => true
4
+
5
+ has value, created_at, created_on
6
+ has cost, :facet => true
7
+ has active
8
+
9
+ set_property :field_weights => {"name" => 10}
10
+ end
11
+
12
+ define_index 'alternative' do
13
+ indexes :name, :as => :alternative_name, :sortable => true
14
+
15
+ has value, created_at, created_on
16
+ has cost, :facet => true
17
+ has active
18
+
19
+ set_property :field_weights => {'alternative_name' => 10}
20
+
21
+ where "value > 3"
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ require "#{File.dirname(__FILE__)}/person"
2
+
3
+ class Andrew < ActiveRecord::Base
4
+ set_table_name 'people'
5
+
6
+ define_index do
7
+ indexes first_name, last_name, street_address
8
+ end
9
+
10
+ sphinx_scope(:locked_first_name) {
11
+ {:conditions => {:first_name => 'Andrew'}}
12
+ }
13
+ sphinx_scope(:locked_last_name) {
14
+ {:conditions => {:last_name => 'Byrne'}}
15
+ }
16
+ default_sphinx_scope :locked_first_name
17
+ end
@@ -1,6 +1,6 @@
1
1
  class Beta < ActiveRecord::Base
2
2
  define_index do
3
- indexes :name, :sortable => true
3
+ indexes :name, :sortable => true, :facet => true
4
4
  has value
5
5
 
6
6
  set_property :delta => true
@@ -1,5 +1,5 @@
1
- require 'features/support/models/tag'
2
- require 'features/support/models/tagging'
1
+ require "#{File.dirname(__FILE__)}/tag"
2
+ require "#{File.dirname(__FILE__)}/tagging"
3
3
 
4
4
  class Developer < ActiveRecord::Base
5
5
  has_many :taggings, :as => :taggable
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), "..", "lib", "generic_delta_handler")
1
+ require "#{Dir.pwd}/features/support/lib/generic_delta_handler"
2
2
 
3
3
  class ExtensibleBeta < ActiveRecord::Base
4
4
  define_index do
@@ -0,0 +1,5 @@
1
+ class Fox < Animal
2
+ define_index do
3
+ indexes :name
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ class Genre < ActiveRecord::Base
2
+ #
3
+ end
@@ -0,0 +1,5 @@
1
+ class Medium < ActiveRecord::Base
2
+ self.abstract_class = true
3
+
4
+ belongs_to :genre
5
+ end
@@ -0,0 +1,8 @@
1
+ class Music < Medium
2
+ set_table_name 'music'
3
+
4
+ define_index do
5
+ indexes artist, track, album
6
+ indexes genre(:name), :as => :genre
7
+ end
8
+ end
@@ -1,6 +1,7 @@
1
1
  class Person < ActiveRecord::Base
2
2
  define_index do
3
- indexes first_name, last_name, :sortable => true
3
+ indexes first_name, :sortable => true
4
+ indexes last_name, :sortable => :insensitive
4
5
 
5
6
  has [first_name, middle_initial, last_name], :as => :name_sort
6
7
  has birthday
@@ -12,7 +12,8 @@ class Post < ActiveRecord::Base
12
12
  indexes comments.content, :as => :comments
13
13
  indexes authors.name, :as => :authors
14
14
 
15
- has comments(:id), :as => :comment_ids, :source => :ranged_query
15
+ has comments(:id), :as => :comment_ids, :source => :ranged_query,
16
+ :facet => true
16
17
  has category.name, :facet => true, :as => :category_name, :type => :string
17
18
  has 'COUNT(DISTINCT comments.id)', :as => :comments_count, :type => :integer
18
19
  has comments.created_at, :as => :comments_created_at
@@ -0,0 +1,12 @@
1
+ require 'thinking_sphinx/test'
2
+
3
+ module Cucumber
4
+ module ThinkingSphinx
5
+ class ExternalWorld
6
+ def initialize(suppress_delta_output = true)
7
+ ::ThinkingSphinx::Test.init
8
+ ::ThinkingSphinx::Test.start_with_autostop
9
+ end
10
+ end
11
+ end
12
+ end
@@ -9,11 +9,12 @@ module Cucumber
9
9
  :password, :host
10
10
 
11
11
  def initialize
12
- @temporary_directory = "#{Dir.pwd}/tmp"
13
- @migrations_directory = "features/support/db/migrations"
14
- @models_directory = "features/support/models"
15
- @fixtures_directory = "features/support/db/fixtures"
16
- @database_file = "features/support/database.yml"
12
+ pwd = Dir.pwd
13
+ @temporary_directory = "#{pwd}/tmp"
14
+ @migrations_directory = "#{pwd}/features/thinking_sphinx/db/migrations"
15
+ @models_directory = "#{pwd}/features/thinking_sphinx/models"
16
+ @fixtures_directory = "#{pwd}/features/thinking_sphinx/db/fixtures"
17
+ @database_file = "#{pwd}/features/thinking_sphinx/database.yml"
17
18
 
18
19
  @adapter = ENV['DATABASE'] || 'mysql'
19
20
  @database = 'thinking_sphinx'
@@ -79,11 +80,11 @@ module Cucumber
79
80
 
80
81
  def database_settings
81
82
  {
82
- :adapter => @adapter,
83
- :database => @database,
84
- :username => @username,
85
- :password => @password,
86
- :host => @host
83
+ 'adapter' => @adapter,
84
+ 'database' => @database,
85
+ 'username' => @username,
86
+ 'password' => @password,
87
+ 'host' => @host
87
88
  }.merge yaml_database_settings
88
89
  end
89
90
 
@@ -108,7 +109,8 @@ module Cucumber
108
109
  end
109
110
 
110
111
  def load_files(path)
111
- Dir["#{path}/*.rb"].each do |file|
112
+ files = Dir["#{path}/*.rb"].sort!
113
+ files.each do |file|
112
114
  require file.gsub(/\.rb$/, '')
113
115
  end
114
116
  end
@@ -10,22 +10,22 @@ module ThinkingSphinx
10
10
  private
11
11
 
12
12
  def update_attribute_values
13
- return unless ThinkingSphinx.updates_enabled? && ThinkingSphinx.sphinx_running?
13
+ return true unless ThinkingSphinx.updates_enabled? &&
14
+ ThinkingSphinx.sphinx_running?
14
15
 
15
- config = ThinkingSphinx::Configuration.instance
16
- client = Riddle::Client.new config.address, config.port
17
-
18
- self.sphinx_indexes.each do |index|
16
+ self.class.sphinx_indexes.each do |index|
19
17
  attribute_pairs = attribute_values_for_index(index)
20
18
  attribute_names = attribute_pairs.keys
21
19
  attribute_values = attribute_names.collect { |key|
22
20
  attribute_pairs[key]
23
21
  }
24
22
 
25
- client.update "#{index.name}_core", attribute_names, {
26
- sphinx_document_id => attribute_values
27
- } if in_core_index?
23
+ update_index index.core_name, attribute_names, attribute_values
24
+ next unless index.delta?
25
+ update_index index.delta_name, attribute_names, attribute_values
28
26
  end
27
+
28
+ true
29
29
  end
30
30
 
31
31
  def updatable_attributes(index)
@@ -34,15 +34,17 @@ module ThinkingSphinx
34
34
 
35
35
  def attribute_values_for_index(index)
36
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
-
37
+ hash[attrib.unique_name.to_s] = attrib.live_value self
43
38
  hash
44
39
  }
45
40
  end
41
+
42
+ def update_index(index_name, attribute_names, attribute_values)
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)
47
+ end
46
48
  end
47
49
  end
48
- end
50
+ end
@@ -12,32 +12,6 @@ module ThinkingSphinx
12
12
  def self.included(base)
13
13
  base.class_eval do
14
14
  class << self
15
- # Temporarily disable delta indexing inside a block, then perform a single
16
- # rebuild of index at the end.
17
- #
18
- # Useful when performing updates to batches of models to prevent
19
- # the delta index being rebuilt after each individual update.
20
- #
21
- # In the following example, the delta index will only be rebuilt once,
22
- # not 10 times.
23
- #
24
- # SomeModel.suspended_delta do
25
- # 10.times do
26
- # SomeModel.create( ... )
27
- # end
28
- # end
29
- #
30
- def suspended_delta(reindex_after = true, &block)
31
- original_setting = ThinkingSphinx.deltas_enabled?
32
- ThinkingSphinx.deltas_enabled = false
33
- begin
34
- yield
35
- ensure
36
- ThinkingSphinx.deltas_enabled = original_setting
37
- self.index_delta if reindex_after
38
- end
39
- end
40
-
41
15
  # Build the delta index for the related model. This won't be called
42
16
  # if running in the test environment.
43
17
  #
@@ -2,27 +2,50 @@ module ThinkingSphinx
2
2
  module ActiveRecord
3
3
  module HasManyAssociation
4
4
  def search(*args)
5
+ options = args.extract_options!
6
+ options[:with] ||= {}
7
+ options[:with].merge! default_filter
8
+
9
+ args << options
10
+ @reflection.klass.search(*args)
11
+ end
12
+
13
+ def method_missing(method, *args, &block)
14
+ if responds_to_scope(method)
15
+ @reflection.klass.
16
+ search(:with => default_filter).
17
+ send(method, *args, &block)
18
+ else
19
+ super
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def attribute_for_foreign_key
5
26
  foreign_key = @reflection.primary_key_name
6
27
  stack = [@reflection.options[:through]].compact
7
28
 
8
- attribute = nil
29
+ @reflection.klass.define_indexes
9
30
  (@reflection.klass.sphinx_indexes || []).each do |index|
10
31
  attribute = index.attributes.detect { |attrib|
11
32
  attrib.columns.length == 1 &&
12
33
  attrib.columns.first.__name == foreign_key.to_sym
13
34
  }
14
- break if attribute
35
+ return attribute unless attribute.nil?
15
36
  end
16
37
 
17
- raise "Missing Attribute for Foreign Key #{foreign_key}" unless attribute
18
-
19
- options = args.extract_options!
20
- options[:with] ||= {}
21
- options[:with][attribute.unique_name] = @owner.id
22
-
23
- args << options
24
- @reflection.klass.search(*args)
38
+ raise "Missing Attribute for Foreign Key #{foreign_key}"
39
+ end
40
+
41
+ def default_filter
42
+ {attribute_for_foreign_key.unique_name => @owner.id}
43
+ end
44
+
45
+ def responds_to_scope(scope)
46
+ @reflection.klass.respond_to?(:sphinx_scopes) &&
47
+ @reflection.klass.sphinx_scopes.include?(scope)
25
48
  end
26
49
  end
27
50
  end
28
- end
51
+ end
@@ -8,27 +8,70 @@ module ThinkingSphinx
8
8
  end
9
9
 
10
10
  module ClassMethods
11
+
12
+ # Similar to ActiveRecord's default_scope method Thinking Sphinx supports
13
+ # a default_sphinx_scope. For example:
14
+ #
15
+ # default_sphinx_scope :some_sphinx_named_scope
16
+ #
17
+ # The scope is automatically applied when the search method is called. It
18
+ # will only be applied if it is an existing sphinx_scope.
19
+ def default_sphinx_scope(sphinx_scope_name)
20
+ @default_sphinx_scope = sphinx_scope_name
21
+ end
22
+
23
+ # Returns the default_sphinx_scope or nil if none is set.
24
+ def get_default_sphinx_scope
25
+ @default_sphinx_scope
26
+ end
27
+
28
+ # Returns true if the current Model has a default_sphinx_scope. Also checks if
29
+ # the default_sphinx_scope actually is a scope.
30
+ def has_default_sphinx_scope?
31
+ !@default_sphinx_scope.nil? && sphinx_scopes.include?(@default_sphinx_scope)
32
+ end
33
+
34
+ # Similar to ActiveRecord's named_scope method Thinking Sphinx supports
35
+ # scopes. For example:
36
+ #
37
+ # sphinx_scope(:latest_first) {
38
+ # {:order => 'created_at DESC, @relevance DESC'}
39
+ # }
40
+ #
41
+ # Usage:
42
+ #
43
+ # @articles = Article.latest_first.search 'pancakes'
44
+ #
11
45
  def sphinx_scope(method, &block)
12
46
  @sphinx_scopes ||= []
13
47
  @sphinx_scopes << method
14
48
 
15
- metaclass.instance_eval do
49
+ singleton_class.instance_eval do
16
50
  define_method(method) do |*args|
17
51
  options = {:classes => classes_option}
18
52
  options.merge! block.call(*args)
19
53
 
20
54
  ThinkingSphinx::Search.new(options)
21
55
  end
56
+
57
+ define_method("#{method}_without_default".to_sym) do |*args|
58
+ options = {:classes => classes_option, :ignore_default => true}
59
+ options.merge! block.call(*args)
60
+
61
+ ThinkingSphinx::Search.new(options)
62
+ end
22
63
  end
23
64
  end
24
-
65
+
66
+ # This returns an Array of all defined scopes. The default
67
+ # scope shows as :default.
25
68
  def sphinx_scopes
26
69
  @sphinx_scopes || []
27
70
  end
28
71
 
29
72
  def remove_sphinx_scopes
30
73
  sphinx_scopes.each do |scope|
31
- metaclass.send(:undef_method, scope)
74
+ singleton_class.send(:undef_method, scope)
32
75
  end
33
76
 
34
77
  sphinx_scopes.clear