skalee-thinking-sphinx 1.3.14.1

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 (199) hide show
  1. data/LICENCE +20 -0
  2. data/README.textile +201 -0
  3. data/Rakefile +3 -0
  4. data/VERSION +1 -0
  5. data/contribute.rb +385 -0
  6. data/cucumber.yml +1 -0
  7. data/features/abstract_inheritance.feature +10 -0
  8. data/features/alternate_primary_key.feature +27 -0
  9. data/features/attribute_transformation.feature +22 -0
  10. data/features/attribute_updates.feature +51 -0
  11. data/features/deleting_instances.feature +67 -0
  12. data/features/direct_attributes.feature +11 -0
  13. data/features/excerpts.feature +13 -0
  14. data/features/extensible_delta_indexing.feature +9 -0
  15. data/features/facets.feature +82 -0
  16. data/features/facets_across_model.feature +29 -0
  17. data/features/handling_edits.feature +92 -0
  18. data/features/retry_stale_indexes.feature +24 -0
  19. data/features/searching_across_models.feature +20 -0
  20. data/features/searching_by_index.feature +40 -0
  21. data/features/searching_by_model.feature +175 -0
  22. data/features/searching_with_find_arguments.feature +56 -0
  23. data/features/sphinx_detection.feature +25 -0
  24. data/features/sphinx_scopes.feature +42 -0
  25. data/features/step_definitions/alpha_steps.rb +16 -0
  26. data/features/step_definitions/beta_steps.rb +7 -0
  27. data/features/step_definitions/common_steps.rb +188 -0
  28. data/features/step_definitions/extensible_delta_indexing_steps.rb +7 -0
  29. data/features/step_definitions/facet_steps.rb +96 -0
  30. data/features/step_definitions/find_arguments_steps.rb +36 -0
  31. data/features/step_definitions/gamma_steps.rb +15 -0
  32. data/features/step_definitions/scope_steps.rb +15 -0
  33. data/features/step_definitions/search_steps.rb +89 -0
  34. data/features/step_definitions/sphinx_steps.rb +35 -0
  35. data/features/sti_searching.feature +19 -0
  36. data/features/support/database.example.yml +3 -0
  37. data/features/support/db/.gitignore +1 -0
  38. data/features/support/db/fixtures/alphas.rb +10 -0
  39. data/features/support/db/fixtures/authors.rb +1 -0
  40. data/features/support/db/fixtures/betas.rb +10 -0
  41. data/features/support/db/fixtures/boxes.rb +9 -0
  42. data/features/support/db/fixtures/categories.rb +1 -0
  43. data/features/support/db/fixtures/cats.rb +3 -0
  44. data/features/support/db/fixtures/comments.rb +24 -0
  45. data/features/support/db/fixtures/developers.rb +29 -0
  46. data/features/support/db/fixtures/dogs.rb +3 -0
  47. data/features/support/db/fixtures/extensible_betas.rb +10 -0
  48. data/features/support/db/fixtures/foxes.rb +3 -0
  49. data/features/support/db/fixtures/gammas.rb +10 -0
  50. data/features/support/db/fixtures/music.rb +4 -0
  51. data/features/support/db/fixtures/people.rb +1001 -0
  52. data/features/support/db/fixtures/posts.rb +6 -0
  53. data/features/support/db/fixtures/robots.rb +14 -0
  54. data/features/support/db/fixtures/tags.rb +27 -0
  55. data/features/support/db/migrations/create_alphas.rb +8 -0
  56. data/features/support/db/migrations/create_animals.rb +5 -0
  57. data/features/support/db/migrations/create_authors.rb +3 -0
  58. data/features/support/db/migrations/create_authors_posts.rb +6 -0
  59. data/features/support/db/migrations/create_betas.rb +5 -0
  60. data/features/support/db/migrations/create_boxes.rb +5 -0
  61. data/features/support/db/migrations/create_categories.rb +3 -0
  62. data/features/support/db/migrations/create_comments.rb +10 -0
  63. data/features/support/db/migrations/create_developers.rb +9 -0
  64. data/features/support/db/migrations/create_extensible_betas.rb +5 -0
  65. data/features/support/db/migrations/create_gammas.rb +3 -0
  66. data/features/support/db/migrations/create_genres.rb +3 -0
  67. data/features/support/db/migrations/create_music.rb +6 -0
  68. data/features/support/db/migrations/create_people.rb +13 -0
  69. data/features/support/db/migrations/create_posts.rb +5 -0
  70. data/features/support/db/migrations/create_robots.rb +4 -0
  71. data/features/support/db/migrations/create_taggings.rb +5 -0
  72. data/features/support/db/migrations/create_tags.rb +4 -0
  73. data/features/support/env.rb +21 -0
  74. data/features/support/lib/generic_delta_handler.rb +8 -0
  75. data/features/support/models/alpha.rb +22 -0
  76. data/features/support/models/animal.rb +5 -0
  77. data/features/support/models/author.rb +3 -0
  78. data/features/support/models/beta.rb +8 -0
  79. data/features/support/models/box.rb +8 -0
  80. data/features/support/models/cat.rb +3 -0
  81. data/features/support/models/category.rb +4 -0
  82. data/features/support/models/comment.rb +10 -0
  83. data/features/support/models/developer.rb +16 -0
  84. data/features/support/models/dog.rb +3 -0
  85. data/features/support/models/extensible_beta.rb +9 -0
  86. data/features/support/models/fox.rb +5 -0
  87. data/features/support/models/gamma.rb +5 -0
  88. data/features/support/models/genre.rb +3 -0
  89. data/features/support/models/medium.rb +5 -0
  90. data/features/support/models/music.rb +8 -0
  91. data/features/support/models/person.rb +23 -0
  92. data/features/support/models/post.rb +21 -0
  93. data/features/support/models/robot.rb +12 -0
  94. data/features/support/models/tag.rb +3 -0
  95. data/features/support/models/tagging.rb +4 -0
  96. data/ginger_scenarios.rb +28 -0
  97. data/init.rb +5 -0
  98. data/install.rb +5 -0
  99. data/lib/cucumber/thinking_sphinx/external_world.rb +8 -0
  100. data/lib/cucumber/thinking_sphinx/internal_world.rb +126 -0
  101. data/lib/cucumber/thinking_sphinx/sql_logger.rb +20 -0
  102. data/lib/thinking_sphinx/active_record/attribute_updates.rb +19 -0
  103. data/lib/thinking_sphinx/active_record/delta.rb +47 -0
  104. data/lib/thinking_sphinx/active_record/has_many_association.rb +29 -0
  105. data/lib/thinking_sphinx/active_record/scopes.rb +75 -0
  106. data/lib/thinking_sphinx/active_record.rb +348 -0
  107. data/lib/thinking_sphinx/adapters/abstract_adapter.rb +42 -0
  108. data/lib/thinking_sphinx/adapters/mysql_adapter.rb +54 -0
  109. data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +143 -0
  110. data/lib/thinking_sphinx/association.rb +164 -0
  111. data/lib/thinking_sphinx/attribute.rb +362 -0
  112. data/lib/thinking_sphinx/auto_version.rb +22 -0
  113. data/lib/thinking_sphinx/class_facet.rb +15 -0
  114. data/lib/thinking_sphinx/configuration.rb +300 -0
  115. data/lib/thinking_sphinx/context.rb +68 -0
  116. data/lib/thinking_sphinx/core/array.rb +7 -0
  117. data/lib/thinking_sphinx/core/string.rb +15 -0
  118. data/lib/thinking_sphinx/deltas/default_delta.rb +62 -0
  119. data/lib/thinking_sphinx/deltas.rb +28 -0
  120. data/lib/thinking_sphinx/deploy/capistrano.rb +100 -0
  121. data/lib/thinking_sphinx/excerpter.rb +22 -0
  122. data/lib/thinking_sphinx/facet.rb +125 -0
  123. data/lib/thinking_sphinx/facet_search.rb +136 -0
  124. data/lib/thinking_sphinx/field.rb +82 -0
  125. data/lib/thinking_sphinx/index/builder.rb +296 -0
  126. data/lib/thinking_sphinx/index/faux_column.rb +110 -0
  127. data/lib/thinking_sphinx/index.rb +157 -0
  128. data/lib/thinking_sphinx/property.rb +162 -0
  129. data/lib/thinking_sphinx/rails_additions.rb +150 -0
  130. data/lib/thinking_sphinx/search.rb +769 -0
  131. data/lib/thinking_sphinx/search_methods.rb +439 -0
  132. data/lib/thinking_sphinx/source/internal_properties.rb +46 -0
  133. data/lib/thinking_sphinx/source/sql.rb +130 -0
  134. data/lib/thinking_sphinx/source.rb +153 -0
  135. data/lib/thinking_sphinx/tasks.rb +131 -0
  136. data/lib/thinking_sphinx/test.rb +52 -0
  137. data/lib/thinking_sphinx.rb +225 -0
  138. data/rails/init.rb +16 -0
  139. data/recipes/thinking_sphinx.rb +3 -0
  140. data/spec/fixtures/data.sql +32 -0
  141. data/spec/fixtures/database.yml.default +3 -0
  142. data/spec/fixtures/models.rb +145 -0
  143. data/spec/fixtures/structure.sql +125 -0
  144. data/spec/spec_helper.rb +60 -0
  145. data/spec/sphinx_helper.rb +81 -0
  146. data/spec/thinking_sphinx/active_record/delta_spec.rb +128 -0
  147. data/spec/thinking_sphinx/active_record/has_many_association_spec.rb +55 -0
  148. data/spec/thinking_sphinx/active_record/scopes_spec.rb +177 -0
  149. data/spec/thinking_sphinx/active_record_spec.rb +622 -0
  150. data/spec/thinking_sphinx/association_spec.rb +239 -0
  151. data/spec/thinking_sphinx/attribute_spec.rb +570 -0
  152. data/spec/thinking_sphinx/auto_version_spec.rb +39 -0
  153. data/spec/thinking_sphinx/configuration_spec.rb +234 -0
  154. data/spec/thinking_sphinx/context_spec.rb +119 -0
  155. data/spec/thinking_sphinx/core/array_spec.rb +9 -0
  156. data/spec/thinking_sphinx/core/string_spec.rb +9 -0
  157. data/spec/thinking_sphinx/excerpter_spec.rb +57 -0
  158. data/spec/thinking_sphinx/facet_search_spec.rb +176 -0
  159. data/spec/thinking_sphinx/facet_spec.rb +333 -0
  160. data/spec/thinking_sphinx/field_spec.rb +154 -0
  161. data/spec/thinking_sphinx/index/builder_spec.rb +479 -0
  162. data/spec/thinking_sphinx/index/faux_column_spec.rb +30 -0
  163. data/spec/thinking_sphinx/index_spec.rb +183 -0
  164. data/spec/thinking_sphinx/rails_additions_spec.rb +203 -0
  165. data/spec/thinking_sphinx/search_methods_spec.rb +152 -0
  166. data/spec/thinking_sphinx/search_spec.rb +1181 -0
  167. data/spec/thinking_sphinx/source_spec.rb +235 -0
  168. data/spec/thinking_sphinx_spec.rb +204 -0
  169. data/tasks/distribution.rb +41 -0
  170. data/tasks/rails.rake +1 -0
  171. data/tasks/testing.rb +72 -0
  172. data/vendor/after_commit/.gitignore +1 -0
  173. data/vendor/after_commit/lib/after_commit/active_record.rb +122 -0
  174. data/vendor/after_commit/lib/after_commit/connection_adapters.rb +168 -0
  175. data/vendor/after_commit/lib/after_commit/test_bypass.rb +30 -0
  176. data/vendor/after_commit/lib/after_commit.rb +70 -0
  177. data/vendor/riddle/lib/riddle/0.9.8.rb +1 -0
  178. data/vendor/riddle/lib/riddle/0.9.9/client/filter.rb +22 -0
  179. data/vendor/riddle/lib/riddle/0.9.9/client.rb +49 -0
  180. data/vendor/riddle/lib/riddle/0.9.9/configuration/searchd.rb +28 -0
  181. data/vendor/riddle/lib/riddle/0.9.9.rb +7 -0
  182. data/vendor/riddle/lib/riddle/auto_version.rb +11 -0
  183. data/vendor/riddle/lib/riddle/client/filter.rb +62 -0
  184. data/vendor/riddle/lib/riddle/client/message.rb +70 -0
  185. data/vendor/riddle/lib/riddle/client/response.rb +94 -0
  186. data/vendor/riddle/lib/riddle/client.rb +745 -0
  187. data/vendor/riddle/lib/riddle/configuration/distributed_index.rb +49 -0
  188. data/vendor/riddle/lib/riddle/configuration/index.rb +149 -0
  189. data/vendor/riddle/lib/riddle/configuration/indexer.rb +20 -0
  190. data/vendor/riddle/lib/riddle/configuration/remote_index.rb +17 -0
  191. data/vendor/riddle/lib/riddle/configuration/searchd.rb +28 -0
  192. data/vendor/riddle/lib/riddle/configuration/section.rb +43 -0
  193. data/vendor/riddle/lib/riddle/configuration/source.rb +23 -0
  194. data/vendor/riddle/lib/riddle/configuration/sql_source.rb +53 -0
  195. data/vendor/riddle/lib/riddle/configuration/xml_source.rb +29 -0
  196. data/vendor/riddle/lib/riddle/configuration.rb +33 -0
  197. data/vendor/riddle/lib/riddle/controller.rb +78 -0
  198. data/vendor/riddle/lib/riddle.rb +51 -0
  199. metadata +312 -0
