warp-thinking-sphinx 1.2.12 → 1.3.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (144) hide show
  1. data/README.textile +21 -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 +22 -5
  6. data/features/deleting_instances.feature +3 -0
  7. data/features/facets.feature +6 -0
  8. data/features/facets_across_model.feature +2 -2
  9. data/features/searching_across_models.feature +1 -1
  10. data/features/searching_by_index.feature +40 -0
  11. data/features/sphinx_scopes.feature +7 -0
  12. data/features/step_definitions/alpha_steps.rb +14 -1
  13. data/features/step_definitions/beta_steps.rb +1 -1
  14. data/features/step_definitions/common_steps.rb +12 -2
  15. data/features/step_definitions/facet_steps.rb +5 -1
  16. data/features/step_definitions/scope_steps.rb +4 -0
  17. data/features/step_definitions/sphinx_steps.rb +8 -4
  18. data/features/sti_searching.feature +5 -0
  19. data/features/support/{db/database.example.yml → database.example.yml} +0 -0
  20. data/features/support/db/fixtures/foxes.rb +3 -0
  21. data/features/support/db/fixtures/music.rb +4 -0
  22. data/features/support/db/fixtures/robots.rb +1 -1
  23. data/features/support/db/fixtures/tags.rb +1 -1
  24. data/features/support/db/migrations/create_alphas.rb +1 -0
  25. data/features/support/db/migrations/create_genres.rb +3 -0
  26. data/features/support/db/migrations/create_music.rb +6 -0
  27. data/features/support/db/migrations/create_robots.rb +1 -2
  28. data/features/support/env.rb +16 -1
  29. data/features/support/models/alpha.rb +12 -0
  30. data/features/support/models/comment.rb +3 -3
  31. data/features/support/models/fox.rb +5 -0
  32. data/features/support/models/genre.rb +3 -0
  33. data/features/support/models/medium.rb +5 -0
  34. data/features/support/models/music.rb +8 -0
  35. data/features/support/models/post.rb +2 -1
  36. data/features/support/models/robot.rb +4 -0
  37. data/lib/cucumber/thinking_sphinx/external_world.rb +8 -0
  38. data/lib/cucumber/thinking_sphinx/internal_world.rb +126 -0
  39. data/lib/cucumber/thinking_sphinx/sql_logger.rb +20 -0
  40. data/lib/thinking_sphinx.rb +56 -37
  41. data/lib/thinking_sphinx/active_record.rb +257 -192
  42. data/lib/thinking_sphinx/active_record/attribute_updates.rb +10 -12
  43. data/lib/thinking_sphinx/active_record/delta.rb +0 -26
  44. data/lib/thinking_sphinx/active_record/scopes.rb +37 -1
  45. data/lib/thinking_sphinx/adapters/mysql_adapter.rb +1 -1
  46. data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +18 -11
  47. data/lib/thinking_sphinx/attribute.rb +19 -4
  48. data/lib/thinking_sphinx/auto_version.rb +22 -0
  49. data/lib/thinking_sphinx/configuration.rb +57 -59
  50. data/lib/thinking_sphinx/context.rb +74 -0
  51. data/lib/thinking_sphinx/deltas.rb +0 -2
  52. data/lib/thinking_sphinx/deltas/default_delta.rb +14 -20
  53. data/lib/thinking_sphinx/deploy/capistrano.rb +1 -1
  54. data/lib/thinking_sphinx/facet_search.rb +3 -1
  55. data/lib/thinking_sphinx/index.rb +77 -19
  56. data/lib/thinking_sphinx/index/builder.rb +2 -2
  57. data/lib/thinking_sphinx/search.rb +47 -9
  58. data/lib/thinking_sphinx/search_methods.rb +22 -4
  59. data/lib/thinking_sphinx/source.rb +9 -8
  60. data/lib/thinking_sphinx/source/sql.rb +5 -3
  61. data/lib/thinking_sphinx/tasks.rb +13 -57
  62. data/lib/thinking_sphinx/test.rb +52 -0
  63. data/rails/init.rb +4 -2
  64. data/spec/{lib/thinking_sphinx → thinking_sphinx}/active_record/delta_spec.rb +4 -6
  65. data/spec/{lib/thinking_sphinx → thinking_sphinx}/active_record/has_many_association_spec.rb +0 -0
  66. data/spec/thinking_sphinx/active_record/scopes_spec.rb +177 -0
  67. data/spec/thinking_sphinx/active_record_spec.rb +622 -0
  68. data/spec/{lib/thinking_sphinx → thinking_sphinx}/association_spec.rb +0 -0
  69. data/spec/{lib/thinking_sphinx → thinking_sphinx}/attribute_spec.rb +39 -0
  70. data/spec/thinking_sphinx/auto_version_spec.rb +39 -0
  71. data/spec/{lib/thinking_sphinx → thinking_sphinx}/configuration_spec.rb +27 -61
  72. data/spec/thinking_sphinx/context_spec.rb +119 -0
  73. data/spec/{lib/thinking_sphinx → thinking_sphinx}/core/array_spec.rb +0 -0
  74. data/spec/{lib/thinking_sphinx → thinking_sphinx}/core/string_spec.rb +0 -0
  75. data/spec/{lib/thinking_sphinx → thinking_sphinx}/excerpter_spec.rb +0 -0
  76. data/spec/{lib/thinking_sphinx → thinking_sphinx}/facet_search_spec.rb +0 -0
  77. data/spec/{lib/thinking_sphinx → thinking_sphinx}/facet_spec.rb +0 -0
  78. data/spec/{lib/thinking_sphinx → thinking_sphinx}/field_spec.rb +0 -0
  79. data/spec/{lib/thinking_sphinx → thinking_sphinx}/index/builder_spec.rb +24 -0
  80. data/spec/{lib/thinking_sphinx → thinking_sphinx}/index/faux_column_spec.rb +0 -0
  81. data/spec/thinking_sphinx/index_spec.rb +183 -0
  82. data/spec/{lib/thinking_sphinx → thinking_sphinx}/rails_additions_spec.rb +0 -0
  83. data/spec/{lib/thinking_sphinx → thinking_sphinx}/search_methods_spec.rb +0 -0
  84. data/spec/{lib/thinking_sphinx → thinking_sphinx}/search_spec.rb +41 -0
  85. data/spec/{lib/thinking_sphinx → thinking_sphinx}/source_spec.rb +1 -1
  86. data/spec/thinking_sphinx_spec.rb +204 -0
  87. data/tasks/distribution.rb +6 -20
  88. data/tasks/testing.rb +8 -19
  89. metadata +117 -142
  90. data/VERSION.yml +0 -4
  91. data/features/a.rb +0 -17
  92. data/features/datetime_deltas.feature +0 -66
  93. data/features/delayed_delta_indexing.feature +0 -37
  94. data/features/step_definitions/datetime_delta_steps.rb +0 -15
  95. data/features/step_definitions/delayed_delta_indexing_steps.rb +0 -7
  96. data/features/support/db/active_record.rb +0 -40
  97. data/features/support/db/fixtures/delayed_betas.rb +0 -10
  98. data/features/support/db/fixtures/thetas.rb +0 -10
  99. data/features/support/db/migrations/create_delayed_betas.rb +0 -17
  100. data/features/support/db/migrations/create_thetas.rb +0 -5
  101. data/features/support/db/mysql.rb +0 -3
  102. data/features/support/db/postgresql.rb +0 -3
  103. data/features/support/models/delayed_beta.rb +0 -7
  104. data/features/support/models/theta.rb +0 -7
  105. data/features/support/post_database.rb +0 -43
  106. data/features/support/z.rb +0 -19
  107. data/lib/thinking_sphinx/deltas/datetime_delta.rb +0 -50
  108. data/lib/thinking_sphinx/deltas/delayed_delta.rb +0 -30
  109. data/lib/thinking_sphinx/deltas/delayed_delta/delta_job.rb +0 -24
  110. data/lib/thinking_sphinx/deltas/delayed_delta/flag_as_deleted_job.rb +0 -27
  111. data/lib/thinking_sphinx/deltas/delayed_delta/job.rb +0 -26
  112. data/spec/lib/thinking_sphinx/active_record/scopes_spec.rb +0 -96
  113. data/spec/lib/thinking_sphinx/active_record_spec.rb +0 -353
  114. data/spec/lib/thinking_sphinx/deltas/job_spec.rb +0 -32
  115. data/spec/lib/thinking_sphinx/index_spec.rb +0 -45
  116. data/spec/lib/thinking_sphinx_spec.rb +0 -162
  117. data/vendor/after_commit/LICENSE +0 -20
  118. data/vendor/after_commit/README +0 -16
  119. data/vendor/after_commit/Rakefile +0 -22
  120. data/vendor/after_commit/init.rb +0 -8
  121. data/vendor/after_commit/lib/after_commit.rb +0 -45
  122. data/vendor/after_commit/lib/after_commit/active_record.rb +0 -114
  123. data/vendor/after_commit/lib/after_commit/connection_adapters.rb +0 -103
  124. data/vendor/after_commit/test/after_commit_test.rb +0 -53
  125. data/vendor/delayed_job/lib/delayed/job.rb +0 -251
  126. data/vendor/delayed_job/lib/delayed/message_sending.rb +0 -7
  127. data/vendor/delayed_job/lib/delayed/performable_method.rb +0 -55
  128. data/vendor/delayed_job/lib/delayed/worker.rb +0 -54
  129. data/vendor/riddle/lib/riddle.rb +0 -30
  130. data/vendor/riddle/lib/riddle/client.rb +0 -635
  131. data/vendor/riddle/lib/riddle/client/filter.rb +0 -53
  132. data/vendor/riddle/lib/riddle/client/message.rb +0 -66
  133. data/vendor/riddle/lib/riddle/client/response.rb +0 -84
  134. data/vendor/riddle/lib/riddle/configuration.rb +0 -33
  135. data/vendor/riddle/lib/riddle/configuration/distributed_index.rb +0 -48
  136. data/vendor/riddle/lib/riddle/configuration/index.rb +0 -142
  137. data/vendor/riddle/lib/riddle/configuration/indexer.rb +0 -19
  138. data/vendor/riddle/lib/riddle/configuration/remote_index.rb +0 -17
  139. data/vendor/riddle/lib/riddle/configuration/searchd.rb +0 -25
  140. data/vendor/riddle/lib/riddle/configuration/section.rb +0 -43
  141. data/vendor/riddle/lib/riddle/configuration/source.rb +0 -23
  142. data/vendor/riddle/lib/riddle/configuration/sql_source.rb +0 -34
  143. data/vendor/riddle/lib/riddle/configuration/xml_source.rb +0 -28
  144. data/vendor/riddle/lib/riddle/controller.rb +0 -53
