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,134 @@
1
+ require 'spec_helper'
2
+
3
+ describe ThinkingSphinx::AbstractAdapter do
4
+ describe '.detect' do
5
+ let(:model) { stub('model') }
6
+
7
+ it "returns a MysqlAdapter object for :mysql" do
8
+ ThinkingSphinx::AbstractAdapter.stub(:adapter_for_model => :mysql)
9
+
10
+ adapter = ThinkingSphinx::AbstractAdapter.detect(model)
11
+ adapter.should be_a(ThinkingSphinx::MysqlAdapter)
12
+ end
13
+
14
+ it "returns a PostgreSQLAdapter object for :postgresql" do
15
+ ThinkingSphinx::AbstractAdapter.stub(:adapter_for_model => :postgresql)
16
+
17
+ adapter = ThinkingSphinx::AbstractAdapter.detect(model)
18
+ adapter.should be_a(ThinkingSphinx::PostgreSQLAdapter)
19
+ end
20
+
21
+ it "raises an exception for other responses" do
22
+ ThinkingSphinx::AbstractAdapter.stub(:adapter_for_model => :sqlite)
23
+
24
+ lambda {
25
+ ThinkingSphinx::AbstractAdapter.detect(model)
26
+ }.should raise_error
27
+ end
28
+ end
29
+
30
+ describe '.adapter_for_model' do
31
+ let(:model) { stub('model') }
32
+
33
+ after :each do
34
+ ThinkingSphinx.database_adapter = nil
35
+ end
36
+
37
+ it "translates strings to symbols" do
38
+ ThinkingSphinx.database_adapter = 'foo'
39
+
40
+ ThinkingSphinx::AbstractAdapter.adapter_for_model(model).should == :foo
41
+ end
42
+
43
+ it "passes through symbols unchanged" do
44
+ ThinkingSphinx.database_adapter = :bar
45
+
46
+ ThinkingSphinx::AbstractAdapter.adapter_for_model(model).should == :bar
47
+ end
48
+
49
+ it "returns standard_adapter_for_model if database_adapter is not set" do
50
+ ThinkingSphinx.database_adapter = nil
51
+ ThinkingSphinx::AbstractAdapter.stub!(:standard_adapter_for_model => :baz)
52
+
53
+ ThinkingSphinx::AbstractAdapter.adapter_for_model(model).should == :baz
54
+ end
55
+
56
+ it "calls the lambda and returns it if one is provided" do
57
+ ThinkingSphinx.database_adapter = lambda { |model| :foo }
58
+
59
+ ThinkingSphinx::AbstractAdapter.adapter_for_model(model).should == :foo
60
+ end
61
+ end
62
+
63
+ describe '.standard_adapter_for_model' do
64
+ let(:klass) { stub('connection class') }
65
+ let(:connection) { stub('connection', :class => klass) }
66
+ let(:model) { stub('model', :connection => connection) }
67
+
68
+ it "translates a normal MySQL adapter" do
69
+ klass.stub(:name => 'ActiveRecord::ConnectionAdapters::MysqlAdapter')
70
+
71
+ ThinkingSphinx::AbstractAdapter.standard_adapter_for_model(model).
72
+ should == :mysql
73
+ end
74
+
75
+ it "translates a MySQL plus adapter" do
76
+ klass.stub(:name => 'ActiveRecord::ConnectionAdapters::MysqlplusAdapter')
77
+
78
+ ThinkingSphinx::AbstractAdapter.standard_adapter_for_model(model).
79
+ should == :mysql
80
+ end
81
+
82
+ it "translates a MySQL2 adapter" do
83
+ klass.stub(:name => 'ActiveRecord::ConnectionAdapters::Mysql2Adapter')
84
+
85
+ ThinkingSphinx::AbstractAdapter.standard_adapter_for_model(model).
86
+ should == :mysql
87
+ end
88
+
89
+ it "translates a NullDB adapter to MySQL" do
90
+ klass.stub(:name => 'ActiveRecord::ConnectionAdapters::NullDBAdapter')
91
+
92
+ ThinkingSphinx::AbstractAdapter.standard_adapter_for_model(model).
93
+ should == :mysql
94
+ end
95
+
96
+ it "translates a normal PostgreSQL adapter" do
97
+ klass.stub(:name => 'ActiveRecord::ConnectionAdapters::PostgreSQLAdapter')
98
+
99
+ ThinkingSphinx::AbstractAdapter.standard_adapter_for_model(model).
100
+ should == :postgresql
101
+ end
102
+
103
+ it "translates a JDBC MySQL adapter to MySQL" do
104
+ klass.stub(:name => 'ActiveRecord::ConnectionAdapters::JdbcAdapter')
105
+ connection.stub(:config => {:adapter => 'jdbcmysql'})
106
+
107
+ ThinkingSphinx::AbstractAdapter.standard_adapter_for_model(model).
108
+ should == :mysql
109
+ end
110
+
111
+ it "translates a JDBC PostgreSQL adapter to PostgreSQL" do
112
+ klass.stub(:name => 'ActiveRecord::ConnectionAdapters::JdbcAdapter')
113
+ connection.stub(:config => {:adapter => 'jdbcpostgresql'})
114
+
115
+ ThinkingSphinx::AbstractAdapter.standard_adapter_for_model(model).
116
+ should == :postgresql
117
+ end
118
+
119
+ it "returns other JDBC adapters without translation" do
120
+ klass.stub(:name => 'ActiveRecord::ConnectionAdapters::JdbcAdapter')
121
+ connection.stub(:config => {:adapter => 'jdbcmssql'})
122
+
123
+ ThinkingSphinx::AbstractAdapter.standard_adapter_for_model(model).
124
+ should == 'jdbcmssql'
125
+ end
126
+
127
+ it "returns other unknown adapters without translation" do
128
+ klass.stub(:name => 'ActiveRecord::ConnectionAdapters::FooAdapter')
129
+
130
+ ThinkingSphinx::AbstractAdapter.standard_adapter_for_model(model).
131
+ should == 'ActiveRecord::ConnectionAdapters::FooAdapter'
132
+ end
133
+ end
134
+ end
@@ -1,4 +1,4 @@
1
- require 'spec/spec_helper'
1
+ require 'spec_helper'
2
2
 