@@ -0,0 +1,25 @@
1
+ Feature: Checking whether Sphinx is running or not
2
+ In order to avoid unnecessary errors
3
+ Thinking Sphinx
4
+ Should be able to determine whether Sphinx is running or not
5
+
6
+ Scenario: Checking Sphinx's status
7
+ Given Sphinx is running
8
+ Then Sphinx should be running
9
+
10
+ When I stop Sphinx
11
+ And I wait for Sphinx to catch up
12
+ Then Sphinx should not be running
13
+
14
+ When I start Sphinx
15
+ And I wait for Sphinx to catch up
16
+ Then Sphinx should be running
17
+
18
+ Given Sphinx is running
19
+ When I kill the Sphinx process
20
+ And I wait for Sphinx to catch up
21
+ Then Sphinx should not be running
22
+
23
+ When I start Sphinx again
24
+ And I wait for Sphinx to catch up
25
+ Then Sphinx should be running again
@@ -0,0 +1,42 @@
1
+ Feature: Sphinx Scopes
2
+
3
+ Scenario: Single Scope
4
+ Given Sphinx is running
5
+ And I am searching on people
6
+ When I use the with_first_name scope set to "Andrew"
7
+ Then I should get 7 results
8
+
9
+ Scenario: Two Field Scopes
10
+ Given Sphinx is running
11
+ And I am searching on people
12
+ When I use the with_first_name scope set to "Andrew"
13
+ And I use the with_last_name scope set to "Byrne"
14
+ Then I should get 1 result
15
+
16
+ Scenario: Mixing Filter and Field Scopes
17
+ Given Sphinx is running
18
+ And I am searching on people
19
+ When I use the with_first_name scope set to "Andrew"
20
+ And I use the with_id scope set to 99
21
+ Then I should get 1 result
22
+
23
+ Scenario: Mixing Field and ID Scopes
24
+ Given Sphinx is running
25
+ And I am searching on people
26
+ When I use the with_first_name scope set to "Andrew"
27
+ And I use the ids_only scope
28
+ Then I should get 7 results
29
+ And I should have an array of integers
30
+
31
+ Scenario: Non-field/filter Scopes
32
+ Given Sphinx is running
33
+ And I am searching on people
34
+ When I use the ids_only scope
35
+ Then I should have an array of integers
36
+
37
+ Scenario: Counts with scopes
38
+ Given Sphinx is running
39
+ And I am searching on people
40
+ When I use the with_first_name scope set to "Andrew"
41
+ And I am retrieving the scoped result count
42
+ Then I should get a value of 7
@@ -0,0 +1,16 @@
1
+ When /^I create a new alpha named (\w+)$/ do |name|
2
+ Alpha.create!(:name => name, :value => 101)
3
+ end
4
+
5
+ When /^I change the (\w+) of alpha (\w+) to (\w+)$/ do |column, name, replacement|
6
+ Alpha.find_by_name(name).update_attributes(column.to_sym => replacement)
7
+ end
8
+
9
+ When /^I filter by active alphas$/ do
10
+ @results = nil
11
+ @with[:active] = true
12
+ end
13
+
14
+ When /^I flag alpha (\w+) as inactive$/ do |name|
15
+ Alpha.find_by_name(name).update_attributes(:active => false)
16
+ end
@@ -0,0 +1,7 @@
1
+ When /^I create a new beta named (\w+)$/ do |name|
2
+ Beta.create!(:name => name, :value => 101)
3
+ end
4
+
5
+ When /^I change the (\w+) of beta (\w+) to (\w+)$/ do |column, name, replacement|
6
+ Beta.find_by_name(name).update_attributes(column.to_sym => replacement)
7
+ end
@@ -0,0 +1,188 @@
1
+ Before do
2
+ $queries_executed = []
3
+
4
+ @model = nil
5
+ @method = :search
6
+ @query = ""
7
+ @conditions = {}
8
+ @with = {}
9
+ @without = {}
10
+ @with_all = {}
11
+ @options = {}
12
+ @results = nil
13
+
14
+ Given "updates are enabled"
15
+ end
16
+
17
+ Given /^I am searching on (.+)$/ do |model|
18
+ @model = model.gsub(/\s/, '_').singularize.camelize.constantize
19
+ end
20
+
21
+ Given /^updates are (\w+)$/ do |action|
22
+ ThinkingSphinx.updates_enabled = (action == "enabled")
23
+ end
24
+
25
+ When /^I am searching for ids$/ do
26
+ @results = nil
27
+ @method = :search_for_ids
28
+ end
29
+
30
+ When /^I use index (.+)$/ do |index|
31
+ @results = nil
32
+ @options[:index] = index
33
+ end
34
+
35
+ When /^I am retrieving the result count$/ do
36
+ @result = nil
37
+ @method = @model ? :search_count : :count
38
+ end
39
+
40
+ When /^I search$/ do
41
+ @results = nil
42
+ end
43
+
44
+ When /^I search for (\w+)$/ do |query|
45
+ @results = nil
46
+ @query = query
47
+ end
48
+
49
+ When /^I search for "([^\"]*)"$/ do |query|
50
+ @results = nil
51
+ @query = query
52
+ end
53
+
54
+ When /^I search for (\w+) on (\w+)$/ do |query, field|
55
+ @results = nil
56
+ @conditions[field.to_sym] = query
57
+ end
58
+
59
+ When /^I output the raw result data$/ do
60
+ puts results.results.inspect
61
+ end
62
+
63
+ When /^I clear existing filters$/ do
64
+ @with = {}
65
+ @without = {}
66
+ @with_all = {}
67
+ end
68
+
69
+ When /^I filter by (\w+) on (\w+)$/ do |filter, attribute|
70
+ @results = nil
71
+ @with[attribute.to_sym] = filter.to_i
72
+ end
73
+
74
+ When /^I filter by (\d+) and (\d+) on (\w+)$/ do |value_one, value_two, attribute|
75
+ @results = nil
76
+ @with[attribute.to_sym] = [value_one.to_i, value_two.to_i]
77
+ end
78
+
79
+ When /^I filter by both (\d+) and (\d+) on (\w+)$/ do |value_one, value_two, attribute|
80
+ @results = nil
81
+ @with_all[attribute.to_sym] = [value_one.to_i, value_two.to_i]
82
+ end
83
+
84
+ When /^I filter between ([\d\.]+) and ([\d\.]+) on (\w+)$/ do |first, last, attribute|
85
+ @results = nil
86
+ if first[/\./].nil? && last[/\./].nil?
87
+ @with[attribute.to_sym] = first.to_i..last.to_i
88
+ else
89
+ @with[attribute.to_sym] = first.to_f..last.to_f
90
+ end
91
+ end
92
+
93
+ When /^I filter between (\d+) and (\d+) days ago on (\w+)$/ do |last, first, attribute|
94
+ @results = nil
95
+ @with[attribute.to_sym] = first.to_i.days.ago..last.to_i.days.ago
96
+ end
97
+
98
+ When /^I filter by (\w+) between (\d+) and (\d+)$/ do |attribute, first, last|
99
+ @results = nil
100
+ @with[attribute.to_sym] = Time.utc(first.to_i)..Time.utc(last.to_i)
101
+ end
102
+
103
+ When /^I order by (\w+)$/ do |attribute|
104
+ @results = nil
105
+ @options[:order] = attribute.to_sym
106
+ end
107
+
108
+ When /^I order by "([^\"]+)"$/ do |str|
109
+ @results = nil
110
+ @options[:order] = str
111
+ end
112
+
113
+ When /^I group results by the (\w+) attribute$/ do |attribute|
114
+ @results = nil
115
+ @options[:group_function] = :attr
116
+ @options[:group_by] = attribute
117
+ end
118
+
119
+ When /^I set match mode to (\w+)$/ do |match_mode|
120
+ @results = nil
121
+ @options[:match_mode] = match_mode.to_sym
122
+ end
123
+
124
+ When /^I set per page to (\d+)$/ do |per_page|
125
+ @results = nil
126
+ @options[:per_page] = per_page.to_i
127
+ end
128
+
129
+ When /^I set retry stale to (\w+)$/ do |retry_stale|
130
+ @results = nil
131
+ @options[:retry_stale] = case retry_stale
132
+ when "true" then true
133
+ when "false" then false
134
+ else retry_stale.to_i
135
+ end
136
+ end
137
+
138
+ When /^I destroy (\w+) (\w+)$/ do |model, name|
139
+ model.gsub(/\s/, '_').camelize.
140
+ constantize.find_by_name(name).destroy
141
+ end
142
+
143
+ Then /^the (\w+) of each result should indicate order$/ do |attribute|
144
+ results.inject(nil) do |prev, current|
145
+ unless prev.nil?
146
+ current.send(attribute.to_sym).should >= prev.send(attribute.to_sym)
147
+ end
148
+
149
+ current
150
+ end
151
+ end
152
+
153
+ Then /^I can iterate by result and (\w+)$/ do |attribute|
154
+ iteration = lambda { |result, attr_value|
155
+ result.should be_kind_of(@model)
156
+ unless attribute == "group" && attr_value.nil?
157
+ attr_value.should be_kind_of(Integer)
158
+ end
159
+ }
160
+
161
+ results.send("each_with_#{attribute}", &iteration)
162
+ end
163
+
164
+ Then /^I should get (\d+) results?$/ do |count|
165
+ results.length.should == count.to_i
166
+ end
167
+
168
+ Then /^I should not get (\d+) results?$/ do |count|
169
+ results.length.should_not == count.to_i
170
+ end
171
+
172
+ Then /^I should get as many results as there are (.+)$/ do |model|
173
+ results.length.should == model.gsub(/\s/, '_').singularize.camelize.
174
+ constantize.count
175
+ end
176
+
177
+ def results
178
+ @results ||= (@model || ThinkingSphinx).send(
179
+ @method,
180
+ @query,
181
+ @options.merge(
182
+ :conditions => @conditions,
183
+ :with => @with,
184
+ :without => @without,
185
+ :with_all => @with_all
186
+ )
187
+ )
188
+ end
@@ -0,0 +1,7 @@
1
+ When /I change the name of extensible beta (\w+) to (\w+)$/ do |current, replacement|
2
+ ExtensibleBeta.find_by_name(current).update_attributes(:name => replacement)
3
+ end
4
+
5
+ Then /^the generic delta handler should handle the delta indexing$/ do
6
+ ExtensibleBeta.find(:first, :conditions => {:changed_by_generic => true}).should_not be_nil
7
+ end
@@ -0,0 +1,96 @@
1
+ When /^I am requesting facet results$/ do
2
+ @results = nil
3
+ @method = :facets
4
+ end
5
+
6
+ When /^I am requesting just the facet (\w+)$/ do |facet|
7
+ @results = nil
8
+ @options[:facets] = facet.downcase.to_sym
9
+ end
10
+
11
+ When /^I am requesting just the facets (\w+) and (\w+)$/ do |one, two|
12
+ @results = nil
13
+ @options[:facets] = [one.downcase.to_sym, two.downcase.to_sym]
14
+ end
15
+
16
+ When "I want classes included" do
17
+ @options[:class_facet] = true
18
+ end
19
+
20
+ When "I don't want classes included" do
21
+ @options[:class_facet] = false
22
+ end
23
+
24
+ When "I want all possible attributes" do
25
+ @options[:all_facets] = true
26
+ end
27
+
28
+ When /^I drill down where (\w+) is (\w+)$/ do |facet, value|
29
+ @results = results.for(facet.downcase.to_sym => value)
30
+ end
31
+
32
+ When /^I drill down where (\w+) is (\w+) and (\w+) is (\w+)$/ do |facet_one, value_one, facet_two, value_two|
33
+ value_one = value_one.to_i unless value_one[/^\d+$/].nil?
34
+ value_two = value_two.to_i unless value_two[/^\d+$/].nil?
35
+
36
+ @results = results.for(
37
+ facet_one.downcase.to_sym => value_one,
38
+ facet_two.downcase.to_sym => value_two
39
+ )
40
+ end
41
+
42
+ When /^I drill down where ([\w_]+) includes the id of tag (\w+)$/ do |facet, text|
43
+ tag = Tag.find_by_text(text)
44
+ @results = results.for(facet.downcase.to_sym => tag.id)
45
+ end
46
+
47
+ When /^I drill down where ([\w_]+) includes the id of tags (\w+) or (\w+)$/ do |facet, text_one, text_two|
48
+ tag_one = Tag.find_by_text(text_one)
49
+ tag_two = Tag.find_by_text(text_two)
50
+ @results = results.for(facet.downcase.to_sym => [tag_one.id, tag_two.id])
51
+ end
52
+
53
+ Then "I should have valid facet results" do
54
+ results.should be_kind_of(Hash)
55
+ results.values.each { |value| value.should be_kind_of(Hash) }
56
+ end
57
+
58
+ Then /^I should have (\d+) facets?$/ do |count|
59
+ results.keys.length.should == count.to_i
60
+ end
61
+
62
+ Then /^I should have the facet ([\w_\s]+)$/ do |name|
63
+ results[facet_name(name)].should be_kind_of(Hash)
64
+ end
65
+
66
+ Then /^I should not have the facet ([\w_\s]+)$/ do |name|
67
+ results.keys.should_not include(facet_name(name))
68
+ end
69
+
70
+ Then /^the ([\w_\s]+) facet should have an? "([\w\s_]+)" key with (\d+) hits$/ do |name, key, hit_count|
71
+ facet_name = facet_name name
72
+ results[facet_name].keys.should include(key)
73
+ results[facet_name][key].should eql(hit_count.to_i)
74
+ end
75
+
76
+ Then /^the ([\w_\s]+) facet should have an? "(\w+)" key$/ do |name, key|
77
+ results[facet_name(name)].keys.should include(key)
78
+ end
79
+
80
+ Then /^the ([\w_\s]+) facet should have an? (\d+\.?\d*) key$/ do |name, key|
81
+ if key[/\./]
82
+ key = key.to_f
83
+ else
84
+ key = key.to_i
85
+ end
86
+
87
+ results[facet_name(name)].keys.should include(key)
88
+ end
89
+
90
+ Then /^the ([\w\s]+) facet should have (\d+) keys$/ do |name, count|
91
+ results[facet_name(name)].keys.length.should == count.to_i
92
+ end
93
+
94
+ def facet_name(string)
95
+ string.gsub(/\s/, '').underscore.to_sym
96
+ end
@@ -0,0 +1,36 @@
1
+ When "I include comments" do
2
+ @results = nil
3
+ @options[:include] = :comments
4
+ end
5
+
6
+ When /^I get the first comment$/ do
7
+ @comment = Comment.find(:first)
8
+ end
9
+
10
+ When /^I track queries$/ do
11
+ $queries_executed = []
12
+ end
13
+
14
+ When /^I compare comments$/ do
15
+ results.first.comments.first.should == @comment
16
+ end
17
+
18
+ When /^I select only content$/ do
19
+ @results = nil
20
+ @options[:select] = "id, content"
21
+ end
22
+
23
+ Then /^I should have (\d+) quer[yies]+$/ do |count|
24
+ $queries_executed.length.should == count.to_i
25
+ end
26
+
27
+ Then /^I should not get an error accessing the subject$/ do
28
+ lambda { results.first.subject }.should_not raise_error
29
+ end
30
+
31
+ Then /^I should get an error accessing the subject$/ do
32
+ error_class = NoMethodError
33
+ error_class = ActiveRecord::MissingAttributeError if ActiveRecord.constants.include?("MissingAttributeError")
34
+
35
+ lambda { results.first.subject }.should raise_error(error_class)
36
+ end
@@ -0,0 +1,15 @@
1
+ When /^I destroy gamma (\w+) without callbacks$/ do |name|
2
+ @results = nil
3
+ gamma = Gamma.find_by_name(name)
4
+ Gamma.delete(gamma.id) if gamma
5
+ end
6
+
7
+ Then "I should get a single result of nil" do
8
+ results.to_a.should == [nil]
9
+ end
10
+
11
+ Then /^I should get a single gamma result with a name of (\w+)$/ do |name|
12
+ results.length.should == 1
13
+ results.first.should be_a(Gamma)
14
+ results.first.name.should == name
15
+ end
@@ -0,0 +1,15 @@
1
+ When /^I use the ([\w]+) scope$/ do |scope|
2
+ @results = results.send(scope.to_sym)
3
+ end
4
+
5
+ When /^I use the ([\w]+) scope set to "([^\"]*)"$/ do |scope, value|
6
+ @results = results.send(scope.to_sym, value)
7
+ end
8
+
9
+ When /^I use the ([\w]+) scope set to (\d+)$/ do |scope, int|
10
+ @results = results.send(scope.to_sym, int.to_i)
11
+ end
12
+
13
+ When /^I am retrieving the scoped result count$/ do
14
+ @results = results.search_count
15
+ end
@@ -0,0 +1,89 @@
1
+ # encoding: UTF-8
2
+ When /^I search for the specific id of (\d+) in the (\w+) index$/ do |id, index|
3
+ @id = id.to_i
4
+ @index = index
5
+ end
6
+
7
+ When /^I search for the document id of (\w+) (\w+) in the (\w+) index$/ do |model, name, index|
8
+ model = model.gsub(/\s/, '_').camelize.constantize
9
+ @id = model.find_by_name(name).sphinx_document_id
10
+ @index = index
11
+ end
12
+
13
+ Then "it should exist" do
14
+ ThinkingSphinx::Search.search_for_id(@id, @index).should == true
15
+ end
16
+
17
+ Then "it should not exist" do
18
+ ThinkingSphinx::Search.search_for_id(@id, @index).should == false
19
+ end
20
+
21
+ Then "it should exist if using Rails 2.1 or newer" do
22
+ require 'active_record/version'
23
+ unless ActiveRecord::VERSION::STRING.to_f < 2.1
24
+ ThinkingSphinx::Search.search_for_id(@id, @index).should == true
25
+ end
26
+ end
27
+
28
+ Then "it should not exist if using Rails 2.1 or newer" do
29
+ require 'active_record/version'
30
+ unless ActiveRecord::VERSION::STRING.to_f < 2.1
31
+ ThinkingSphinx::Search.search_for_id(@id, @index).should == false
32
+ end
33
+ end
34
+
35
+ Then /^I can iterate by result and group and count$/ do
36
+ results.each_with_groupby_and_count do |result, group, count|
37
+ result.should be_kind_of(@model)
38
+ count.should be_kind_of(Integer)
39
+ group.should be_kind_of(Integer)
40
+ end
41
+ end
42
+
43
+ Then "each result id should match the corresponding sphinx internal id" do
44
+ results.each_with_sphinx_internal_id do |result, id|
45
+ result.id.should == id
46
+ end
47
+ end
48
+
49
+ Then "I should have an array of integers" do
50
+ results.each do |result|
51
+ result.should be_kind_of(Integer)
52
+ end
53
+ end
54
+
55
+ Then "searching for ids should match the record ids of the normal search results" do
56
+ normal_results = results
57
+
58
+ # reset search, switch method
59
+ @results = nil
60
+ @method = :search_for_ids
61
+
62
+ results.to_a.should == normal_results.collect(&:id)
63
+ end
64
+
65
+ Then /^I should get a value of (\d+)$/ do |count|
66
+ results.should == count.to_i
67
+ end
68
+
69
+ Then /^the (\w+) excerpt of the first result is "(.*)"$/ do |column, string|
70
+ excerpt = results.excerpt_for(results.first.send(column))
71
+ if excerpt.respond_to?(:force_encoding)
72
+ excerpt = excerpt.force_encoding('UTF-8')
73
+ end
74
+
75
+ excerpt.should == string
76
+ end
77
+
78
+ Then /^calling (\w+) on the first result excerpts object should return "(.*)"$/ do |column, string|
79
+ excerpt = results.first.excerpts.send(column)
80
+ if excerpt.respond_to?(:force_encoding)
81
+ excerpt = excerpt.force_encoding('UTF-8')
82
+ end
83
+
84
+ excerpt.should == string
85
+ end
86
+
87
+ Then /^the first result should have a (\w+\s?\w*) of (\d+)$/ do |attribute, value|
88
+ results.first.sphinx_attributes[attribute.gsub(/\s+/, '_')].should == value.to_i
89
+ end
@@ -0,0 +1,35 @@
1
+ Given "Sphinx is running" do
2
+ ThinkingSphinx::Configuration.instance.controller.should be_running
3
+ end
4
+
5
+ When "I kill the Sphinx process" do
6
+ Process.kill(9, ThinkingSphinx.sphinx_pid.to_i)
7
+ end
8
+
9
+ When "I wait for Sphinx to catch up" do
10
+ sleep(0.25)
11
+ end
12
+
13
+ When /^I start Sphinx/ do
14
+ ThinkingSphinx::Configuration.instance.controller.start
15
+ end
16
+
17
+ When "I stop Sphinx" do
18
+ ThinkingSphinx::Configuration.instance.controller.stop
19
+ end
20
+
21
+ When /^I (enable|disable) delta updates$/ do |mode|
22
+ ThinkingSphinx.deltas_enabled = (mode == 'enable')
23
+ end
24
+
25
+ When /^I process the (\w+) index$/ do |index|
26
+ ThinkingSphinx::Configuration.instance.controller.index index
27
+ end
28
+
29
+ Then /^Sphinx should be running/ do
30
+ ThinkingSphinx.sphinx_running?.should be_true
31
+ end
32
+
33
+ Then "Sphinx should not be running" do
34
+ ThinkingSphinx.sphinx_running?.should be_false
35
+ end
@@ -0,0 +1,19 @@
1
+ Feature: Searching via STI model relationships
2
+ In order to be used easy in applications with STI relationships
3
+ Thinking Sphinx
4
+ Should return expected results depending on where in the hierarchy searches are called from.
5
+
6
+ Scenario: Searching from a parent model
7
+ Given Sphinx is running
8
+ And I am searching on animals
9
+ Then I should get as many results as there are animals
10
+
11
+ Scenario: Searching from a child model
12
+ Given Sphinx is running
13
+ And I am searching on cats
14
+ Then I should get as many results as there are cats
15
+
16
+ Scenario: Searching across super and subclass indexes
17
+ Given Sphinx is running
18
+ When I search for "fantastic"
19
+ Then I should get 1 result
@@ -0,0 +1,3 @@
1
+ username: root
2
+ host: localhost
3
+ password:
@@ -0,0 +1 @@
1
+ database.yml
@@ -0,0 +1,10 @@
1
+ Alpha.create :name => "one", :value => 1, :cost => 1.51, :created_on => 1.day.ago.to_date, :created_at => 1.day.ago
2
+ Alpha.create :name => "two", :value => 2, :cost => 2.52, :created_on => 2.day.ago.to_date, :created_at => 2.day.ago
3
+ Alpha.create :name => "three", :value => 3, :cost => 3.53, :created_on => 3.day.ago.to_date, :created_at => 3.day.ago
4
+ Alpha.create :name => "four", :value => 4, :cost => 4.54, :created_on => 4.day.ago.to_date, :created_at => 4.day.ago
5
+ Alpha.create :name => "five", :value => 5, :cost => 5.55, :created_on => 5.day.ago.to_date, :created_at => 5.day.ago
6
+ Alpha.create :name => "six", :value => 6, :cost => 6.56, :created_on => 6.day.ago.to_date, :created_at => 6.day.ago
7
+ Alpha.create :name => "seven", :value => 7, :cost => 7.57, :created_on => 7.day.ago.to_date, :created_at => 7.day.ago
8
+ Alpha.create :name => "eight", :value => 8, :cost => 8.58, :created_on => 8.day.ago.to_date, :created_at => 8.day.ago
9
+ Alpha.create :name => "nine", :value => 9, :cost => 9.59, :created_on => 9.day.ago.to_date, :created_at => 9.day.ago
10
+ Alpha.create :name => "ten", :value => 10, :cost => 10.50, :created_on => 10.day.ago.to_date, :created_at => 10.day.ago
@@ -0,0 +1 @@
1
+ Author.create :name => "William Shakespeare"
@@ -0,0 +1,10 @@
1
+ Beta.create :name => "one", :value => 1
2
+ Beta.create :name => "two", :value => 2
3
+ Beta.create :name => "three", :value => 3
4
+ Beta.create :name => "four", :value => 4
5
+ Beta.create :name => "five", :value => 5
6
+ Beta.create :name => "six", :value => 6
7
+ Beta.create :name => "seven", :value => 7
8
+ Beta.create :name => "eight", :value => 8
9
+ Beta.create :name => "nine", :value => 9
10
+ Beta.create :name => "ten", :value => 10
@@ -0,0 +1,9 @@
1
+ (1..10).each do |i|
2
+ Box.create :width => i, :length => i, :depth => i
3
+ end
4
+
5
+ (11..20).each do |i|
6
+ Box.create :width => i, :length => i+1, :depth => i+2
7
+ end
8
+
9
+ Box.create :width => 5, :length => 5, :depth => nil
@@ -0,0 +1 @@
1
+ Category.create :name => "hello"
@@ -0,0 +1,3 @@
1
+ %w( rogue nat molly jasper moggy ).each do |name|
2
+ Cat.create :name => name
3
+ end
@@ -0,0 +1,24 @@
1
+ # encoding: UTF-8
2
+ Comment.create(
3
+ :name => "Pat",
4
+ :content => "+1",
5
+ :post_id => 1,
6
+ :category_id => 1
7
+ ).update_attribute(:created_at, Time.utc(2001, 01, 01))
8
+
9
+ Comment.create(
10
+ :name => "Menno",
11
+ :content => "Second post!",
12
+ :post_id => 1,
13
+ :category_id => 1
14
+ )
15
+
16
+ Comment.create :name => 'A', :post_id => 1, :content => 'Es un hecho establecido hace demasiado tiempo que un lector se distraerá con el contenido del texto', :category_id => 1
17
+ Comment.create :name => 'B', :post_id => 1, :content => 'de un sitio mientras que mira su diseño. El punto de usar Lorem Ipsum es que tiene una distribución', :category_id => 1
18
+ Comment.create :name => 'C', :post_id => 1, :content => 'más o menos normal de las letras, al contrario de usar textos como por ejemplo "Contenido aquí', :category_id => 1
19
+ Comment.create :name => 'D', :post_id => 1, :content => 'contenido aquí". Estos textos hacen parecerlo un español que se puede leer. Muchos paquetes de', :category_id => 1
20
+ Comment.create :name => 'E', :post_id => 1, :content => 'autoedición y editores de páginas web usan el Lorem Ipsum como su texto por defecto, y al hacer una', :category_id => 1
21
+ Comment.create :name => 'F', :post_id => 1, :content => 'búsqueda de "Lorem Ipsum" va a dar por resultado muchos sitios web que usan este texto si se', :category_id => 1
22
+
23
+ # The one we'll really want to find via Sphinx search
24
+ Comment.create :name => 'G', :post_id => 1, :content => 'Turtle', :category_id => 1