@@ -155,7 +155,7 @@ module ThinkingSphinx
155
155
  # asterisks. You need to make the config/sphinx.yml changes yourself.
156
156
  #
157
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
158
+ # /\w\+/u\+. If you've modified the charset_table, pass another regular
159
159
  # expression, e.g.
160
160
  #
161
161
  # User.search("oo@bar.c", :star => /[\w@.]+/u)
@@ -313,13 +313,31 @@ module ThinkingSphinx
313
313
  # Once you've got your results set, you can access the distances as
314
314
  # follows:
315
315
  #
316
- # @results.each_with_geodist do |result, distance|
317
- # # ...
318
- # end
316
+ # @results.each_with_geodist do |result, distance|
317
+ # # ...
318
+ # end
319
319
  #
320
320
  # The distance value is returned as a float, representing the distance in
321
321
  # metres.
322
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
+ #
323
341
  # == Handling a Stale Index
324
342
  #
325
343
  # Especially if you don't use delta indexing, you risk having records in
@@ -33,30 +33,31 @@ module ThinkingSphinx
33
33
  end
34
34
 
35
35
  def name
36
- @model.sphinx_name
36
+ index.name
37
37
  end
38
38
 
39
- def to_riddle_for_core(offset, index)
39
+ def to_riddle_for_core(offset, position)
40
40
  source = Riddle::Configuration::SQLSource.new(
41
- "#{name}_core_#{index}", adapter.sphinx_identifier
41
+ "#{index.core_name}_#{position}", adapter.sphinx_identifier
42
42
  )
