zipme-thinking-sphinx 1.3.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 (158) hide show
  1. data/LICENCE +20 -0
  2. data/README.textile +168 -0
  3. data/VERSION +1 -0
  4. data/features/abstract_inheritance.feature +10 -0
  5. data/features/alternate_primary_key.feature +27 -0
  6. data/features/attribute_transformation.feature +22 -0
  7. data/features/attribute_updates.feature +51 -0
  8. data/features/deleting_instances.feature +67 -0
  9. data/features/direct_attributes.feature +11 -0
  10. data/features/excerpts.feature +13 -0
  11. data/features/extensible_delta_indexing.feature +9 -0
  12. data/features/facets.feature +82 -0
  13. data/features/facets_across_model.feature +29 -0
  14. data/features/handling_edits.feature +92 -0
  15. data/features/retry_stale_indexes.feature +24 -0
  16. data/features/searching_across_models.feature +20 -0
  17. data/features/searching_by_index.feature +40 -0
  18. data/features/searching_by_model.feature +175 -0
  19. data/features/searching_with_find_arguments.feature +56 -0
  20. data/features/sphinx_detection.feature +25 -0
  21. data/features/sphinx_scopes.feature +42 -0
  22. data/features/step_definitions/alpha_steps.rb +16 -0
  23. data/features/step_definitions/beta_steps.rb +7 -0
  24. data/features/step_definitions/common_steps.rb +188 -0
  25. data/features/step_definitions/extensible_delta_indexing_steps.rb +7 -0
  26. data/features/step_definitions/facet_steps.rb +96 -0
  27. data/features/step_definitions/find_arguments_steps.rb +36 -0
  28. data/features/step_definitions/gamma_steps.rb +15 -0
  29. data/features/step_definitions/scope_steps.rb +15 -0
  30. data/features/step_definitions/search_steps.rb +89 -0
  31. data/features/step_definitions/sphinx_steps.rb +35 -0
  32. data/features/sti_searching.feature +19 -0
  33. data/features/support/database.example.yml +3 -0
  34. data/features/support/db/fixtures/alphas.rb +10 -0
  35. data/features/support/db/fixtures/authors.rb +1 -0
  36. data/features/support/db/fixtures/betas.rb +10 -0
  37. data/features/support/db/fixtures/boxes.rb +9 -0
  38. data/features/support/db/fixtures/categories.rb +1 -0
  39. data/features/support/db/fixtures/cats.rb +3 -0
  40. data/features/support/db/fixtures/comments.rb +24 -0
  41. data/features/support/db/fixtures/developers.rb +29 -0
  42. data/features/support/db/fixtures/dogs.rb +3 -0
  43. data/features/support/db/fixtures/extensible_betas.rb +10 -0
  44. data/features/support/db/fixtures/foxes.rb +3 -0
  45. data/features/support/db/fixtures/gammas.rb +10 -0
  46. data/features/support/db/fixtures/music.rb +4 -0
  47. data/features/support/db/fixtures/people.rb +1001 -0
  48. data/features/support/db/fixtures/posts.rb +6 -0
  49. data/features/support/db/fixtures/robots.rb +14 -0
  50. data/features/support/db/fixtures/tags.rb +27 -0
  51. data/features/support/db/migrations/create_alphas.rb +8 -0
  52. data/features/support/db/migrations/create_animals.rb +5 -0
  53. data/features/support/db/migrations/create_authors.rb +3 -0
  54. data/features/support/db/migrations/create_authors_posts.rb +6 -0
  55. data/features/support/db/migrations/create_betas.rb +5 -0
  56. data/features/support/db/migrations/create_boxes.rb +5 -0
  57. data/features/support/db/migrations/create_categories.rb +3 -0
  58. data/features/support/db/migrations/create_comments.rb +10 -0
  59. data/features/support/db/migrations/create_developers.rb +9 -0
  60. data/features/support/db/migrations/create_extensible_betas.rb +5 -0
  61. data/features/support/db/migrations/create_gammas.rb +3 -0
  62. data/features/support/db/migrations/create_genres.rb +3 -0
  63. data/features/support/db/migrations/create_music.rb +6 -0
  64. data/features/support/db/migrations/create_people.rb +13 -0
  65. data/features/support/db/migrations/create_posts.rb +5 -0
  66. data/features/support/db/migrations/create_robots.rb +4 -0
  67. data/features/support/db/migrations/create_taggings.rb +5 -0
  68. data/features/support/db/migrations/create_tags.rb +4 -0
  69. data/features/support/env.rb +21 -0
  70. data/features/support/lib/generic_delta_handler.rb +8 -0
  71. data/features/support/models/alpha.rb +22 -0
  72. data/features/support/models/animal.rb +5 -0
  73. data/features/support/models/author.rb +3 -0
  74. data/features/support/models/beta.rb +8 -0
  75. data/features/support/models/box.rb +8 -0
  76. data/features/support/models/cat.rb +3 -0
  77. data/features/support/models/category.rb +4 -0
  78. data/features/support/models/comment.rb +10 -0
  79. data/features/support/models/developer.rb +16 -0
  80. data/features/support/models/dog.rb +3 -0
  81. data/features/support/models/extensible_beta.rb +9 -0
  82. data/features/support/models/fox.rb +5 -0
  83. data/features/support/models/gamma.rb +5 -0
  84. data/features/support/models/genre.rb +3 -0
  85. data/features/support/models/medium.rb +5 -0
  86. data/features/support/models/music.rb +8 -0
  87. data/features/support/models/person.rb +23 -0
  88. data/features/support/models/post.rb +21 -0
  89. data/features/support/models/robot.rb +12 -0
  90. data/features/support/models/tag.rb +3 -0
  91. data/features/support/models/tagging.rb +4 -0
  92. data/lib/cucumber/thinking_sphinx/external_world.rb +8 -0
  93. data/lib/cucumber/thinking_sphinx/internal_world.rb +126 -0
  94. data/lib/cucumber/thinking_sphinx/sql_logger.rb +20 -0
  95. data/lib/thinking_sphinx.rb +231 -0
  96. data/lib/thinking_sphinx/active_record.rb +373 -0
  97. data/lib/thinking_sphinx/active_record/attribute_updates.rb +46 -0
  98. data/lib/thinking_sphinx/active_record/delta.rb +61 -0
  99. data/lib/thinking_sphinx/active_record/has_many_association.rb +29 -0
  100. data/lib/thinking_sphinx/active_record/scopes.rb +75 -0
  101. data/lib/thinking_sphinx/adapters/abstract_adapter.rb +42 -0
  102. data/lib/thinking_sphinx/adapters/mysql_adapter.rb +54 -0
  103. data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +143 -0
  104. data/lib/thinking_sphinx/association.rb +164 -0
  105. data/lib/thinking_sphinx/attribute.rb +362 -0
  106. data/lib/thinking_sphinx/auto_version.rb +22 -0
  107. data/lib/thinking_sphinx/class_facet.rb +15 -0
  108. data/lib/thinking_sphinx/configuration.rb +283 -0
  109. data/lib/thinking_sphinx/context.rb +68 -0
  110. data/lib/thinking_sphinx/core/array.rb +7 -0
  111. data/lib/thinking_sphinx/core/string.rb +15 -0
  112. data/lib/thinking_sphinx/deltas.rb +28 -0
  113. data/lib/thinking_sphinx/deltas/default_delta.rb +62 -0
  114. data/lib/thinking_sphinx/deploy/capistrano.rb +100 -0
  115. data/lib/thinking_sphinx/excerpter.rb +22 -0
  116. data/lib/thinking_sphinx/facet.rb +125 -0
  117. data/lib/thinking_sphinx/facet_search.rb +136 -0
  118. data/lib/thinking_sphinx/field.rb +82 -0
  119. data/lib/thinking_sphinx/index.rb +157 -0
  120. data/lib/thinking_sphinx/index/builder.rb +296 -0
  121. data/lib/thinking_sphinx/index/faux_column.rb +110 -0
  122. data/lib/thinking_sphinx/property.rb +162 -0
  123. data/lib/thinking_sphinx/rails_additions.rb +150 -0
  124. data/lib/thinking_sphinx/search.rb +775 -0
  125. data/lib/thinking_sphinx/search_methods.rb +439 -0
  126. data/lib/thinking_sphinx/source.rb +153 -0
  127. data/lib/thinking_sphinx/source/internal_properties.rb +46 -0
  128. data/lib/thinking_sphinx/source/sql.rb +130 -0
  129. data/lib/thinking_sphinx/tasks.rb +121 -0
  130. data/lib/thinking_sphinx/test.rb +52 -0
  131. data/rails/init.rb +16 -0
  132. data/spec/thinking_sphinx/active_record/delta_spec.rb +128 -0
  133. data/spec/thinking_sphinx/active_record/has_many_association_spec.rb +55 -0
  134. data/spec/thinking_sphinx/active_record/scopes_spec.rb +177 -0
  135. data/spec/thinking_sphinx/active_record_spec.rb +622 -0
  136. data/spec/thinking_sphinx/association_spec.rb +239 -0
  137. data/spec/thinking_sphinx/attribute_spec.rb +570 -0
  138. data/spec/thinking_sphinx/auto_version_spec.rb +39 -0
  139. data/spec/thinking_sphinx/configuration_spec.rb +234 -0
  140. data/spec/thinking_sphinx/context_spec.rb +119 -0
  141. data/spec/thinking_sphinx/core/array_spec.rb +9 -0
  142. data/spec/thinking_sphinx/core/string_spec.rb +9 -0
  143. data/spec/thinking_sphinx/excerpter_spec.rb +57 -0
  144. data/spec/thinking_sphinx/facet_search_spec.rb +176 -0
  145. data/spec/thinking_sphinx/facet_spec.rb +333 -0
  146. data/spec/thinking_sphinx/field_spec.rb +154 -0
  147. data/spec/thinking_sphinx/index/builder_spec.rb +479 -0
  148. data/spec/thinking_sphinx/index/faux_column_spec.rb +30 -0
  149. data/spec/thinking_sphinx/index_spec.rb +183 -0
  150. data/spec/thinking_sphinx/rails_additions_spec.rb +203 -0
  151. data/spec/thinking_sphinx/search_methods_spec.rb +152 -0
  152. data/spec/thinking_sphinx/search_spec.rb +1181 -0
  153. data/spec/thinking_sphinx/source_spec.rb +235 -0
  154. data/spec/thinking_sphinx_spec.rb +204 -0
  155. data/tasks/distribution.rb +39 -0
  156. data/tasks/rails.rake +1 -0
  157. data/tasks/testing.rb +72 -0
  158. metadata +242 -0