3
3
  describe ThinkingSphinx::Association do
4
4
  describe '.children' do
@@ -1,4 +1,4 @@
1
- require 'spec/spec_helper'
1
+ require 'spec_helper'
2
2
 
3
3
  describe ThinkingSphinx::Attribute do
4
4
  before :each do
@@ -47,47 +47,6 @@ describe ThinkingSphinx::Attribute do
47
47
  end
48
48
  end
49
49
 
50
- describe '#column_with_prefix' do
51
- before :each do
52
- @attribute = ThinkingSphinx::Attribute.new @source, [
53
- ThinkingSphinx::Index::FauxColumn.new(:col_name)
54
- ]
55
- @attribute.columns.each { |col| @attribute.associations[col] = [] }
56
- @attribute.model = Person
57
-
58
- @first_join = Object.new
59
- @first_join.stub!(:aliased_table_name => "tabular")
60
- @second_join = Object.new
61
- @second_join.stub!(:aliased_table_name => "data")
62
-
63
- @first_assoc = ThinkingSphinx::Association.new nil, nil
64
- @first_assoc.stub!(:join => @first_join, :has_column? => true)
65
- @second_assoc = ThinkingSphinx::Association.new nil, nil
66
- @second_assoc.stub!(:join => @second_join, :has_column? => true)
67
- end
68
-
69
- it "should return the column name if the column is a string" do
70
- @attribute.columns = [ThinkingSphinx::Index::FauxColumn.new("string")]
71
- @attribute.send(:column_with_prefix, @attribute.columns.first).should == "string"
72
- end
73
-
74
- it "should return the column with model's table prefix if there's no associations for the column" do
75
- @attribute.send(:column_with_prefix, @attribute.columns.first).should == "`people`.`col_name`"
76
- end
77
-
78
- it "should return the column with its join table prefix if an association exists" do
79
- column = @attribute.columns.first
80
- @attribute.associations[column] = [@first_assoc]
81
- @attribute.send(:column_with_prefix, column).should == "`tabular`.`col_name`"
82
- end
83
-
84
- it "should return multiple columns concatenated if more than one association exists" do
85
- column = @attribute.columns.first
86
- @attribute.associations[column] = [@first_assoc, @second_assoc]
87
- @attribute.send(:column_with_prefix, column).should == "`tabular`.`col_name`, `data`.`col_name`"
88
- end
89
- end
90
-
91
50
  describe '#to_select_sql' do