43
43
 
44
44
  set_source_database_settings source
45
45
  set_source_attributes source, offset
46
- set_source_sql source, offset
47
46
  set_source_settings source
47
+ set_source_sql source, offset
48
48
 
49
49
  source
50
50
  end
51
51
 
52
- def to_riddle_for_delta(offset, index)
52
+ def to_riddle_for_delta(offset, position)
53
53
  source = Riddle::Configuration::SQLSource.new(
54
- "#{name}_delta_#{index}", adapter.sphinx_identifier
54
+ "#{index.delta_name}_#{position}", adapter.sphinx_identifier
55
55
  )
56
- source.parent = "#{name}_core_#{index}"
56
+ source.parent = "#{index.core_name}_#{position}"
57
57
 
58
58
  set_source_database_settings source
59
59
  set_source_attributes source, offset, true
60
+ set_source_settings source
60
61
  set_source_sql source, offset, true
61
62
 
62
63
  source
@@ -146,7 +147,7 @@ module ThinkingSphinx
146
147
  end
147
148
 
148
149
  def utf8?
149
- @index.options[:charset_type] == "utf-8"
150
+ @index.options[:charset_type] =~ /utf-8|zh_cn.utf-8/
150
151
  end
151
152
  end
152
153
  end
@@ -13,8 +13,10 @@ module ThinkingSphinx
13
13
  # source.to_sql(:delta => true)