@@ -0,0 +1,46 @@
1
+ module ThinkingSphinx
2
+ class Source
3
+ module InternalProperties
4
+ def add_internal_attributes_and_facets
5
+ add_internal_attribute :sphinx_internal_id, :integer, @model.primary_key_for_sphinx.to_sym
6
+ add_internal_attribute :class_crc, :integer, crc_column, true
7
+ add_internal_attribute :subclass_crcs, :multi, subclasses_to_s
8
+ add_internal_attribute :sphinx_deleted, :integer, "0"
9
+
10
+ add_internal_facet :class_crc
11
+ end
12
+
13
+ def add_internal_attribute(name, type, contents, facet = false)
14
+ return unless attribute_by_alias(name).nil?
15
+
16
+ Attribute.new(self,
17
+ ThinkingSphinx::Index::FauxColumn.new(contents),
18
+ :type => type,
19
+ :as => name,
20
+ :facet => facet,
21
+ :admin => true
22
+ )
23
+ end
24
+
25
+ def add_internal_facet(name)
26
+ return unless facet_by_alias(name).nil?
27
+
28
+ @model.sphinx_facets << ClassFacet.new(attribute_by_alias(name))
29
+ end
30
+
31
+ def attribute_by_alias(attr_alias)
32
+ @attributes.detect { |attrib| attrib.alias == attr_alias }
33
+ end
34
+
35
+ def facet_by_alias(name)
36
+ @model.sphinx_facets.detect { |facet| facet.name == name }
37
+ end
38
+
39
+ def subclasses_to_s
40
+ "'" + (@model.send(:subclasses).collect { |klass|
41
+ klass.to_crc32.to_s
42
+ } << @model.to_crc32.to_s).join(",") + "'"
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,130 @@
1
+ module ThinkingSphinx
2
+ class Source
3
+ module SQL
4
+ # Generates the big SQL statement to get the data back for all the fields
5
+ # and attributes, using all the relevant association joins. If you want
6
+ # the version filtered for delta values, send through :delta => true in the
7
+ # options. Won't do much though if the index isn't set up to support a
8
+ # delta sibling.
9
+ #
10
+ # Examples:
11
+ #
12
+ # source.to_sql
13
+ # source.to_sql(:delta => true)
14
+ #
15
+ def to_sql(options={})
16
+ sql = "SELECT "
17
+ sql += "SQL_NO_CACHE " if adapter.sphinx_identifier == "mysql"
18
+ sql += <<-SQL
19
+ #{ sql_select_clause options[:offset] }
20
+ FROM #{ @model.quoted_table_name }
21
+ #{ all_associations.collect { |assoc| assoc.to_sql }.join(' ') }
22
+ #{ sql_where_clause(options) }
23
+ GROUP BY #{ sql_group_clause }
24
+ SQL
25
+
26
+ sql += " ORDER BY NULL" if adapter.sphinx_identifier == "mysql"
27
+ sql
28
+ end
29
+
30
+ # Simple helper method for the query range SQL - which is a statement that
31
+ # returns minimum and maximum id values. These can be filtered by delta -
32
+ # so pass in :delta => true to get the delta version of the SQL.
33
+ #
34
+ def to_sql_query_range(options={})
35
+ return nil if @index.options[:disable_range]
36
+
37
+ min_statement = adapter.convert_nulls(
38
+ "MIN(#{quote_column(@model.primary_key_for_sphinx)})", 1
39
+ )
40
+ max_statement = adapter.convert_nulls(
41
+ "MAX(#{quote_column(@model.primary_key_for_sphinx)})", 1
42
+ )
43
+
44
+ sql = "SELECT #{min_statement}, #{max_statement} " +
45
+ "FROM #{@model.quoted_table_name} "
46
+ if self.delta? && !@index.delta_object.clause(@model, options[:delta]).blank?
47
+ sql << "WHERE #{@index.delta_object.clause(@model, options[:delta])}"
48
+ end
49
+
50
+ sql
51
+ end
52
+
53
+ # Simple helper method for the query info SQL - which is a statement that
54
+ # returns the single row for a corresponding id.
55
+ #
56
+ def to_sql_query_info(offset)
57
+ "SELECT * FROM #{@model.quoted_table_name} WHERE " +
58
+ "#{quote_column(@model.primary_key_for_sphinx)} = (($id - #{offset}) / #{ThinkingSphinx.context.indexed_models.size})"
59
+ end
60
+
61
+ def sql_select_clause(offset)
62
+ unique_id_expr = ThinkingSphinx.unique_id_expression(offset)
63
+
64
+ (
65
+ ["#{@model.quoted_table_name}.#{quote_column(@model.primary_key_for_sphinx)} #{unique_id_expr} AS #{quote_column(@model.primary_key_for_sphinx)} "] +
66
+ @fields.collect { |field| field.to_select_sql } +
67
+ @attributes.collect { |attribute| attribute.to_select_sql }
68
+ ).compact.join(", ")
69
+ end
70
+
71
+ def sql_where_clause(options)
72
+ logic = []
73
+ logic += [
74
+ "#{@model.quoted_table_name}.#{quote_column(@model.primary_key_for_sphinx)} >= $start",
75
+ "#{@model.quoted_table_name}.#{quote_column(@model.primary_key_for_sphinx)} <= $end"
76
+ ] unless @index.options[:disable_range]
77
+
78
+ if self.delta? && !@index.delta_object.clause(@model, options[:delta]).blank?
79
+ logic << "#{@index.delta_object.clause(@model, options[:delta])}"
80
+ end
81
+
82
+ logic += (@conditions || [])
83
+ logic.empty? ? "" : "WHERE #{logic.join(' AND ')}"
84
+ end
85
+
86
+ def sql_group_clause
87
+ internal_groupings = []
88
+ if @model.column_names.include?(@model.inheritance_column)
89
+ internal_groupings << "#{@model.quoted_table_name}.#{quote_column(@model.inheritance_column)}"
90
+ end
91
+
92
+ (
93
+ ["#{@model.quoted_table_name}.#{quote_column(@model.primary_key_for_sphinx)}"] +
94
+ @fields.collect { |field| field.to_group_sql }.compact +
95
+ @attributes.collect { |attribute| attribute.to_group_sql }.compact +
96
+ @groupings + internal_groupings
97
+ ).join(", ")
98
+ end
99
+
100
+ def sql_query_pre_for_core
101
+ if self.delta? && !@index.delta_object.reset_query(@model).blank?
102
+ [@index.delta_object.reset_query(@model)]
103
+ else
104
+ []
105
+ end
106
+ end
107
+
108
+ def sql_query_pre_for_delta
109
+ [""]
110
+ end
111
+
112
+ def quote_column(column)
113
+ @model.connection.quote_column_name(column)
114
+ end
115
+
116
+ def crc_column
117
+ if @model.table_exists? &&
118
+ @model.column_names.include?(@model.inheritance_column)
119
+
120
+ adapter.cast_to_unsigned(adapter.convert_nulls(
121
+ adapter.crc(adapter.quote_with_table(@model.inheritance_column), true),
122
+ @model.to_crc32
123
+ ))
124
+ else
125
+ @model.to_crc32.to_s
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,121 @@
1
+ require 'fileutils'
2
+
3
+ namespace :thinking_sphinx do
4
+ task :app_env do
5
+ if defined?(RAILS_ROOT)
6
+ Rake::Task[:environment].invoke
7
+ Rails.configuration.cache_classes = false
8
+ end
9
+
10
+ Rake::Task[:merb_env].invoke if defined?(Merb)
11
+ end
12
+
13
+ desc "Output the current Thinking Sphinx version"
14
+ task :version => :app_env do
15
+ puts "Thinking Sphinx v" + ThinkingSphinx.version
16
+ end
17
+
18
+ desc "Stop if running, then start a Sphinx searchd daemon using Thinking Sphinx's settings"
19
+ task :running_start => :app_env do
20
+ Rake::Task["thinking_sphinx:stop"].invoke if sphinx_running?
21
+ Rake::Task["thinking_sphinx:start"].invoke
22
+ end
23
+
24
+ desc "Start a Sphinx searchd daemon using Thinking Sphinx's settings"
25
+ task :start => :app_env do
26
+ config = ThinkingSphinx::Configuration.instance
27
+
28
+ FileUtils.mkdir_p config.searchd_file_path
29
+ raise RuntimeError, "searchd is already running." if sphinx_running?
30
+
31
+ Dir["#{config.searchd_file_path}/*.spl"].each { |file| File.delete(file) }
32
+
33
+ config.controller.start
34
+
35
+ if sphinx_running?
36
+ puts "Started successfully (pid #{sphinx_pid})."
37
+ else
38
+ puts "Failed to start searchd daemon. Check #{config.searchd_log_file}"
39
+ end
40
+ end
41
+
42
+ desc "Stop Sphinx using Thinking Sphinx's settings"
43
+ task :stop => :app_env do
44
+ unless sphinx_running?
45
+ puts "searchd is not running"
46
+ else
47
+ config = ThinkingSphinx::Configuration.instance
48
+ pid = sphinx_pid
49
+ config.controller.stop
50
+ puts "Stopped search daemon (pid #{pid})."
51
+ end
52
+ end
53
+
54
+ desc "Restart Sphinx"
55
+ task :restart => [:app_env, :stop, :start]
56
+
57
+ desc "Generate the Sphinx configuration file using Thinking Sphinx's settings"
58
+ task :configure => :app_env do
59
+ config = ThinkingSphinx::Configuration.instance
60
+ puts "Generating Configuration to #{config.config_file}"
61
+ config.build
62
+ end
63
+
64
+ desc "Index data for Sphinx using Thinking Sphinx's settings"
65
+ task :index => :app_env do
66
+ config = ThinkingSphinx::Configuration.instance
67
+ unless ENV["INDEX_ONLY"] == "true"
68
+ puts "Generating Configuration to #{config.config_file}"
69
+ config.build
70
+ end
71
+
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
+ end
82
+
83
+ desc "Stop Sphinx (if it's running), rebuild the indexes, and start Sphinx"
84
+ task :rebuild => :app_env do
85
+ Rake::Task["thinking_sphinx:stop"].invoke if sphinx_running?
86
+ Rake::Task["thinking_sphinx:index"].invoke
87
+ Rake::Task["thinking_sphinx:start"].invoke
88
+ end
89
+ end
90
+
91
+ namespace :ts do
92
+ desc "Output the current Thinking Sphinx version"
93
+ task :version => "thinking_sphinx:version"
94
+ desc "Stop if running, then start a Sphinx searchd daemon using Thinking Sphinx's settings"
95
+ task :run => "thinking_sphinx:running_start"
96
+ desc "Start a Sphinx searchd daemon using Thinking Sphinx's settings"
97
+ task :start => "thinking_sphinx:start"
98
+ desc "Stop Sphinx using Thinking Sphinx's settings"
99
+ task :stop => "thinking_sphinx:stop"
100
+ desc "Index data for Sphinx using Thinking Sphinx's settings"
101
+ task :in => "thinking_sphinx:index"
102
+ task :index => "thinking_sphinx:index"
103
+ desc "Reindex Sphinx without regenerating the configuration file"
104
+ task :reindex => "thinking_sphinx:reindex"
105
+ desc "Restart Sphinx"
106
+ task :restart => "thinking_sphinx:restart"
107
+ desc "Generate the Sphinx configuration file using Thinking Sphinx's settings"
108
+ task :conf => "thinking_sphinx:configure"
109
+ desc "Generate the Sphinx configuration file using Thinking Sphinx's settings"
110
+ task :config => "thinking_sphinx:configure"
111
+ desc "Stop Sphinx (if it's running), rebuild the indexes, and start Sphinx"
112
+ task :rebuild => "thinking_sphinx:rebuild"
113
+ end
114
+
115
+ def sphinx_pid
116
+ ThinkingSphinx.sphinx_pid
117
+ end
118
+
119
+ def sphinx_running?
120
+ ThinkingSphinx.sphinx_running?
121
+ 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 ADDED
@@ -0,0 +1,16 @@
1
+ Dir[File.join(File.dirname(__FILE__), '../vendor/*/lib')].each do |path|
2
+ $LOAD_PATH.unshift path
3
+ end
4
+
5
+ require 'thinking_sphinx'
6
+ require 'action_controller/dispatcher'
7
+
8
+ ActionController::Dispatcher.to_prepare :thinking_sphinx do
9
+ # Force internationalisation to be loaded.
10
+ if Rails::VERSION::STRING.to_f > 2.2
11
+ I18n.backend.reload!
12
+ I18n.backend.available_locales
13
+ elsif Rails::VERSION::STRING.to_f > 2.1
14
+ I18n.backend.load_translations(*I18n.load_path)
15
+ end
16
+ end
@@ -0,0 +1,128 @@
1
+ require 'spec/spec_helper'
2
+
3
+ describe "ThinkingSphinx::ActiveRecord::Delta" do
4
+ it "should call the toggle_delta method after a save" do
5
+ @beta = Beta.new(:name => 'beta')
6
+ @beta.should_receive(:toggle_delta).and_return(true)
7
+
8
+ @beta.save
9
+ end
10
+
11
+ it "should call the toggle_delta method after a save!" do
12
+ @beta = Beta.new(:name => 'beta')
13
+ @beta.should_receive(:toggle_delta).and_return(true)
14
+
15
+ @beta.save!
16
+ end
17
+
18
+ describe "suspended_delta method" do
19
+ before :each do
20
+ ThinkingSphinx.deltas_enabled = true
21
+ Person.sphinx_indexes.first.delta_object.stub!(:` => "")
22
+ end
23
+
24
+ it "should execute the argument block with deltas disabled" do
25
+ ThinkingSphinx.should_receive(:deltas_enabled=).once.with(false)
26
+ ThinkingSphinx.should_receive(:deltas_enabled=).once.with(true)
27
+ lambda { Person.suspended_delta { raise 'i was called' } }.should(
28
+ raise_error(Exception)
29
+ )
30
+ end
31
+
32
+ it "should restore deltas_enabled to its original setting" do
33
+ ThinkingSphinx.deltas_enabled = false
34
+ ThinkingSphinx.should_receive(:deltas_enabled=).twice.with(false)
35
+ Person.suspended_delta { 'no-op' }
36
+ end
37
+
38
+ it "should restore deltas_enabled to its original setting even if there was an exception" do
39
+ ThinkingSphinx.deltas_enabled = false
40
+ ThinkingSphinx.should_receive(:deltas_enabled=).twice.with(false)
41
+ lambda { Person.suspended_delta { raise 'bad error' } }.should(
42
+ raise_error(Exception)
43
+ )
44
+ end
45
+
46
+ it "should reindex by default after the code block is run" do
47
+ Person.should_receive(:index_delta)
48
+ Person.suspended_delta { 'no-op' }
49
+ end
50
+
51
+ it "should not reindex after the code block if false is passed in" do
52
+ Person.should_not_receive(:index_delta)
53
+ Person.suspended_delta(false) { 'no-op' }
54
+ end
55
+ end
56
+
57
+ describe "toggle_delta method" do
58
+ it "should set the delta value to true" do
59
+ @person = Person.new
60
+
61
+ @person.delta.should be_false
62
+ @person.send(:toggle_delta)
63
+ @person.delta.should be_true
64
+ end
65
+ end
66
+
67
+ describe "index_delta method" do
68
+ before :each do
69
+ ThinkingSphinx::Configuration.stub!(:environment => "spec")
70
+ ThinkingSphinx.deltas_enabled = true
71
+ ThinkingSphinx.updates_enabled = true
72
+ ThinkingSphinx.stub!(:sphinx_running? => true)
73
+ Person.delta_object.stub!(:` => "", :toggled => true)
74
+
75
+ @person = Person.new
76
+ Person.stub!(:search_for_id => false)
77
+ @person.stub!(:sphinx_document_id => 1)
78
+
79
+ @client = Riddle::Client.new
80
+ @client.stub!(:update => true)
81
+ ThinkingSphinx::Configuration.instance.stub!(:client => @client)
82
+ end
83
+
84
+ it "shouldn't index if delta indexing is disabled" do
85
+ ThinkingSphinx.deltas_enabled = false
86
+ Person.sphinx_indexes.first.delta_object.should_not_receive(:`)
87
+ @client.should_not_receive(:update)
88
+
89
+ @person.send(:index_delta)
90
+ end
91
+
92
+ it "shouldn't index if index updating is disabled" do
93
+ ThinkingSphinx.updates_enabled = false
94
+ Person.sphinx_indexes.first.delta_object.should_not_receive(:`)
95
+
96
+ @person.send(:index_delta)
97
+ end
98
+
99
+ it "shouldn't index if the environment is 'test'" do
100
+ ThinkingSphinx.deltas_enabled = nil
101
+ ThinkingSphinx::Configuration.stub!(:environment => "test")
102
+ Person.sphinx_indexes.first.delta_object.should_not_receive(:`)
103
+
104
+ @person.send(:index_delta)
105
+ end
106
+
107
+ it "should call indexer for the delta index" do
108
+ Person.sphinx_indexes.first.delta_object.should_receive(:`).with(
109
+ "#{ThinkingSphinx::Configuration.instance.bin_path}indexer --config #{ThinkingSphinx::Configuration.instance.config_file} --rotate person_delta"
110
+ )
111
+
112
+ @person.send(:index_delta)
113
+ end
114
+
115
+ it "shouldn't update the deleted attribute if not in the index" do
116
+ @client.should_not_receive(:update)
117
+
118
+ @person.send(:index_delta)
119
+ end
120
+
121
+ it "should update the deleted attribute if in the core index" do
122
+ Person.stub!(:search_for_id => true)
123
+ @client.should_receive(:update)
124
+
125
+ @person.send(:index_delta)
126
+ end
127
+ end
128
+ end