92
51
  it "should convert a mixture of dates and datetimes to timestamps" do
93
52
  attribute = ThinkingSphinx::Attribute.new(@source,
@@ -99,6 +58,16 @@ describe ThinkingSphinx::Attribute do
99
58
 
100
59
  attribute.to_select_sql.should == "CONCAT_WS(',', UNIX_TIMESTAMP(`friendships`.`created_at`), UNIX_TIMESTAMP(`friendships`.`created_on`)) AS `times`"
101
60
  end
61
+
62
+ it "should handle columns which don't exist for polymorphic joins" do
63
+ attribute = ThinkingSphinx::Attribute.new(@source,
64
+ [ ThinkingSphinx::Index::FauxColumn.new(:team, :name),
65
+ ThinkingSphinx::Index::FauxColumn.new(:team, :league) ],
66
+ :as => :team
67
+ )
68
+
69
+ attribute.to_select_sql.should == "CONCAT_WS(' ', IFNULL(`cricket_teams`.`name`, ''), IFNULL(`football_teams`.`name`, ''), IFNULL(`football_teams`.`league`, '')) AS `team`"
70
+ end
102
71
  end
103
72
 
104
73
  describe '#is_many?' do
@@ -183,15 +152,15 @@ describe ThinkingSphinx::Attribute do
183
152
 
184
153
  it "should return the column type from the database if not :multi or more than one association" do
185
154
  @column.send(:instance_variable_set, :@name, "birthday")
186
- @attribute.send(:type).should == :datetime
155
+ @attribute.type.should == :datetime
187
156
 
188
157
  @attribute.send(:instance_variable_set, :@type, nil)
189
158
  @column.send(:instance_variable_set, :@name, "first_name")
190
- @attribute.send(:type).should == :string
159
+ @attribute.type.should == :string
191
160
 
192
161
  @attribute.send(:instance_variable_set, :@type, nil)
193
162
  @column.send(:instance_variable_set, :@name, "id")
194
- @attribute.send(:type).should == :integer
163
+ @attribute.type.should == :integer
195
164
  end
196
165
 
197
166
  it "should return :multi if the columns return multiple datetimes" do
@@ -200,6 +169,15 @@ describe ThinkingSphinx::Attribute do
200
169
 
201
170
  @attribute.type.should == :multi
202
171
  end
172
+
173
+ it "should return :bigint for 64bit integers" do
174
+ Person.columns.detect { |col|
175
+ col.name == 'id'
176
+ }.stub!(:sql_type => 'BIGINT(20)')
177
+ @column.send(:instance_variable_set, :@name, 'id')
178
+
179
+ @attribute.type.should == :bigint
180
+ end
203
181
  end
204
182
 
205
183
  describe '#all_ints?' do
@@ -504,4 +482,67 @@ describe ThinkingSphinx::Attribute do
504
482
  @statement.should match(/SELECT cricket_team_id, id FROM tags/)
505
483
  end
506
484
  end
507
- end
485
+
486
+ describe '#live_value' do
487
+ before :each do
488
+ @attribute = ThinkingSphinx::Attribute.new @source, [
489
+ stub('column', :__stack => [], :__name => "col_name")
490
+ ]
491
+ @instance = stub('model')
492
+ end
493
+
494
+ it "should translate boolean values to integers" do
495
+ @instance.stub!(:col_name => true)
496
+ @attribute.live_value(@instance).should == 1
497
+
498
+ @instance.stub!(:col_name => false)
499
+ @attribute.live_value(@instance).should == 0
500
+ end
501
+
502
+ it "should translate timestamps to integers" do
503
+ now = Time.now
504
+ @instance.stub!(:col_name => now)
505
+ @attribute.live_value(@instance).should == now.to_i
506
+ end
507
+
508
+ it "should translate dates to timestamp integers" do
509
+ today = Date.today
510
+ @instance.stub!(:col_name => today)
511
+ @attribute.live_value(@instance).should == today.to_time.to_i
512
+ end
513
+
514
+ it "should translate nils to 0" do
515
+ @instance.stub!(:col_name => nil)
516
+ @attribute.live_value(@instance).should == 0
517
+ end
518
+
519
+ it "should return integers as integers" do
520
+ @instance.stub!(:col_name => 42)
521
+ @attribute.live_value(@instance).should == 42
522
+ end
523
+
524
+ it "should handle nils in the association chain" do
525
+ @attribute = ThinkingSphinx::Attribute.new @source, [
526
+ stub('column', :__stack => [:assoc_name], :__name => :id)
527
+ ]
528
+ @instance.stub!(:assoc_name => nil)
529
+ @attribute.live_value(@instance).should == 0
530
+ end
531
+
532
+ it "should handle association chains" do
533
+ @attribute = ThinkingSphinx::Attribute.new @source, [
534
+ stub('column', :__stack => [:assoc_name], :__name => :id)
535
+ ]
536
+ @instance.stub!(:assoc_name => stub('object', :id => 42))
537
+ @attribute.live_value(@instance).should == 42
538
+ end
539
+
540
+ it "should translate crc strings to their integer values" do
541
+ @attribute = ThinkingSphinx::Attribute.new @source, [
542
+ stub('column', :__stack => [], :__name => "col_name")
543
+ ], :crc => true, :type => :string
544
+ @instance.stub!(:col_name => 'foo')
545
+ @attribute.live_value(@instance).should == 'foo'.to_crc32
546
+ end
547
+ end
548
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe ThinkingSphinx::AutoVersion do
4
+ describe '.detect' do
5
+ before :each do
6
+ @config = ThinkingSphinx::Configuration.instance
7
+ end
8
+
9
+ it "should require 0.9.8 if that is the detected version" do
10
+ ThinkingSphinx::AutoVersion.should_receive(:require).
11
+ with('riddle/0.9.8')
12
+
13
+ @config.stub!(:version => '0.9.8')
14
+ ThinkingSphinx::AutoVersion.detect
15
+ end
16
+
17
+ it "should require 0.9.9 if that is the detected version" do
18
+ ThinkingSphinx::AutoVersion.should_receive(:require).
19
+ with('riddle/0.9.9')
20
+
21
+ @config.stub!(:version => '0.9.9')
22
+ ThinkingSphinx::AutoVersion.detect
23
+ end
24
+
25
+ it "should require 1.10-beta if that is the detected version" do
26
+ ThinkingSphinx::AutoVersion.should_receive(:require).
27
+ with('riddle/1.10')
28
+
29
+ @config.stub!(:version => '1.10-beta')
30
+ ThinkingSphinx::AutoVersion.detect
31
+ end
32
+
33
+ it "should output a warning if the detected version is something else" do
34
+ STDERR.should_receive(:puts)
35
+
36
+ @config.stub!(:version => '0.9.7')
37
+ ThinkingSphinx::AutoVersion.detect
38
+ end
39
+
40
+ it "should output a warning if the version cannot be determined" do
41
+ STDERR.should_receive(:puts)
42
+
43
+ @config.stub!(:version => nil)
44
+ ThinkingSphinx::AutoVersion.detect
45
+ end
46
+ end
47
+ end
@@ -1,10 +1,10 @@
1
- require 'spec/spec_helper'
1
+ require 'spec_helper'
2
2
 
3
3
  describe ThinkingSphinx::Configuration do
4
4
  describe "environment class method" do
5
5
  before :each do
6
- ThinkingSphinx::Configuration.send(:class_variable_set, :@@environment, nil)
7
-
6
+ Thread.current[:thinking_sphinx_environment] = nil
7
+
8
8
  ENV["RAILS_ENV"] = nil
9
9
  end
10
10
 
@@ -17,7 +17,15 @@ describe ThinkingSphinx::Configuration do
17
17
  Merb.stub!(:environment => "merb_production")
18
18
  ThinkingSphinx::Configuration.environment.should == "merb_production"
19
19
 
20
- Object.send(:remove_const, :Merb)
20
+ Object.send :remove_const, :Merb
21
+ end
22
+
23
+ it "should use RAILS_ENV if set" do
24
+ RAILS_ENV = 'global_rails'
25
+
26
+ ThinkingSphinx::Configuration.environment.should == 'global_rails'
27
+
28
+ Object.send :remove_const, :RAILS_ENV
21
29
  end
22
30
 
23
31
  it "should use the Rails environment value if set" do
@@ -29,6 +37,34 @@ describe ThinkingSphinx::Configuration do
29
37
  ThinkingSphinx::Configuration.environment.should == "development"
30
38
  end
31
39
  end
40
+
41
+ describe '#version' do
42
+ before :each do
43
+ @config = ThinkingSphinx::Configuration.instance
44
+ @config.reset
45
+ end
46
+
47
+ it "should use the given version from sphinx.yml if there is one" do
48
+ open("#{RAILS_ROOT}/config/sphinx.yml", "w") do |f|
49
+ f.write YAML.dump({'development' => {'version' => '0.9.7'}})
50
+ end
51
+ @config.reset
52
+
53
+ @config.version.should == '0.9.7'
54
+
55
+ FileUtils.rm "#{RAILS_ROOT}/config/sphinx.yml"
56
+ end
57
+
58
+ it "should detect the version from Riddle otherwise" do
59
+ controller = @config.controller
60
+ controller.stub!(:sphinx_version => '0.9.6')
61
+
62
+ Riddle::Controller.stub!(:new => controller)
63
+ @config.reset
64
+
65
+ @config.version.should == '0.9.6'
66
+ end
67
+ end
32
68
 
33
69
  describe "parse_config method" do
34
70
  before :each do
@@ -50,7 +86,9 @@ describe ThinkingSphinx::Configuration do
50
86
  "charset_table" => "table",
51
87
  "ignore_chars" => "e",
52
88
  "searchd_binary_name" => "sphinx-searchd",
53
- "indexer_binary_name" => "sphinx-indexer"
89
+ "indexer_binary_name" => "sphinx-indexer",
90
+ "index_exact_words" => true,
91
+ "indexed_models" => ['Alpha', 'Beta']
54
92
  }