14
14
  #
15
15
  def to_sql(options={})
16
- sql = <<-SQL
17
- SELECT #{ sql_select_clause options[:offset] }
16
+ sql = "SELECT "
17
+ sql += "SQL_NO_CACHE " if adapter.sphinx_identifier == "mysql"
18
+ sql += <<-SQL
19
+ #{ sql_select_clause options[:offset] }
18
20
  FROM #{ @model.quoted_table_name }
19
21
  #{ all_associations.collect { |assoc| assoc.to_sql }.join(' ') }
20
22
  #{ sql_where_clause(options) }
@@ -52,7 +54,7 @@ FROM #{ @model.quoted_table_name }
52
54
  #
53
55
  def to_sql_query_info(offset)
54
56
  "SELECT * FROM #{@model.quoted_table_name} WHERE " +
55
- "#{quote_column(@model.primary_key_for_sphinx)} = (($id - #{offset}) / #{ThinkingSphinx.indexed_models.size})"
57
+ "#{quote_column(@model.primary_key_for_sphinx)} = (($id - #{offset}) / #{ThinkingSphinx.context.indexed_models.size})"
56
58
  end
57
59
 
58
60
  def sql_select_clause(offset)
@@ -29,10 +29,8 @@ namespace :thinking_sphinx do
29
29
  raise RuntimeError, "searchd is already running." if sphinx_running?
30
30
 
31
31
  Dir["#{config.searchd_file_path}/*.spl"].each { |file| File.delete(file) }
32
-
33
- system! "#{config.bin_path}#{config.searchd_binary_name} --pidfile --config \"#{config.config_file}\""
34
32
 
35
- sleep(2)
33
+ config.controller.start
36
34
 
37
35
  if sphinx_running?
38
36
  puts "Started successfully (pid #{sphinx_pid})."
@@ -48,7 +46,7 @@ namespace :thinking_sphinx do
48
46
  else
49
47
  config = ThinkingSphinx::Configuration.instance
50
48
  pid = sphinx_pid
51
- system! "#{config.bin_path}#{config.searchd_binary_name} --stop --config \"#{config.config_file}\""
49
+ config.controller.stop
52
50
  puts "Stopped search daemon (pid #{pid})."
53
51
  end
54
52
  end
@@ -65,19 +63,21 @@ namespace :thinking_sphinx do
65
63
 
66
64
  desc "Index data for Sphinx using Thinking Sphinx's settings"
67
65
  task :index => :app_env do
68
- ThinkingSphinx::Deltas::Job.cancel_thinking_sphinx_jobs
69
-
70
66
  config = ThinkingSphinx::Configuration.instance
71
67
  unless ENV["INDEX_ONLY"] == "true"
72
68
  puts "Generating Configuration to #{config.config_file}"
73
69
  config.build
74
70
  end
75
-
76
- FileUtils.mkdir_p config.searchd_file_path
77
- cmd = "#{config.bin_path}#{config.indexer_binary_name} --config \"#{config.config_file}\" --all"
78
- cmd << " --rotate" if sphinx_running?
79
71
 
80
- system! cmd
72
+ FileUtils.mkdir_p config.searchd_file_path
73
+ config.controller.index :verbose => true
74
+ end
75
+
76
+ desc "Reindex Sphinx without regenerating the configuration file"
77
+ task :reindex => :app_env do
78
+ config = ThinkingSphinx::Configuration.instance
79
+ FileUtils.mkdir_p config.searchd_file_path
80
+ puts config.controller.index
81
81
  end
82
82
 
83
83
  desc "Stop Sphinx (if it's running), rebuild the indexes, and start Sphinx"
@@ -86,30 +86,6 @@ namespace :thinking_sphinx do
86
86
  Rake::Task["thinking_sphinx:index"].invoke
87
87
  Rake::Task["thinking_sphinx:start"].invoke
88
88
  end
89
-
90
- namespace :index do
91
- task :delta => :app_env do
92
- ThinkingSphinx.indexed_models.select { |model|
93
- model.constantize.sphinx_indexes.any? { |index| index.delta? }
94
- }.each do |model|
95
- model.constantize.sphinx_indexes.select { |index|
96
- index.delta? && index.delta_object.respond_to?(:delayed_index)
97
- }.each { |index|
98
- index.delta_object.delayed_index(index.model)
99
- }
100
- end
101
- end
102
- end
103
-
104
- desc "Process stored delta index requests"
105
- task :delayed_delta => :app_env do
106
- require 'delayed/worker'
107
-
108
- Delayed::Worker.new(
109
- :min_priority => ENV['MIN_PRIORITY'],
110
- :max_priority => ENV['MAX_PRIORITY']
111
- ).start
112
- end
113
89
  end
114
90
 
115
91
  namespace :ts do
@@ -123,11 +99,9 @@ namespace :ts do
123
99
  task :stop => "thinking_sphinx:stop"
124
100
  desc "Index data for Sphinx using Thinking Sphinx's settings"
125
101
  task :in => "thinking_sphinx:index"
126
- namespace :in do
127
- desc "Index Thinking Sphinx datetime delta indexes"
128
- task :delta => "thinking_sphinx:index:delta"
129
- end
130
102
  task :index => "thinking_sphinx:index"
103
+ desc "Reindex Sphinx without regenerating the configuration file"
104
+ task :reindex => "thinking_sphinx:reindex"
131
105
  desc "Restart Sphinx"
132
106
  task :restart => "thinking_sphinx:restart"
133
107
  desc "Generate the Sphinx configuration file using Thinking Sphinx's settings"
@@ -136,8 +110,6 @@ namespace :ts do
136
110
  task :config => "thinking_sphinx:configure"
137
111
  desc "Stop Sphinx (if it's running), rebuild the indexes, and start Sphinx"
138
112
  task :rebuild => "thinking_sphinx:rebuild"