55
93
  }
56
94
 
@@ -80,6 +118,8 @@ describe ThinkingSphinx::Configuration do
80
118
  config.app_root = "/here/somewhere"
81
119
  end
82
120
  ThinkingSphinx::Configuration.instance.app_root.should == "/here/somewhere"
121
+
122
+ ThinkingSphinx::Configuration.instance.reset
83
123
  end
84
124
  end
85
125
 
@@ -129,65 +169,11 @@ describe ThinkingSphinx::Configuration do
129
169
  end
130
170
  end
131
171
 
132
- describe "#load_models" do
133
- before :each do
134
- @config = ThinkingSphinx::Configuration.instance
135
- @config.model_directories = ['']
136
-
137
- @file_name = 'a.rb'
138
- @model_name_lower = 'a'
139
- @class_name = 'A'
140
-
141
- @file_name.stub!(:gsub).and_return(@model_name_lower)
142
- @model_name_lower.stub!(:camelize).and_return(@class_name)
143
- Dir.stub(:[]).and_return([@file_name])
144
- end
145
-
146
- it "should load the files by guessing the file name" do
147
- @class_name.should_receive(:constantize).and_return(true)
148
-
149
- @config.load_models
150
- end
151
-
152
- it "should not raise errors if the model name is nil" do
153
- @file_name.stub!(:gsub).and_return(nil)
154
-
155
- lambda {
156
- @config.load_models
157
- }.should_not raise_error
158
- end
159
-
160
- it "should not raise errors if the file name does not represent a class name" do
161
- @class_name.should_receive(:constantize).and_raise(NameError)
162
-
163
- lambda {
164
- @config.load_models
165
- }.should_not raise_error
166
- end
167
-
168
- it "should retry if the first pass fails and contains a directory" do
169
- @model_name_lower.stub!(:gsub!).and_return(true, nil)
170
- @class_name.stub(:constantize).and_raise(LoadError)
171
- @model_name_lower.should_receive(:camelize).twice
172
-
173
- lambda {
174
- @config.load_models
175
- }.should_not raise_error
176
- end
177
-
178
- it "should catch database errors with a warning" do
179
- @class_name.should_receive(:constantize).and_raise(Mysql::Error)
180
- @config.should_receive(:puts).with('Warning: Error loading a.rb')
181
-
182
- lambda {
183
- @config.load_models
184
- }.should_not raise_error
185
- end
186
- end
187
-
188
172
  it "should insert set index options into the configuration file" do