139
- desc "Process stored delta index requests"
140
- task :dd => "thinking_sphinx:delayed_delta"
141
113
  end
142
114
 
143
115
  def sphinx_pid
@@ -147,19 +119,3 @@ end
147
119
  def sphinx_running?
148
120
  ThinkingSphinx.sphinx_running?
149
121
  end
150
-
151
- # a fail-fast, hopefully helpful version of system
152
- def system!(cmd)
153
- unless system(cmd)
154
- raise <<-SYSTEM_CALL_FAILED
155
- The following command failed:
156
- #{cmd}
157
-
158
- This could be caused by a PATH issue in the environment of cron/passenger/etc. Your current PATH:
159
- #{ENV['PATH']}
160
- You can set the path to your indexer and searchd binaries using the bin_path property in config/sphinx.yml:
161
- production:
162
- bin_path: '/usr/local/bin'
163
- SYSTEM_CALL_FAILED
164
- end
165
- end
@@ -0,0 +1,52 @@
1
+ class ThinkingSphinx::Test
2
+ def self.init(suppress_delta_output = true)
3
+ set_flags suppress_delta_output
4
+ create_indexes_folder
5
+ end
6
+
7
+ def self.start
8
+ config.build
9
+ config.controller.index
10
+ config.controller.start
11
+ end
12
+
13
+ def self.start_with_autostop
14
+ autostop
15
+ start
16
+ end
17
+
18
+ def self.stop
19
+ config.controller.stop
20
+ sleep(0.5) # Ensure Sphinx has shut down completely
21
+ end
22
+
23
+ def self.autostop
24
+ Kernel.at_exit do
25
+ ThinkingSphinx::Test.stop
26
+ end
27
+ end
28
+
29
+ def self.run(&block)
30
+ start
31
+ yield
32
+ stop
33
+ end
34
+
35
+ def self.config
36
+ @config ||= ::ThinkingSphinx::Configuration.instance
37
+ end
38
+
39
+ def self.index(*indexes)
40
+ config.controller.index *indexes
41
+ end
42
+
43
+ def self.set_flags(suppress_delta_output)
44
+ ::ThinkingSphinx.deltas_enabled = true
45
+ ::ThinkingSphinx.updates_enabled = true
46
+ ::ThinkingSphinx.suppress_delta_output = suppress_delta_output
47
+ end
48
+
49
+ def self.create_indexes_folder
50
+ FileUtils.mkdir_p config.searchd_file_path
51
+ end
52
+ end
data/rails/init.rb CHANGED
@@ -1,3 +1,7 @@
1
+ Dir[File.join(File.dirname(__FILE__), '../vendor/*/lib')].each do |path|
2
+ $LOAD_PATH.unshift path
3
+ end
4
+
1
5
  require 'thinking_sphinx'
2
6
  require 'action_controller/dispatcher'
3
7
 
@@ -9,6 +13,4 @@ ActionController::Dispatcher.to_prepare :thinking_sphinx do
9
13
  elsif Rails::VERSION::STRING.to_f > 2.1
10
14
  I18n.backend.load_translations(*I18n.load_path)
11
15
  end
12
-
13
- ThinkingSphinx::Configuration.instance.load_models
14
16
  end
@@ -73,14 +73,12 @@ describe "ThinkingSphinx::ActiveRecord::Delta" do
73
73
  Person.delta_object.stub!(:` => "", :toggled => true)
74
74
 
75
75
  @person = Person.new
76
- @person.stub!(
77
- :in_both_indexes? => false,
78
- :sphinx_document_id => 1
79
- )
76
+ Person.stub!(:search_for_id => false)
77
+ @person.stub!(:sphinx_document_id => 1)
80
78
 
81
79
  @client = Riddle::Client.new
82
80
  @client.stub!(:update => true)
83
- Riddle::Client.stub!(:new => @client)
81
+ ThinkingSphinx::Configuration.instance.stub!(:client => @client)
84
82
  end
85
83
 
86
84
  it "shouldn't index if delta indexing is disabled" do
@@ -121,7 +119,7 @@ describe "ThinkingSphinx::ActiveRecord::Delta" do
121
119
  end
122
120
 
123
121
  it "should update the deleted attribute if in the core index" do
124
- @person.stub!(:in_both_indexes? => true)
122
+ Person.stub!(:search_for_id => true)
125
123
  @client.should_receive(:update)
126
124
 
127
125
  @person.send(:index_delta)
@@ -0,0 +1,177 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe ThinkingSphinx::ActiveRecord::Scopes do
4
+ after :each do
5
+ Alpha.remove_sphinx_scopes
6
+ end
7
+
8
+ it "should be included into models with indexes" do
9
+ Alpha.included_modules.should include(ThinkingSphinx::ActiveRecord::Scopes)
10
+ end
11
+
12
+ it "should not be included into models without indexes" do
13
+ Gamma.included_modules.should_not include(
14
+ ThinkingSphinx::ActiveRecord::Scopes
15
+ )
16
+ end
17
+
18
+ describe '.sphinx_scope' do
19
+ before :each do
20
+ Alpha.sphinx_scope(:by_name) { |name| {:conditions => {:name => name}} }
21
+ end
22
+
23
+ it "should define a method on the model" do
24
+ Alpha.should respond_to(:by_name)
25
+ end
26
+ end
27
+
28
+ describe '.sphinx_scopes' do
29
+ before :each do
30
+ Alpha.sphinx_scope(:by_name) { |name| {:conditions => {:name => name}} }
31
+ end
32
+
33
+ it "should return an array of defined scope names as symbols" do
34
+ Alpha.sphinx_scopes.should == [:by_name]
35
+ end
36
+ end
37
+
38
+ describe '.default_sphinx_scope' do
39
+ before :each do
40
+ Alpha.sphinx_scope(:scope_used_as_default_scope) { {:conditions => {:name => 'name'}} }
41
+ Alpha.default_sphinx_scope :scope_used_as_default_scope
42
+ end
43
+
44
+ it "should return an array of defined scope names as symbols" do
45
+ Alpha.sphinx_scopes.should == [:scope_used_as_default_scope]
46
+ end
47
+
48
+ it "should have a default_sphinx_scope" do
49
+ Alpha.has_default_sphinx_scope?.should be_true
50
+ end
51
+ end
52
+
53
+ describe '.remove_sphinx_scopes' do
54
+ before :each do
55
+ Alpha.sphinx_scope(:by_name) { |name| {:conditions => {:name => name}} }
56
+ Alpha.remove_sphinx_scopes
57
+ end
58
+
59
+ it "should remove sphinx scope methods" do
60
+ Alpha.should_not respond_to(:by_name)
61
+ end
62
+
63
+ it "should empty the list of sphinx scopes" do
64
+ Alpha.sphinx_scopes.should be_empty
65
+ end
66
+ end
67
+
68
+ describe '.example_default_scope' do
69
+ before :each do
70
+ Alpha.sphinx_scope(:foo_scope){ {:conditions => {:name => 'foo'}} }
71
+ Alpha.default_sphinx_scope :foo_scope
72
+ Alpha.sphinx_scope(:by_name) { |name| {:conditions => {:name => name}} }
73
+ Alpha.sphinx_scope(:by_foo) { |foo| {:conditions => {:foo => foo}} }
74
+ end
75
+
76
+ it "should return a ThinkingSphinx::Search object" do
77
+ Alpha.search.should be_a(ThinkingSphinx::Search)
78
+ end
79
+
80
+ it "should apply the default scope options to the underlying search object" do
81
+ search = ThinkingSphinx::Search.new(:classes => [Alpha])
82
+ search.search.options[:conditions].should == {:name => 'foo'}
83
+ end
84
+
85
+ it "should apply the default scope options and scope options to the underlying search object" do
86
+ search = ThinkingSphinx::Search.new(:classes => [Alpha])
87
+ search.by_foo('foo').search.options[:conditions].should == {:foo => 'foo', :name => 'foo'}
88
+ end
89
+
90
+ # FIXME: Probably the other way around is more logical? How to do this?
91
+ it "should apply the default scope options after other scope options to the underlying search object" do
92
+ search = ThinkingSphinx::Search.new(:classes => [Alpha])
93
+ search.by_name('bar').search.options[:conditions].should == {:name => 'foo'}
94
+ end
95
+ end
96
+
97
+ describe '.example_scope' do
98
+ before :each do
99
+ Alpha.sphinx_scope(:by_name) { |name| {:conditions => {:name => name}} }
100
+ Alpha.sphinx_scope(:by_foo) { |foo| {:conditions => {:foo => foo}} }
101
+ Alpha.sphinx_scope(:with_betas) { {:classes => [Beta]} }
102
+ end
103
+
104
+ it "should return a ThinkingSphinx::Search object" do
105
+ Alpha.by_name('foo').should be_a(ThinkingSphinx::Search)
106
+ end
107
+
108
+ it "should set the classes option" do
109
+ Alpha.by_name('foo').options[:classes].should == [Alpha]
110
+ end
111
+
112
+ it "should be able to be called on a ThinkingSphinx::Search object" do
113
+ search = ThinkingSphinx::Search.new(:classes => [Alpha])
114
+ lambda {
115
+ search.by_name('foo')
116
+ }.should_not raise_error
117
+ end
118
+
119
+ it "should return the search object it gets called upon" do
120
+ search = ThinkingSphinx::Search.new(:classes => [Alpha])
121
+ search.by_name('foo').should == search
122
+ end
123
+
124
+ it "should apply the scope options to the underlying search object" do
125
+ search = ThinkingSphinx::Search.new(:classes => [Alpha])
126
+ search.by_name('foo').options[:conditions].should == {:name => 'foo'}
127
+ end
128
+
129
+ it "should combine hash option scopes such as :conditions" do
130
+ search = ThinkingSphinx::Search.new(:classes => [Alpha])
131
+ search.by_name('foo').by_foo('bar').options[:conditions].
132
+ should == {:name => 'foo', :foo => 'bar'}
133
+ end
134
+
135
+ it "should combine array option scopes such as :classes" do
136
+ search = ThinkingSphinx::Search.new(:classes => [Alpha])
137
+ search.with_betas.options[:classes].should == [Alpha, Beta]
138
+ end
139
+ end
140
+
141
+ describe '.search_count_with_scope' do
142
+ before :each do
143
+ @config = ThinkingSphinx::Configuration.instance
144
+ @client = Riddle::Client.new
145
+
146
+ @config.stub!(:client => @client)
147
+ @client.stub!(:query => {:matches => [], :total_found => 43})
148
+ Alpha.sphinx_scope(:by_name) { |name| {:conditions => {:name => name}} }
149
+ Alpha.sphinx_scope(:ids_only) { {:ids_only => true} }
150
+ end
151
+
152
+ it "should return the total number of results" do
153
+ Alpha.by_name('foo').search_count.should == 43
154
+ end
155
+
156
+ it "should not make any calls to the database" do
157
+ Alpha.should_not_receive(:find)
158
+
159
+ Alpha.by_name('foo').search_count
160
+ end
161
+
162
+ it "should not leave the :ids_only option set and the results populated if it was not set before" do
163
+ stored_scope = Alpha.by_name('foo')
164
+ stored_scope.search_count
165
+ stored_scope.options[:ids_only].should be_false
166
+ stored_scope.populated?.should be_false
167
+ end
168
+
169
+ it "should leave the :ids_only option set and the results populated if it was set before" do
170
+ stored_scope = Alpha.by_name('foo').ids_only
171
+ stored_scope.search_count
172
+ stored_scope.options[:ids_only].should be_true
173
+ stored_scope.populated?.should be_true
174
+ end
175
+ end
176
+
177
+ end