189
173
  config = ThinkingSphinx::Configuration.instance
174
+
190
175
  ThinkingSphinx::Configuration::IndexOptions.each do |option|
176
+ config.reset
191
177
  config.index_options[option.to_sym] = "something"
192
178
  config.build
193
179
 
@@ -200,15 +186,34 @@ describe ThinkingSphinx::Configuration do
200
186
 
201
187
  it "should insert set source options into the configuration file" do
202
188
  config = ThinkingSphinx::Configuration.instance
189
+ config.reset
190
+
191
+ config.source_options[:sql_query_pre] = ["something"]
203
192
  ThinkingSphinx::Configuration::SourceOptions.each do |option|
204
- config.source_options[option.to_sym] = "something"
193
+ config.source_options[option.to_sym] ||= "something"
205
194
  config.build
206
195
 
207
196
  file = open(config.config_file) { |f| f.read }
208
197
  file.should match(/#{option}\s+= something/)
209
198
 
210
- config.source_options[option.to_sym] = nil
199
+ config.source_options.delete option.to_sym
211
200
  end
201
+
202
+ config.source_options[:sql_query_pre] = nil
203
+ end
204
+
205
+ it "should not blow away delta or utf options if sql pre is specified in config" do
206
+ config = ThinkingSphinx::Configuration.instance
207
+ config.reset
208
+
209
+ config.source_options[:sql_query_pre] = ["a pre query"]
210
+ config.build
211
+ file = open(config.config_file) { |f| f.read }
212
+
213
+ file.should match(/sql_query_pre = a pre query\n\s*sql_query_pre = UPDATE `\w+` SET `delta` = 0 WHERE `delta` = 1/im)
214
+ file.should match(/sql_query_pre = a pre query\n\s*sql_query_pre = \n/im)
215
+
216
+ config.source_options[:sql_query_pre] = nil
212
217
  end
213
218
 
214
219
  it "should set any explicit prefixed or infixed fields" do
@@ -232,6 +237,7 @@ describe ThinkingSphinx::Configuration do
232
237
  @config.address = 'domain.url'
233
238
  @config.port = 3333
234
239
  @config.configuration.searchd.max_matches = 100
240
+ @config.timeout = 1
235
241
  end
236
242
 
237
243
  it "should return an instance of Riddle::Client" do
@@ -249,6 +255,10 @@ describe ThinkingSphinx::Configuration do
249
255
  it "should use the configuration max matches" do
250
256
  @config.client.max_matches.should == 100
251
257
  end
258
+
259
+ it "should use the configuration timeout" do
260
+ @config.client.timeout.should == 1
261
+ end
252
262
  end
253
263
 
254
264
  describe '#models_by_crc' do
@@ -0,0 +1,127 @@
1
+ require 'spec_helper'
2
+
3
+ describe ThinkingSphinx::Context do
4
+ before :each do
5
+ @context = ThinkingSphinx::Context.new
6
+ end
7
+
8
+ describe '#prepare' do
9
+ before :each do
10
+ @config = ThinkingSphinx::Configuration.instance
11
+ @config.model_directories = ['']
12
+
13
+ @file_name = 'a.rb'
14
+ @model_name_lower = 'a'
15
+ @class_name = 'A'
16
+
17
+ @file_name.stub!(:gsub).and_return(@model_name_lower)
18
+ @model_name_lower.stub!(:camelize).and_return(@class_name)
19
+ Dir.stub(:[]).and_return([@file_name])
20
+ end
21
+
22
+ it "should load the files by guessing the file name" do
23
+ @class_name.should_receive(:constantize).and_return(true)
24
+
25
+ @context.prepare
26
+ end
27
+
28
+ it "should not raise errors if the model name is nil" do
29
+ @file_name.stub!(:gsub).and_return(nil)
30
+
31
+ lambda {
32
+ @context.prepare
33
+ }.should_not raise_error
34
+ end
35
+
36
+ it "should not raise errors if the file name does not represent a class name" do
37
+ @class_name.should_receive(:constantize).and_raise(NameError)
38
+
39
+ lambda {
40
+ @context.prepare
41
+ }.should_not raise_error
42
+ end
43
+
44
+ it "should retry if the first pass fails and contains a directory" do
45
+ @model_name_lower.stub!(:gsub!).and_return(true, nil)
46
+ @class_name.stub(:constantize).and_raise(LoadError)
47
+ @model_name_lower.should_receive(:camelize).twice
48
+
49
+ lambda {
50
+ @context.prepare
51
+ }.should_not raise_error
52
+ end
53
+
54
+ it "should catch database errors with a warning" do
55
+ @class_name.should_receive(:constantize).and_raise(Mysql::Error)
56
+ STDERR.stub!(:puts => '')
57
+ STDERR.should_receive(:puts).with('Warning: Error loading a.rb:')
58
+
59
+ lambda {
60
+ @context.prepare
61
+ }.should_not raise_error
62
+ end
63
+
64
+ it "should not load models if they're explicitly set in the configuration" do
65
+ @config.indexed_models = ['Alpha', 'Beta']
66
+ @context.prepare
67
+
68
+ @context.indexed_models.should == ['Alpha', 'Beta']
69
+ end
70
+ end
71
+
72
+ describe '#define_indexes' do
73
+ it "should call define_indexes on all known indexed models" do
74
+ @context.stub!(:indexed_models => ['Alpha', 'Beta'])
75
+ Alpha.should_receive(:define_indexes)
76
+ Beta.should_receive(:define_indexes)
77
+
78
+ @context.define_indexes
79
+ end
80
+ end
81
+
82
+ describe '#add_indexed_model' do
83
+ before :each do
84
+ @context.indexed_models.clear
85
+ end
86
+
87
+ it "should add the model to the collection" do
88
+ @context.add_indexed_model 'Alpha'
89
+
90
+ @context.indexed_models.should == ['Alpha']
91
+ end
92
+
93
+ it "should not duplicate models in the collection" do
94
+ @context.add_indexed_model 'Alpha'
95
+ @context.add_indexed_model 'Alpha'
96
+
97
+ @context.indexed_models.should == ['Alpha']
98
+ end
99
+
100
+ it "should keep the collection in alphabetical order" do
101
+ @context.add_indexed_model 'Beta'
102
+ @context.add_indexed_model 'Alpha'
103
+
104
+ @context.indexed_models.should == ['Alpha', 'Beta']
105
+ end
106
+
107
+ it "should translate classes to their names" do
108
+ @context.add_indexed_model Alpha
109
+
110
+ @context.indexed_models.should == ['Alpha']
111
+ end
112
+ end
113
+
114
+ describe '#superclass_indexed_models' do
115
+ it "should return indexed model names" do
116
+ @context.stub!(:indexed_models => ['Alpha', 'Beta'])
117
+
118
+ @context.superclass_indexed_models.should == ['Alpha', 'Beta']
119
+ end
120
+
121
+ it "should not include classes which have indexed superclasses" do
122
+ @context.stub!(:indexed_models => ['Parent', 'Person'])
123
+
124
+ @context.superclass_indexed_models.should == ['Person']
125
+ end
126
+ end
127
+ end