thinking-sphinx 3.1.4 → 6.0.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 (347) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +99 -0
  3. data/.github/actions/test/action.yml +46 -0
  4. data/.github/workflows/ci.yml +75 -0
  5. data/.gitignore +7 -2
  6. data/.travis.yml +31 -16
  7. data/Appraisals +68 -12
  8. data/CHANGELOG.markdown +782 -0
  9. data/Gemfile +13 -4
  10. data/Procfile.support +2 -0
  11. data/README.textile +41 -27
  12. data/Rakefile +2 -0
  13. data/bin/console +15 -0
  14. data/bin/loadsphinx +99 -0
  15. data/bin/testmatrix +48 -0
  16. data/lib/thinking/sphinx.rb +2 -0
  17. data/lib/thinking-sphinx.rb +2 -0
  18. data/lib/thinking_sphinx/active_record/association.rb +2 -0
  19. data/lib/thinking_sphinx/active_record/association_proxy/attribute_finder.rb +3 -1
  20. data/lib/thinking_sphinx/active_record/association_proxy/attribute_matcher.rb +2 -0
  21. data/lib/thinking_sphinx/active_record/association_proxy.rb +3 -2
  22. data/lib/thinking_sphinx/active_record/attribute/sphinx_presenter.rb +3 -1
  23. data/lib/thinking_sphinx/active_record/attribute/type.rb +20 -4
  24. data/lib/thinking_sphinx/active_record/attribute/values.rb +2 -0
  25. data/lib/thinking_sphinx/active_record/attribute.rb +2 -0
  26. data/lib/thinking_sphinx/active_record/base.rb +43 -11
  27. data/lib/thinking_sphinx/active_record/callbacks/association_delta_callbacks.rb +21 -0
  28. data/lib/thinking_sphinx/active_record/callbacks/delete_callbacks.rb +15 -9
  29. data/lib/thinking_sphinx/active_record/callbacks/delta_callbacks.rb +20 -5
  30. data/lib/thinking_sphinx/active_record/callbacks/update_callbacks.rb +18 -4
  31. data/lib/thinking_sphinx/active_record/column.rb +2 -0
  32. data/lib/thinking_sphinx/active_record/column_sql_presenter.rb +7 -1
  33. data/lib/thinking_sphinx/active_record/database_adapters/abstract_adapter.rb +2 -0
  34. data/lib/thinking_sphinx/active_record/database_adapters/mysql_adapter.rb +9 -1
  35. data/lib/thinking_sphinx/active_record/database_adapters/postgresql_adapter.rb +2 -0
  36. data/lib/thinking_sphinx/active_record/database_adapters.rb +3 -1
  37. data/lib/thinking_sphinx/active_record/depolymorph/association_reflection.rb +32 -0
  38. data/lib/thinking_sphinx/active_record/depolymorph/base_reflection.rb +32 -0
  39. data/lib/thinking_sphinx/active_record/depolymorph/conditions_reflection.rb +40 -0
  40. data/lib/thinking_sphinx/active_record/depolymorph/overridden_reflection.rb +50 -0
  41. data/lib/thinking_sphinx/active_record/depolymorph/scoped_reflection.rb +26 -0
  42. data/lib/thinking_sphinx/active_record/field.rb +2 -0
  43. data/lib/thinking_sphinx/active_record/filter_reflection.rb +13 -71
  44. data/lib/thinking_sphinx/active_record/index.rb +7 -5
  45. data/lib/thinking_sphinx/active_record/interpreter.rb +6 -4
  46. data/lib/thinking_sphinx/active_record/join_association.rb +5 -1
  47. data/lib/thinking_sphinx/active_record/log_subscriber.rb +22 -3
  48. data/lib/thinking_sphinx/active_record/polymorpher.rb +2 -0
  49. data/lib/thinking_sphinx/active_record/property.rb +2 -0
  50. data/lib/thinking_sphinx/active_record/property_query.rb +4 -1
  51. data/lib/thinking_sphinx/active_record/property_sql_presenter.rb +2 -0
  52. data/lib/thinking_sphinx/active_record/simple_many_query.rb +2 -0
  53. data/lib/thinking_sphinx/active_record/source_joins.rb +68 -0
  54. data/lib/thinking_sphinx/active_record/sql_builder/clause_builder.rb +2 -0
  55. data/lib/thinking_sphinx/active_record/sql_builder/query.rb +13 -0
  56. data/lib/thinking_sphinx/active_record/sql_builder/statement.rb +2 -0
  57. data/lib/thinking_sphinx/active_record/sql_builder.rb +5 -18
  58. data/lib/thinking_sphinx/active_record/sql_source/template.rb +5 -3
  59. data/lib/thinking_sphinx/active_record/sql_source.rb +35 -9
  60. data/lib/thinking_sphinx/active_record.rb +14 -1
  61. data/lib/thinking_sphinx/attribute_types.rb +72 -0
  62. data/lib/thinking_sphinx/batched_search.rb +2 -0
  63. data/lib/thinking_sphinx/callbacks/appender.rb +63 -0
  64. data/lib/thinking_sphinx/callbacks.rb +29 -0
  65. data/lib/thinking_sphinx/capistrano/v2.rb +2 -0
  66. data/lib/thinking_sphinx/capistrano/v3.rb +2 -0
  67. data/lib/thinking_sphinx/capistrano.rb +2 -0
  68. data/lib/thinking_sphinx/commander.rb +27 -0
  69. data/lib/thinking_sphinx/commands/base.rb +53 -0
  70. data/lib/thinking_sphinx/commands/clear_real_time.rb +22 -0
  71. data/lib/thinking_sphinx/commands/clear_sql.rb +18 -0
  72. data/lib/thinking_sphinx/commands/configure.rb +15 -0
  73. data/lib/thinking_sphinx/commands/index_real_time.rb +15 -0
  74. data/lib/thinking_sphinx/commands/index_sql.rb +25 -0
  75. data/lib/thinking_sphinx/commands/merge.rb +27 -0
  76. data/lib/thinking_sphinx/commands/merge_and_update.rb +57 -0
  77. data/lib/thinking_sphinx/commands/prepare.rb +15 -0
  78. data/lib/thinking_sphinx/commands/rotate.rb +13 -0
  79. data/lib/thinking_sphinx/commands/running.rb +15 -0
  80. data/lib/thinking_sphinx/commands/start_attached.rb +22 -0
  81. data/lib/thinking_sphinx/commands/start_detached.rb +21 -0
  82. data/lib/thinking_sphinx/commands/stop.rb +24 -0
  83. data/lib/thinking_sphinx/commands.rb +20 -0
  84. data/lib/thinking_sphinx/configuration/consistent_ids.rb +2 -0
  85. data/lib/thinking_sphinx/configuration/defaults.rb +2 -0
  86. data/lib/thinking_sphinx/configuration/distributed_indices.rb +3 -1
  87. data/lib/thinking_sphinx/configuration/duplicate_names.rb +36 -0
  88. data/lib/thinking_sphinx/configuration/minimum_fields.rb +17 -12
  89. data/lib/thinking_sphinx/configuration.rb +90 -74
  90. data/lib/thinking_sphinx/connection/client.rb +74 -0
  91. data/lib/thinking_sphinx/connection/jruby.rb +58 -0
  92. data/lib/thinking_sphinx/connection/mri.rb +26 -0
  93. data/lib/thinking_sphinx/connection.rb +13 -114
  94. data/lib/thinking_sphinx/core/field.rb +2 -0
  95. data/lib/thinking_sphinx/core/index.rb +22 -2
  96. data/lib/thinking_sphinx/core/interpreter.rb +2 -0
  97. data/lib/thinking_sphinx/core/property.rb +2 -0
  98. data/lib/thinking_sphinx/core/settings.rb +2 -0
  99. data/lib/thinking_sphinx/core.rb +2 -0
  100. data/lib/thinking_sphinx/deletion.rb +33 -13
  101. data/lib/thinking_sphinx/deltas/default_delta.rb +3 -1
  102. data/lib/thinking_sphinx/deltas/delete_job.rb +16 -4
  103. data/lib/thinking_sphinx/deltas/index_job.rb +14 -2
  104. data/lib/thinking_sphinx/deltas.rb +2 -0
  105. data/lib/thinking_sphinx/distributed/index.rb +25 -3
  106. data/lib/thinking_sphinx/distributed.rb +2 -0
  107. data/lib/thinking_sphinx/errors.rb +47 -3
  108. data/lib/thinking_sphinx/excerpter.rb +2 -0
  109. data/lib/thinking_sphinx/facet.rb +4 -3
  110. data/lib/thinking_sphinx/facet_search.rb +4 -2
  111. data/lib/thinking_sphinx/float_formatter.rb +2 -0
  112. data/lib/thinking_sphinx/frameworks/plain.rb +2 -0
  113. data/lib/thinking_sphinx/frameworks/rails.rb +2 -0
  114. data/lib/thinking_sphinx/frameworks.rb +2 -0
  115. data/lib/thinking_sphinx/guard/file.rb +3 -1
  116. data/lib/thinking_sphinx/guard/files.rb +2 -0
  117. data/lib/thinking_sphinx/guard/none.rb +7 -0
  118. data/lib/thinking_sphinx/guard.rb +3 -0
  119. data/lib/thinking_sphinx/hooks/guard_presence.rb +34 -0
  120. data/lib/thinking_sphinx/index.rb +2 -0
  121. data/lib/thinking_sphinx/index_set.rb +27 -4
  122. data/lib/thinking_sphinx/indexing_strategies/all_at_once.rb +9 -0
  123. data/lib/thinking_sphinx/indexing_strategies/one_at_a_time.rb +16 -0
  124. data/lib/thinking_sphinx/interfaces/base.rb +13 -0
  125. data/lib/thinking_sphinx/interfaces/daemon.rb +27 -0
  126. data/lib/thinking_sphinx/interfaces/real_time.rb +46 -0
  127. data/lib/thinking_sphinx/interfaces/sql.rb +53 -0
  128. data/lib/thinking_sphinx/interfaces.rb +10 -0
  129. data/lib/thinking_sphinx/logger.rb +2 -0
  130. data/lib/thinking_sphinx/masks/group_enumerators_mask.rb +6 -4
  131. data/lib/thinking_sphinx/masks/pagination_mask.rb +2 -0
  132. data/lib/thinking_sphinx/masks/scopes_mask.rb +8 -0
  133. data/lib/thinking_sphinx/masks/weight_enumerator_mask.rb +3 -1
  134. data/lib/thinking_sphinx/masks.rb +2 -0
  135. data/lib/thinking_sphinx/middlewares/active_record_translator.rb +32 -9
  136. data/lib/thinking_sphinx/middlewares/geographer.rb +2 -0
  137. data/lib/thinking_sphinx/middlewares/glazier.rb +14 -1
  138. data/lib/thinking_sphinx/middlewares/ids_only.rb +2 -0
  139. data/lib/thinking_sphinx/middlewares/inquirer.rb +3 -1
  140. data/lib/thinking_sphinx/middlewares/middleware.rb +2 -0
  141. data/lib/thinking_sphinx/middlewares/sphinxql.rb +18 -16
  142. data/lib/thinking_sphinx/middlewares/stale_id_checker.rb +3 -1
  143. data/lib/thinking_sphinx/middlewares/stale_id_filter.rb +4 -2
  144. data/lib/thinking_sphinx/middlewares/valid_options.rb +25 -0
  145. data/lib/thinking_sphinx/middlewares.rb +7 -3
  146. data/lib/thinking_sphinx/panes/attributes_pane.rb +2 -0
  147. data/lib/thinking_sphinx/panes/distance_pane.rb +2 -0
  148. data/lib/thinking_sphinx/panes/excerpts_pane.rb +2 -0
  149. data/lib/thinking_sphinx/panes/weight_pane.rb +3 -1
  150. data/lib/thinking_sphinx/panes.rb +2 -0
  151. data/lib/thinking_sphinx/processor.rb +71 -0
  152. data/lib/thinking_sphinx/query.rb +2 -0
  153. data/lib/thinking_sphinx/railtie.rb +29 -2
  154. data/lib/thinking_sphinx/rake_interface.rb +14 -69
  155. data/lib/thinking_sphinx/real_time/attribute.rb +9 -1
  156. data/lib/thinking_sphinx/real_time/callbacks/real_time_callbacks.rb +17 -7
  157. data/lib/thinking_sphinx/real_time/field.rb +2 -0
  158. data/lib/thinking_sphinx/real_time/index/template.rb +19 -1
  159. data/lib/thinking_sphinx/real_time/index.rb +11 -5
  160. data/lib/thinking_sphinx/real_time/interpreter.rb +10 -6
  161. data/lib/thinking_sphinx/real_time/populator.rb +12 -14
  162. data/lib/thinking_sphinx/real_time/processor.rb +36 -0
  163. data/lib/thinking_sphinx/real_time/property.rb +3 -5
  164. data/lib/thinking_sphinx/real_time/transcribe_instance.rb +38 -0
  165. data/lib/thinking_sphinx/real_time/transcriber.rb +63 -15
  166. data/lib/thinking_sphinx/real_time/translator.rb +39 -0
  167. data/lib/thinking_sphinx/real_time.rb +22 -1
  168. data/lib/thinking_sphinx/scopes.rb +6 -0
  169. data/lib/thinking_sphinx/search/batch_inquirer.rb +2 -0
  170. data/lib/thinking_sphinx/search/context.rb +11 -0
  171. data/lib/thinking_sphinx/search/glaze.rb +2 -0
  172. data/lib/thinking_sphinx/search/merger.rb +2 -0
  173. data/lib/thinking_sphinx/search/query.rb +9 -1
  174. data/lib/thinking_sphinx/search/stale_ids_exception.rb +7 -3
  175. data/lib/thinking_sphinx/search.rb +30 -2
  176. data/lib/thinking_sphinx/settings.rb +128 -0
  177. data/lib/thinking_sphinx/sinatra.rb +3 -1
  178. data/lib/thinking_sphinx/subscribers/populator_subscriber.rb +19 -5
  179. data/lib/thinking_sphinx/tasks.rb +55 -28
  180. data/lib/thinking_sphinx/test.rb +3 -1
  181. data/lib/thinking_sphinx/utf8.rb +2 -0
  182. data/lib/thinking_sphinx/wildcard.rb +3 -1
  183. data/lib/thinking_sphinx/with_output.rb +13 -0
  184. data/lib/thinking_sphinx.rb +35 -4
  185. data/spec/acceptance/association_scoping_spec.rb +7 -5
  186. data/spec/acceptance/attribute_access_spec.rb +29 -12
  187. data/spec/acceptance/attribute_updates_spec.rb +5 -3
  188. data/spec/acceptance/batch_searching_spec.rb +6 -4
  189. data/spec/acceptance/big_integers_spec.rb +9 -7
  190. data/spec/acceptance/excerpts_spec.rb +11 -10
  191. data/spec/acceptance/facets_spec.rb +29 -16
  192. data/spec/acceptance/geosearching_spec.rb +22 -10
  193. data/spec/acceptance/grouping_by_attributes_spec.rb +30 -28
  194. data/spec/acceptance/index_options_spec.rb +18 -16
  195. data/spec/acceptance/indexing_spec.rb +5 -3
  196. data/spec/acceptance/merging_spec.rb +90 -0
  197. data/spec/acceptance/paginating_search_results_spec.rb +21 -3
  198. data/spec/acceptance/real_time_updates_spec.rb +103 -5
  199. data/spec/acceptance/remove_deleted_records_spec.rb +64 -8
  200. data/spec/acceptance/search_counts_spec.rb +4 -2
  201. data/spec/acceptance/search_for_just_ids_spec.rb +4 -2
  202. data/spec/acceptance/searching_across_models_spec.rb +15 -6
  203. data/spec/acceptance/searching_across_schemas_spec.rb +12 -10
  204. data/spec/acceptance/searching_on_fields_spec.rb +11 -9
  205. data/spec/acceptance/searching_with_filters_spec.rb +35 -20
  206. data/spec/acceptance/searching_with_sti_spec.rb +11 -9
  207. data/spec/acceptance/searching_within_a_model_spec.rb +44 -17
  208. data/spec/acceptance/sorting_search_results_spec.rb +21 -19
  209. data/spec/acceptance/spec_helper.rb +2 -13
  210. data/spec/acceptance/specifying_sql_spec.rb +118 -62
  211. data/spec/acceptance/sphinx_scopes_spec.rb +30 -21
  212. data/spec/acceptance/sql_deltas_spec.rb +35 -9
  213. data/spec/acceptance/support/database_cleaner.rb +3 -1
  214. data/spec/acceptance/support/sphinx_controller.rb +25 -9
  215. data/spec/acceptance/support/sphinx_helpers.rb +17 -2
  216. data/spec/acceptance/suspended_deltas_spec.rb +14 -12
  217. data/spec/fixtures/database.yml +1 -1
  218. data/spec/internal/app/indices/admin_person_index.rb +6 -0
  219. data/spec/internal/app/indices/album_index.rb +9 -0
  220. data/spec/internal/app/indices/animal_index.rb +2 -0
  221. data/spec/internal/app/indices/article_index.rb +10 -3
  222. data/spec/internal/app/indices/bird_index.rb +2 -0
  223. data/spec/internal/app/indices/book_index.rb +4 -1
  224. data/spec/internal/app/indices/car_index.rb +2 -0
  225. data/spec/internal/app/indices/city_index.rb +2 -0
  226. data/spec/internal/app/indices/colour_index.rb +7 -0
  227. data/spec/internal/app/indices/product_index.rb +3 -2
  228. data/spec/internal/app/indices/tee_index.rb +3 -1
  229. data/spec/internal/app/indices/user_index.rb +2 -0
  230. data/spec/internal/app/models/admin/person.rb +6 -0
  231. data/spec/internal/app/models/album.rb +25 -0
  232. data/spec/internal/app/models/animal.rb +3 -0
  233. data/spec/internal/app/models/article.rb +4 -0
  234. data/spec/internal/app/models/bird.rb +3 -0
  235. data/spec/internal/app/models/book.rb +9 -5
  236. data/spec/internal/app/models/car.rb +3 -1
  237. data/spec/internal/app/models/categorisation.rb +10 -1
  238. data/spec/internal/app/models/category.rb +2 -0
  239. data/spec/internal/app/models/city.rb +4 -0
  240. data/spec/internal/app/models/colour.rb +4 -0
  241. data/spec/internal/app/models/event.rb +2 -0
  242. data/spec/internal/app/models/flightless_bird.rb +2 -0
  243. data/spec/internal/app/models/genre.rb +2 -0
  244. data/spec/internal/app/models/hardcover.rb +2 -0
  245. data/spec/internal/app/models/mammal.rb +2 -0
  246. data/spec/internal/app/models/manufacturer.rb +2 -0
  247. data/spec/internal/app/models/product.rb +3 -1
  248. data/spec/internal/app/models/tag.rb +2 -0
  249. data/spec/internal/app/models/tagging.rb +2 -0
  250. data/spec/internal/app/models/tee.rb +7 -0
  251. data/spec/internal/app/models/tweet.rb +2 -0
  252. data/spec/internal/app/models/user.rb +4 -0
  253. data/spec/internal/config/database.yml +12 -1
  254. data/spec/internal/db/schema.rb +13 -1
  255. data/spec/spec_helper.rb +12 -1
  256. data/spec/support/json_column.rb +35 -0
  257. data/spec/support/multi_schema.rb +5 -1
  258. data/spec/support/mysql.rb +25 -0
  259. data/spec/support/sphinx_yaml_helpers.rb +8 -1
  260. data/spec/thinking_sphinx/active_record/association_spec.rb +3 -1
  261. data/spec/thinking_sphinx/active_record/attribute/type_spec.rb +43 -38
  262. data/spec/thinking_sphinx/active_record/base_spec.rb +31 -29
  263. data/spec/thinking_sphinx/active_record/callbacks/delete_callbacks_spec.rb +81 -10
  264. data/spec/thinking_sphinx/active_record/callbacks/delta_callbacks_spec.rb +56 -29
  265. data/spec/thinking_sphinx/active_record/callbacks/update_callbacks_spec.rb +27 -10
  266. data/spec/thinking_sphinx/active_record/column_spec.rb +15 -13
  267. data/spec/thinking_sphinx/active_record/column_sql_presenter_spec.rb +39 -0
  268. data/spec/thinking_sphinx/active_record/database_adapters/abstract_adapter_spec.rb +7 -5
  269. data/spec/thinking_sphinx/active_record/database_adapters/mysql_adapter_spec.rb +26 -12
  270. data/spec/thinking_sphinx/active_record/database_adapters/postgresql_adapter_spec.rb +15 -13
  271. data/spec/thinking_sphinx/active_record/database_adapters_spec.rb +50 -48
  272. data/spec/thinking_sphinx/active_record/field_spec.rb +9 -7
  273. data/spec/thinking_sphinx/active_record/filter_reflection_spec.rb +113 -80
  274. data/spec/thinking_sphinx/active_record/index_spec.rb +41 -37
  275. data/spec/thinking_sphinx/active_record/interpreter_spec.rb +62 -59
  276. data/spec/thinking_sphinx/active_record/polymorpher_spec.rb +16 -14
  277. data/spec/thinking_sphinx/active_record/property_sql_presenter_spec.rb +69 -67
  278. data/spec/thinking_sphinx/active_record/sql_builder_spec.rb +146 -154
  279. data/spec/thinking_sphinx/active_record/sql_source_spec.rb +185 -109
  280. data/spec/thinking_sphinx/attribute_types_spec.rb +52 -0
  281. data/spec/thinking_sphinx/commands/clear_real_time_spec.rb +46 -0
  282. data/spec/thinking_sphinx/commands/clear_sql_spec.rb +52 -0
  283. data/spec/thinking_sphinx/commands/configure_spec.rb +31 -0
  284. data/spec/thinking_sphinx/commands/index_real_time_spec.rb +33 -0
  285. data/spec/thinking_sphinx/commands/index_sql_spec.rb +86 -0
  286. data/spec/thinking_sphinx/commands/merge_and_update_spec.rb +106 -0
  287. data/spec/thinking_sphinx/commands/merge_spec.rb +48 -0
  288. data/spec/thinking_sphinx/commands/prepare_spec.rb +31 -0
  289. data/spec/thinking_sphinx/commands/running_spec.rb +30 -0
  290. data/spec/thinking_sphinx/commands/start_detached_spec.rb +67 -0
  291. data/spec/thinking_sphinx/commands/stop_spec.rb +63 -0
  292. data/spec/thinking_sphinx/configuration/minimum_fields_spec.rb +60 -0
  293. data/spec/thinking_sphinx/configuration_spec.rb +247 -94
  294. data/spec/thinking_sphinx/connection/mri_spec.rb +49 -0
  295. data/spec/thinking_sphinx/connection_spec.rb +15 -13
  296. data/spec/thinking_sphinx/deletion_spec.rb +17 -17
  297. data/spec/thinking_sphinx/deltas/default_delta_spec.rb +28 -21
  298. data/spec/thinking_sphinx/deltas_spec.rb +14 -12
  299. data/spec/thinking_sphinx/errors_spec.rb +59 -27
  300. data/spec/thinking_sphinx/excerpter_spec.rb +12 -9
  301. data/spec/thinking_sphinx/facet_search_spec.rb +24 -22
  302. data/spec/thinking_sphinx/hooks/guard_presence_spec.rb +30 -0
  303. data/spec/thinking_sphinx/index_set_spec.rb +59 -18
  304. data/spec/thinking_sphinx/index_spec.rb +28 -26
  305. data/spec/thinking_sphinx/interfaces/daemon_spec.rb +60 -0
  306. data/spec/thinking_sphinx/interfaces/real_time_spec.rb +109 -0
  307. data/spec/thinking_sphinx/interfaces/sql_spec.rb +122 -0
  308. data/spec/thinking_sphinx/masks/pagination_mask_spec.rb +22 -20
  309. data/spec/thinking_sphinx/masks/scopes_mask_spec.rb +20 -18
  310. data/spec/thinking_sphinx/middlewares/active_record_translator_spec.rb +45 -21
  311. data/spec/thinking_sphinx/middlewares/geographer_spec.rb +11 -9
  312. data/spec/thinking_sphinx/middlewares/glazier_spec.rb +12 -9
  313. data/spec/thinking_sphinx/middlewares/inquirer_spec.rb +9 -7
  314. data/spec/thinking_sphinx/middlewares/sphinxql_spec.rb +60 -58
  315. data/spec/thinking_sphinx/middlewares/stale_id_checker_spec.rb +7 -4
  316. data/spec/thinking_sphinx/middlewares/stale_id_filter_spec.rb +39 -17
  317. data/spec/thinking_sphinx/middlewares/valid_options_spec.rb +51 -0
  318. data/spec/thinking_sphinx/panes/attributes_pane_spec.rb +3 -1
  319. data/spec/thinking_sphinx/panes/distance_pane_spec.rb +6 -4
  320. data/spec/thinking_sphinx/panes/excerpts_pane_spec.rb +8 -6
  321. data/spec/thinking_sphinx/panes/weight_pane_spec.rb +4 -2
  322. data/spec/thinking_sphinx/rake_interface_spec.rb +17 -235
  323. data/spec/thinking_sphinx/real_time/attribute_spec.rb +15 -13
  324. data/spec/thinking_sphinx/real_time/callbacks/real_time_callbacks_spec.rb +114 -28
  325. data/spec/thinking_sphinx/real_time/field_spec.rb +16 -14
  326. data/spec/thinking_sphinx/real_time/index_spec.rb +83 -32
  327. data/spec/thinking_sphinx/real_time/interpreter_spec.rb +44 -42
  328. data/spec/thinking_sphinx/real_time/transcribe_instance_spec.rb +35 -0
  329. data/spec/thinking_sphinx/real_time/transcriber_spec.rb +109 -0
  330. data/spec/thinking_sphinx/real_time/translator_spec.rb +17 -0
  331. data/spec/thinking_sphinx/scopes_spec.rb +11 -5
  332. data/spec/thinking_sphinx/search/glaze_spec.rb +17 -15
  333. data/spec/thinking_sphinx/search/query_spec.rb +19 -10
  334. data/spec/thinking_sphinx/search_spec.rb +30 -28
  335. data/spec/thinking_sphinx/wildcard_spec.rb +18 -11
  336. data/spec/thinking_sphinx_spec.rb +10 -7
  337. data/thinking-sphinx.gemspec +17 -10
  338. metadata +157 -49
  339. data/HISTORY +0 -248
  340. data/gemfiles/.gitignore +0 -1
  341. data/gemfiles/rails_3_2.gemfile +0 -11
  342. data/gemfiles/rails_4_0.gemfile +0 -11
  343. data/gemfiles/rails_4_1.gemfile +0 -11
  344. data/gemfiles/rails_4_2.gemfile +0 -11
  345. data/lib/thinking_sphinx/controller.rb +0 -10
  346. data/lib/thinking_sphinx/middlewares/utf8.rb +0 -27
  347. data/lib/thinking_sphinx/sphinxql.rb +0 -23
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'acceptance/spec_helper'
2
4
 
3
5
  describe 'specifying SQL for index definitions' do
@@ -8,7 +10,7 @@ describe 'specifying SQL for index definitions' do
8
10
  join user
9
11
  }
10
12
  index.render
11
- index.sources.first.sql_query.should match(/LEFT OUTER JOIN .users./)
13
+ expect(index.sources.first.sql_query).to match(/LEFT OUTER JOIN .users./)
12
14
  end
13
15
 
14
16
  it "handles deep joins" do
@@ -20,8 +22,8 @@ describe 'specifying SQL for index definitions' do
20
22
  index.render
21
23
 
22
24
  query = index.sources.first.sql_query
23
- query.should match(/LEFT OUTER JOIN .users./)
24
- query.should match(/LEFT OUTER JOIN .articles./)
25
+ expect(query).to match(/LEFT OUTER JOIN .users./)
26
+ expect(query).to match(/LEFT OUTER JOIN .articles./)
25
27
  end
26
28
 
27
29
  it "handles has-many :through joins" do
@@ -32,8 +34,8 @@ describe 'specifying SQL for index definitions' do
32
34
  index.render
33
35
 
34
36
  query = index.sources.first.sql_query
35
- query.should match(/LEFT OUTER JOIN .taggings./)
36
- query.should match(/LEFT OUTER JOIN .tags./)
37
+ expect(query).to match(/LEFT OUTER JOIN .taggings./)
38
+ expect(query).to match(/LEFT OUTER JOIN .tags./)
37
39
  end
38
40
 
39
41
  it "handles custom join SQL statements" do
@@ -45,7 +47,7 @@ describe 'specifying SQL for index definitions' do
45
47
  index.render
46
48
 
47
49
  query = index.sources.first.sql_query
48
- query.should match(/INNER JOIN foo ON foo.x = bar.y/)
50
+ expect(query).to match(/INNER JOIN foo ON foo.x = bar.y/)
49
51
  end
50
52
 
51
53
  it "handles GROUP BY clauses" do
@@ -57,7 +59,7 @@ describe 'specifying SQL for index definitions' do
57
59
  index.render
58
60
 
59
61
  query = index.sources.first.sql_query
60
- query.should match(/GROUP BY .articles.\..id., .?articles.?\..title., .?articles.?\..id., lat/)
62
+ expect(query).to match(/GROUP BY .articles.\..id., .?articles.?\..title., .?articles.?\..id., lat/)
61
63
  end
62
64
 
63
65
  it "handles WHERE clauses" do
@@ -69,7 +71,7 @@ describe 'specifying SQL for index definitions' do
69
71
  index.render
70
72
 
71
73
  query = index.sources.first.sql_query
72
- query.should match(/WHERE .+title != 'secret'.+ GROUP BY/)
74
+ expect(query).to match(/WHERE .+title != 'secret'.+ GROUP BY/)
73
75
  end
74
76
 
75
77
  it "handles manual MVA declarations" do
@@ -81,7 +83,7 @@ describe 'specifying SQL for index definitions' do
81
83
  }
82
84
  index.render
83
85
 
84
- index.sources.first.sql_attr_multi.should == ['uint tag_ids from field']
86
+ expect(index.sources.first.sql_attr_multi).to eq(['uint tag_ids from field'])
85
87
  end
86
88
 
87
89
  it "provides the sanitize_sql helper within the index definition block" do
@@ -93,7 +95,7 @@ describe 'specifying SQL for index definitions' do
93
95
  index.render
94
96
 
95
97
  query = index.sources.first.sql_query
96
- query.should match(/WHERE .+title != 'secret'.+ GROUP BY/)
98
+ expect(query).to match(/WHERE .+title != 'secret'.+ GROUP BY/)
97
99
  end
98
100
 
99
101
  it "escapes new lines in SQL snippets" do
@@ -111,7 +113,7 @@ describe 'specifying SQL for index definitions' do
111
113
  index.render
112
114
 
113
115
  query = index.sources.first.sql_query
114
- query.should match(/\\\n/)
116
+ expect(query).to match(/\\\n/)
115
117
  end
116
118
 
117
119
  it "joins each polymorphic relation" do
@@ -123,9 +125,9 @@ describe 'specifying SQL for index definitions' do
123
125
  index.render
124
126
 
125
127
  query = index.sources.first.sql_query
126
- query.should match(/LEFT OUTER JOIN .articles. ON .articles.\..id. = .events.\..eventable_id. AND .events.\..eventable_type. = 'Article'/)
127
- query.should match(/LEFT OUTER JOIN .books. ON .books.\..id. = .events.\..eventable_id. AND .events.\..eventable_type. = 'Book'/)
128
- query.should match(/.articles.\..title., .books.\..title./)
128
+ expect(query).to match(/LEFT OUTER JOIN .articles. ON .articles.\..id. = .events.\..eventable_id. AND .events.\..eventable_type. = 'Article'/)
129
+ expect(query).to match(/LEFT OUTER JOIN .books. ON .books.\..id. = .events.\..eventable_id. AND .events.\..eventable_type. = 'Book'/)
130
+ expect(query).to match(/.articles.\..title., .books.\..title./)
129
131
  end if ActiveRecord::VERSION::MAJOR > 3
130
132
 
131
133
  it "concatenates references that have column" do
@@ -137,9 +139,9 @@ describe 'specifying SQL for index definitions' do
137
139
  index.render
138
140
 
139
141
  query = index.sources.first.sql_query
140
- query.should match(/LEFT OUTER JOIN .articles. ON .articles.\..id. = .events.\..eventable_id. AND .events.\..eventable_type. = 'Article'/)
141
- query.should_not match(/articles\..title., users\..title./)
142
- query.should match(/.articles.\..title./)
142
+ expect(query).to match(/LEFT OUTER JOIN .articles. ON .articles.\..id. = .events.\..eventable_id. AND .events.\..eventable_type. = 'Article'/)
143
+ expect(query).not_to match(/articles\..title., users\..title./)
144
+ expect(query).to match(/.articles.\..title./)
143
145
  end if ActiveRecord::VERSION::MAJOR > 3
144
146
 
145
147
  it "respects deeper associations through polymorphic joins" do
@@ -151,13 +153,31 @@ describe 'specifying SQL for index definitions' do
151
153
  index.render
152
154
 
153
155
  query = index.sources.first.sql_query
154
- query.should match(/LEFT OUTER JOIN .articles. ON .articles.\..id. = .events.\..eventable_id. AND .events.\..eventable_type. = 'Article'/)
155
- query.should match(/LEFT OUTER JOIN .users. ON .users.\..id. = .articles.\..user_id./)
156
- query.should match(/.users.\..name./)
156
+ expect(query).to match(/LEFT OUTER JOIN .articles. ON .articles.\..id. = .events.\..eventable_id. AND .events.\..eventable_type. = 'Article'/)
157
+ expect(query).to match(/LEFT OUTER JOIN .users. ON .users.\..id. = .articles.\..user_id./)
158
+ expect(query).to match(/.users.\..name./)
159
+ end
160
+
161
+ it "allows for STI mixed with polymorphic joins" do
162
+ index = ThinkingSphinx::ActiveRecord::Index.new(:event)
163
+ index.definition_block = Proc.new {
164
+ indexes eventable.name, :as => :name
165
+ polymorphs eventable, :to => %w(Bird Car)
166
+ }
167
+ index.render
168
+
169
+ query = index.sources.first.sql_query
170
+ expect(query).to match(/LEFT OUTER JOIN .animals. ON .animals.\..id. = .events.\..eventable_id. .* AND .events.\..eventable_type. = 'Animal'/)
171
+ expect(query).to match(/LEFT OUTER JOIN .cars. ON .cars.\..id. = .events.\..eventable_id. AND .events.\..eventable_type. = 'Car'/)
172
+ expect(query).to match(/.animals.\..name., .cars.\..name./)
157
173
  end
158
174
  end if ActiveRecord::VERSION::MAJOR > 3
159
175
 
160
176
  describe 'separate queries for MVAs' do
177
+ def id_type
178
+ ActiveRecord::VERSION::STRING.to_f > 5.0 ? 'bigint' : 'uint'
179
+ end
180
+
161
181
  let(:index) { ThinkingSphinx::ActiveRecord::Index.new(:article) }
162
182
  let(:count) { ThinkingSphinx::Configuration.instance.indices.count }
163
183
  let(:source) { index.sources.first }
@@ -174,8 +194,33 @@ describe 'separate queries for MVAs' do
174
194
  }
175
195
  declaration, query = attribute.split(/;\s+/)
176
196
 
177
- declaration.should == 'uint tag_ids from query'
178
- query.should match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .taggings.\..tag_id. AS .tag_ids. FROM .taggings.\s? WHERE \(.taggings.\..article_id. IS NOT NULL\)$/)
197
+ expect(declaration).to eq("uint tag_ids from query")
198
+ expect(query).to match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .taggings.\..tag_id. AS .tag_ids. FROM .taggings.\s? WHERE \(.taggings.\..article_id. IS NOT NULL\)$/)
199
+ end
200
+
201
+ it "does not include attributes sourced via separate queries" do
202
+ index.definition_block = Proc.new {
203
+ indexes title
204
+ has taggings.tag_id, :as => :tag_ids, :source => :query
205
+ }
206
+ index.render
207
+
208
+ # We don't want it in the SELECT, JOIN or GROUP clauses. This should catch
209
+ # them all.
210
+ expect(source.sql_query).not_to include('taggings')
211
+ end
212
+
213
+ it "keeps the joins in for separately queried tables if they're used elsewhere" do
214
+ index.definition_block = Proc.new {
215
+ indexes taggings.tag.name, :as => :tag_names
216
+ has taggings.tag.created_at, :as => :tag_dates, :source => :query
217
+ }
218
+ index.render
219
+
220
+ expect(source.sql_query).to include('taggings')
221
+ expect(source.sql_query).to include('tags')
222
+ expect(source.sql_query).to_not match(/.tags.\..created_at./)
223
+ expect(source.sql_query).to match(/.tags.\..name./)
179
224
  end
180
225
 
181
226
  it "generates a SQL query with joins when appropriate for MVAs" do
@@ -190,8 +235,8 @@ describe 'separate queries for MVAs' do
190
235
  }
191
236
  declaration, query = attribute.split(/;\s+/)
192
237
 
193
- declaration.should == 'uint tag_ids from query'
194
- query.should match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..id. AS .tag_ids. FROM .taggings. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id. WHERE \(.taggings.\..article_id. IS NOT NULL\)\s?$/)
238
+ expect(declaration).to eq("#{id_type} tag_ids from query")
239
+ expect(query).to match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..id. AS .tag_ids. FROM .taggings. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id. WHERE \(.taggings.\..article_id. IS NOT NULL\)\s?$/)
195
240
  end
196
241
 
197
242
  it "respects has_many :through joins for MVA queries" do
@@ -206,8 +251,8 @@ describe 'separate queries for MVAs' do
206
251
  }
207
252
  declaration, query = attribute.split(/;\s+/)
208
253
 
209
- declaration.should == 'uint tag_ids from query'
210
- query.should match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..id. AS .tag_ids. FROM .taggings. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id. WHERE \(.taggings.\..article_id. IS NOT NULL\)\s?$/)
254
+ expect(declaration).to eq("#{id_type} tag_ids from query")
255
+ expect(query).to match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..id. AS .tag_ids. FROM .taggings. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id. WHERE \(.taggings.\..article_id. IS NOT NULL\)\s?$/)
211
256
  end
212
257
 
213
258
  it "can handle multiple joins for MVA queries" do
@@ -224,8 +269,8 @@ describe 'separate queries for MVAs' do
224
269
  }
225
270
  declaration, query = attribute.split(/;\s+/)
226
271
 
227
- declaration.should == 'uint tag_ids from query'
228
- query.should match(/^SELECT .articles.\..user_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..id. AS .tag_ids. FROM .articles. INNER JOIN .taggings. ON .taggings.\..article_id. = .articles.\..id. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id. WHERE \(.articles.\..user_id. IS NOT NULL\)\s?$/)
272
+ expect(declaration).to eq("#{id_type} tag_ids from query")
273
+ expect(query).to match(/^SELECT .articles.\..user_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..id. AS .tag_ids. FROM .articles. INNER JOIN .taggings. ON .taggings.\..article_id. = .articles.\..id. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id. WHERE \(.articles.\..user_id. IS NOT NULL\)\s?$/)
229
274
  end
230
275
 
231
276
  it "can handle simple HABTM joins for MVA queries" do
@@ -242,8 +287,8 @@ describe 'separate queries for MVAs' do
242
287
  }
243
288
  declaration, query = attribute.split(/;\s+/)
244
289
 
245
- declaration.should == 'uint genre_ids from query'
246
- query.should match(/^SELECT .books_genres.\..book_id. \* #{count} \+ #{source.offset} AS .id., .books_genres.\..genre_id. AS .genre_ids. FROM .books_genres.\s?$/)
290
+ expect(declaration).to eq("#{id_type} genre_ids from query")
291
+ expect(query).to match(/^SELECT .books_genres.\..book_id. \* #{count} \+ #{source.offset} AS .id., .books_genres.\..genre_id. AS .genre_ids. FROM .books_genres.\s?$/)
247
292
  end if ActiveRecord::VERSION::MAJOR > 3
248
293
 
249
294
  it "generates an appropriate range SQL queries for an MVA" do
@@ -258,9 +303,9 @@ describe 'separate queries for MVAs' do
258
303
  }
259
304
  declaration, query, range = attribute.split(/;\s+/)
260
305
 
261
- declaration.should == 'uint tag_ids from ranged-query'
262
- query.should match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .taggings.\..tag_id. AS .tag_ids. FROM .taggings. \s?WHERE \(.taggings.\..article_id. BETWEEN \$start AND \$end\) AND \(.taggings.\..article_id. IS NOT NULL\)$/)
263
- range.should match(/^SELECT MIN\(.taggings.\..article_id.\), MAX\(.taggings.\..article_id.\) FROM .taggings.\s?$/)
306
+ expect(declaration).to eq("uint tag_ids from ranged-query")
307
+ expect(query).to match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .taggings.\..tag_id. AS .tag_ids. FROM .taggings. \s?WHERE \(.taggings.\..article_id. BETWEEN \$start AND \$end\) AND \(.taggings.\..article_id. IS NOT NULL\)$/)
308
+ expect(range).to match(/^SELECT MIN\(.taggings.\..article_id.\), MAX\(.taggings.\..article_id.\) FROM .taggings.\s?$/)
264
309
  end
265
310
 
266
311
  it "generates a SQL query with joins when appropriate for MVAs" do
@@ -275,9 +320,9 @@ describe 'separate queries for MVAs' do
275
320
  }
276
321
  declaration, query, range = attribute.split(/;\s+/)
277
322
 
278
- declaration.should == 'uint tag_ids from ranged-query'
279
- query.should match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..id. AS .tag_ids. FROM .taggings. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id. \s?WHERE \(.taggings.\..article_id. BETWEEN \$start AND \$end\) AND \(.taggings.\..article_id. IS NOT NULL\)$/)
280
- range.should match(/^SELECT MIN\(.taggings.\..article_id.\), MAX\(.taggings.\..article_id.\) FROM .taggings.\s?$/)
323
+ expect(declaration).to eq("#{id_type} tag_ids from ranged-query")
324
+ expect(query).to match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..id. AS .tag_ids. FROM .taggings. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id. \s?WHERE \(.taggings.\..article_id. BETWEEN \$start AND \$end\) AND \(.taggings.\..article_id. IS NOT NULL\)$/)
325
+ expect(range).to match(/^SELECT MIN\(.taggings.\..article_id.\), MAX\(.taggings.\..article_id.\) FROM .taggings.\s?$/)
281
326
  end
282
327
 
283
328
  it "can handle ranged queries for simple HABTM joins for MVA queries" do
@@ -294,9 +339,9 @@ describe 'separate queries for MVAs' do
294
339
  }
295
340
  declaration, query, range = attribute.split(/;\s+/)
296
341
 
297
- declaration.should == 'uint genre_ids from ranged-query'
298
- query.should match(/^SELECT .books_genres.\..book_id. \* #{count} \+ #{source.offset} AS .id., .books_genres.\..genre_id. AS .genre_ids. FROM .books_genres. WHERE \(.books_genres.\..book_id. BETWEEN \$start AND \$end\)$/)
299
- range.should match(/^SELECT MIN\(.books_genres.\..book_id.\), MAX\(.books_genres.\..book_id.\) FROM .books_genres.$/)
342
+ expect(declaration).to eq("#{id_type} genre_ids from ranged-query")
343
+ expect(query).to match(/^SELECT .books_genres.\..book_id. \* #{count} \+ #{source.offset} AS .id., .books_genres.\..genre_id. AS .genre_ids. FROM .books_genres. WHERE \(.books_genres.\..book_id. BETWEEN \$start AND \$end\)$/)
344
+ expect(range).to match(/^SELECT MIN\(.books_genres.\..book_id.\), MAX\(.books_genres.\..book_id.\) FROM .books_genres.$/)
300
345
  end if ActiveRecord::VERSION::MAJOR > 3
301
346
 
302
347
  it "respects custom SQL snippets as the query value" do
@@ -312,8 +357,8 @@ describe 'separate queries for MVAs' do
312
357
  }
313
358
  declaration, query = attribute.split(/;\s+/)
314
359
 
315
- declaration.should == 'uint tag_ids from query'
316
- query.should == 'My Custom SQL Query'
360
+ expect(declaration).to eq('uint tag_ids from query')
361
+ expect(query).to eq('My Custom SQL Query')
317
362
  end
318
363
 
319
364
  it "respects custom SQL snippets as the ranged query value" do
@@ -329,9 +374,9 @@ describe 'separate queries for MVAs' do
329
374
  }
330
375
  declaration, query, range = attribute.split(/;\s+/)
331
376
 
332
- declaration.should == 'uint tag_ids from ranged-query'
333
- query.should == 'My Custom SQL Query'
334
- range.should == 'And a Range'
377
+ expect(declaration).to eq('uint tag_ids from ranged-query')
378
+ expect(query).to eq('My Custom SQL Query')
379
+ expect(range).to eq('And a Range')
335
380
  end
336
381
 
337
382
  it "escapes new lines in custom SQL snippets" do
@@ -349,8 +394,8 @@ SQL Query
349
394
  }
350
395
  declaration, query = attribute.split(/;\s+/)
351
396
 
352
- declaration.should == 'uint tag_ids from query'
353
- query.should == "My Custom\\\nSQL Query"
397
+ expect(declaration).to eq('uint tag_ids from query')
398
+ expect(query).to eq("My Custom\\\nSQL Query")
354
399
  end
355
400
  end
356
401
 
@@ -368,8 +413,8 @@ describe 'separate queries for field' do
368
413
  field = source.sql_joined_field.detect { |field| field[/tags/] }
369
414
  declaration, query = field.split(/;\s+/)
370
415
 
371
- declaration.should == 'tags from query'
372
- query.should match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..name. AS .tags. FROM .taggings. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id.\s? WHERE \(.taggings.\..article_id. IS NOT NULL\)\s? ORDER BY .taggings.\..article_id. ASC\s?$/)
416
+ expect(declaration).to eq('tags from query')
417
+ expect(query).to match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..name. AS .tags. FROM .taggings. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id.\s? WHERE \(.taggings.\..article_id. IS NOT NULL\)\s? ORDER BY .taggings.\..article_id. ASC\s?$/)
373
418
  end
374
419
 
375
420
  it "respects has_many :through joins for MVF queries" do
@@ -381,8 +426,8 @@ describe 'separate queries for field' do
381
426
  field = source.sql_joined_field.detect { |field| field[/tags/] }
382
427
  declaration, query = field.split(/;\s+/)
383
428
 
384
- declaration.should == 'tags from query'
385
- query.should match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..name. AS .tags. FROM .taggings. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id.\s? WHERE \(.taggings.\..article_id. IS NOT NULL\)\s? ORDER BY .taggings.\..article_id. ASC\s?$/)
429
+ expect(declaration).to eq('tags from query')
430
+ expect(query).to match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..name. AS .tags. FROM .taggings. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id.\s? WHERE \(.taggings.\..article_id. IS NOT NULL\)\s? ORDER BY .taggings.\..article_id. ASC\s?$/)
386
431
  end
387
432
 
388
433
  it "can handle multiple joins for MVF queries" do
@@ -396,8 +441,8 @@ describe 'separate queries for field' do
396
441
  field = source.sql_joined_field.detect { |field| field[/tags/] }
397
442
  declaration, query = field.split(/;\s+/)
398
443
 
399
- declaration.should == 'tags from query'
400
- query.should match(/^SELECT .articles.\..user_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..name. AS .tags. FROM .articles. INNER JOIN .taggings. ON .taggings.\..article_id. = .articles.\..id. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id.\s? WHERE \(.articles.\..user_id. IS NOT NULL\)\s? ORDER BY .articles.\..user_id. ASC\s?$/)
444
+ expect(declaration).to eq('tags from query')
445
+ expect(query).to match(/^SELECT .articles.\..user_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..name. AS .tags. FROM .articles. INNER JOIN .taggings. ON .taggings.\..article_id. = .articles.\..id. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id.\s? WHERE \(.articles.\..user_id. IS NOT NULL\)\s? ORDER BY .articles.\..user_id. ASC\s?$/)
401
446
  end
402
447
 
403
448
  it "generates a SQL query with joins when appropriate for MVFs" do
@@ -409,9 +454,20 @@ describe 'separate queries for field' do
409
454
  field = source.sql_joined_field.detect { |field| field[/tags/] }
410
455
  declaration, query, range = field.split(/;\s+/)
411
456
 
412
- declaration.should == 'tags from ranged-query'
413
- query.should match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..name. AS .tags. FROM .taggings. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id. \s?WHERE \(.taggings.\..article_id. BETWEEN \$start AND \$end\) AND \(.taggings.\..article_id. IS NOT NULL\)\s? ORDER BY .taggings.\..article_id. ASC$/)
414
- range.should match(/^SELECT MIN\(.taggings.\..article_id.\), MAX\(.taggings.\..article_id.\) FROM .taggings.\s?$/)
457
+ expect(declaration).to eq('tags from ranged-query')
458
+ expect(query).to match(/^SELECT .taggings.\..article_id. \* #{count} \+ #{source.offset} AS .id., .tags.\..name. AS .tags. FROM .taggings. INNER JOIN .tags. ON .tags.\..id. = .taggings.\..tag_id. \s?WHERE \(.taggings.\..article_id. BETWEEN \$start AND \$end\) AND \(.taggings.\..article_id. IS NOT NULL\)\s? ORDER BY .taggings.\..article_id. ASC$/)
459
+ expect(range).to match(/^SELECT MIN\(.taggings.\..article_id.\), MAX\(.taggings.\..article_id.\) FROM .taggings.\s?$/)
460
+ end
461
+
462
+ it "does not include fields sourced via separate queries" do
463
+ index.definition_block = Proc.new {
464
+ indexes taggings.tag.name, :as => :tags, :source => :query
465
+ }
466
+ index.render
467
+
468
+ # We don't want it in the SELECT, JOIN or GROUP clauses. This should catch
469
+ # them all.
470
+ expect(source.sql_query).not_to include('tags')
415
471
  end
416
472
 
417
473
  it "respects custom SQL snippets as the query value" do
@@ -423,8 +479,8 @@ describe 'separate queries for field' do
423
479
  field = source.sql_joined_field.detect { |field| field[/tags/] }
424
480
  declaration, query = field.split(/;\s+/)
425
481
 
426
- declaration.should == 'tags from query'
427
- query.should == 'My Custom SQL Query'
482
+ expect(declaration).to eq('tags from query')
483
+ expect(query).to eq('My Custom SQL Query')
428
484
  end
429
485
 
430
486
  it "respects custom SQL snippets as the ranged query value" do
@@ -437,9 +493,9 @@ describe 'separate queries for field' do
437
493
  field = source.sql_joined_field.detect { |field| field[/tags/] }
438
494
  declaration, query, range = field.split(/;\s+/)
439
495
 
440
- declaration.should == 'tags from ranged-query'
441
- query.should == 'My Custom SQL Query'
442
- range.should == 'And a Range'
496
+ expect(declaration).to eq('tags from ranged-query')
497
+ expect(query).to eq('My Custom SQL Query')
498
+ expect(range).to eq('And a Range')
443
499
  end
444
500
 
445
501
  it "escapes new lines in custom SQL snippets" do
@@ -454,7 +510,7 @@ SQL Query
454
510
  field = source.sql_joined_field.detect { |field| field[/tags/] }
455
511
  declaration, query = field.split(/;\s+/)
456
512
 
457
- declaration.should == 'tags from query'
458
- query.should == "My Custom\\\nSQL Query"
513
+ expect(declaration).to eq('tags from query')
514
+ expect(query).to eq("My Custom\\\nSQL Query")
459
515
  end
460
516
  end
@@ -1,41 +1,43 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'acceptance/spec_helper'
2
4
 
3
5
  describe 'Sphinx scopes', :live => true do
4
6
  it "allows calling sphinx scopes from models" do
5
- gods = Book.create! :title => 'American Gods', :year => 2001
6
- boys = Book.create! :title => 'Anansi Boys', :year => 2005
7
- grave = Book.create! :title => 'The Graveyard Book', :year => 2009
7
+ gods = Book.create! :title => 'American Gods', :publishing_year => 2001
8
+ boys = Book.create! :title => 'Anansi Boys', :publishing_year => 2005
9
+ grave = Book.create! :title => 'The Graveyard Book', :publishing_year => 2009
8
10
  index
9
11
 
10
- Book.by_year(2009).to_a.should == [grave]
12
+ expect(Book.by_publishing_year(2009).to_a).to eq([grave])
11
13
  end
12
14
 
13
15
  it "allows scopes to return both query and options" do
14
- gods = Book.create! :title => 'American Gods', :year => 2001
15
- boys = Book.create! :title => 'Anansi Boys', :year => 2005
16
- grave = Book.create! :title => 'The Graveyard Book', :year => 2009
16
+ gods = Book.create! :title => 'American Gods', :publishing_year => 2001
17
+ boys = Book.create! :title => 'Anansi Boys', :publishing_year => 2005
18
+ grave = Book.create! :title => 'The Graveyard Book', :publishing_year => 2009
17
19
  index
18
20
 
19
- Book.by_query_and_year('Graveyard', 2009).to_a.should == [grave]
21
+ expect(Book.by_query_and_publishing_year('Graveyard', 2009).to_a).to eq([grave])
20
22
  end
21
23
 
22
24
  it "allows chaining of scopes" do
23
- gods = Book.create! :title => 'American Gods', :year => 2001
24
- boys = Book.create! :title => 'Anansi Boys', :year => 2005
25
- grave = Book.create! :title => 'The Graveyard Book', :year => 2009
25
+ gods = Book.create! :title => 'American Gods', :publishing_year => 2001
26
+ boys = Book.create! :title => 'Anansi Boys', :publishing_year => 2005
27
+ grave = Book.create! :title => 'The Graveyard Book', :publishing_year => 2009
26
28
  index
27
29
 
28
- Book.by_year(2001..2005).ordered.to_a.should == [boys, gods]
30
+ expect(Book.by_publishing_year(2001..2005).ordered.to_a).to eq([boys, gods])
29
31
  end
30
32
 
31
33
  it "allows chaining of scopes that include queries" do
32
- gods = Book.create! :title => 'American Gods', :year => 2001
33
- boys = Book.create! :title => 'Anansi Boys', :year => 2005
34
- grave = Book.create! :title => 'The Graveyard Book', :year => 2009
34
+ gods = Book.create! :title => 'American Gods', :publishing_year => 2001
35
+ boys = Book.create! :title => 'Anansi Boys', :publishing_year => 2005
36
+ grave = Book.create! :title => 'The Graveyard Book', :publishing_year => 2009
35
37
  index
36
38
 
37
- Book.by_year(2001).by_query_and_year('Graveyard', 2009).to_a.
38
- should == [grave]
39
+ expect(Book.by_publishing_year(2001).by_query_and_publishing_year('Graveyard', 2009).to_a).
40
+ to eq([grave])
39
41
  end
40
42
 
41
43
  it "allows further search calls on scopes" do
@@ -43,7 +45,7 @@ describe 'Sphinx scopes', :live => true do
43
45
  pratchett = Book.create! :title => 'Small Gods'
44
46
  index
45
47
 
46
- Book.by_query('Gods').search('Small').to_a.should == [pratchett]
48
+ expect(Book.by_query('Gods').search('Small').to_a).to eq([pratchett])
47
49
  end
48
50
 
49
51
  it "allows facet calls on scopes" do
@@ -52,9 +54,9 @@ describe 'Sphinx scopes', :live => true do
52
54
  Book.create! :title => 'Small Gods', :author => 'Terry Pratchett'
53
55
  index
54
56
 
55
- Book.by_query('Gods').facets.to_hash[:author].should == {
57
+ expect(Book.by_query('Gods').facets.to_hash[:author]).to eq({
56
58
  'Neil Gaiman' => 1, 'Terry Pratchett' => 1
57
- }
59
+ })
58
60
  end
59
61
 
60
62
  it "allows accessing counts on scopes" do
@@ -64,7 +66,7 @@ describe 'Sphinx scopes', :live => true do
64
66
  Book.create! :title => 'Night Watch'
65
67
  index
66
68
 
67
- Book.by_query('gods').count.should == 2
69
+ expect(Book.by_query('gods').count).to eq(2)
68
70
  end
69
71
 
70
72
  it 'raises an exception when trying to modify a populated request' do
@@ -75,4 +77,11 @@ describe 'Sphinx scopes', :live => true do
75
77
  ThinkingSphinx::PopulatedResultsError
76
78
  )
77
79
  end
80
+
81
+ it "handles a chainable 'none' scope and returns nothing" do
82
+ Book.create! :title => 'Small Gods'
83
+ index
84
+
85
+ expect(Book.by_query('gods').none).to be_empty
86
+ end
78
87
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'acceptance/spec_helper'
2
4
 
3
5
  describe 'SQL delta indexing', :live => true do
@@ -7,38 +9,50 @@ describe 'SQL delta indexing', :live => true do
7
9
  )
8
10
  index
9
11
 
10
- Book.search('Terry Pratchett').to_a.should == [guards]
12
+ expect(Book.search('Terry Pratchett').to_a).to eq([guards])
11
13
 
12
14
  men = Book.create(
13
15
  :title => 'Men At Arms', :author => 'Terry Pratchett'
14
16
  )
15
17
  sleep 0.25
16
18
 
17
- Book.search('Terry Pratchett').to_a.should == [guards, men]
19
+ expect(Book.search('Terry Pratchett').to_a).to match_array([guards, men])
18
20
  end
19
21
 
20
22
  it "automatically indexes updated records" do
21
23
  book = Book.create :title => 'Night Watch', :author => 'Harry Pritchett'
22
24
  index
23
25
 
24
- Book.search('Harry').to_a.should == [book]
26
+ expect(Book.search('Harry').to_a).to eq([book])
25
27
 
26
- book.reload.update_attributes(:author => 'Terry Pratchett')
28
+ book.reload.update(:author => 'Terry Pratchett')
27
29
  sleep 0.25
28
30
 
29
- Book.search('Terry').to_a.should == [book]
31
+ expect(Book.search('Terry').to_a).to eq([book])
30
32
  end
31
33
 
32
34
  it "does not match on old values" do
33
35
  book = Book.create :title => 'Night Watch', :author => 'Harry Pritchett'
34
36
  index
35
37
 
36
- Book.search('Harry').to_a.should == [book]
38
+ expect(Book.search('Harry').to_a).to eq([book])
39
+
40
+ book.reload.update(:author => 'Terry Pratchett')
41
+ sleep 0.25
42
+
43
+ expect(Book.search('Harry')).to be_empty
44
+ end
45
+
46
+ it "does not match on old values with alternative ids" do
47
+ album = Album.create :name => 'Eternal Nightcap', :artist => 'The Whitloms'
48
+ index
49
+
50
+ expect(Album.search('Whitloms').to_a).to eq([album])
37
51
 
38
- book.reload.update_attributes(:author => 'Terry Pratchett')
52
+ album.reload.update(:artist => 'The Whitlams')
39
53
  sleep 0.25
40
54
 
41
- Book.search('Harry').should be_empty
55
+ expect(Book.search('Whitloms')).to be_empty
42
56
  end
43
57
 
44
58
  it "automatically indexes new records of subclasses" do
@@ -47,6 +61,18 @@ describe 'SQL delta indexing', :live => true do
47
61
  )
48
62
  sleep 0.25
49
63
 
50
- Book.search('Gaiman').to_a.should == [book]
64
+ expect(Book.search('Gaiman').to_a).to eq([book])
65
+ end
66
+
67
+ it "updates associated models" do
68
+ colour = Colour.create(:name => 'green')
69
+ sleep 0.25
70
+
71
+ expect(Colour.search('green').to_a).to eq([colour])
72
+
73
+ tee = colour.tees.create
74
+ sleep 0.25
75
+
76
+ expect(Colour.search(:with => {:tee_ids => tee.id}).to_a).to eq([colour])
51
77
  end
52
78
  end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  RSpec.configure do |config|
2
4
  config.before(:suite) do
3
5
  DatabaseCleaner.strategy = :truncation
4
6
  end
5
7
 
6
- config.after(:each) do
8
+ config.after(:each) do |example|
7
9
  if example.example_group_instance.class.metadata[:live]
8
10
  DatabaseCleaner.clean
9
11
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class SphinxController
2
4
  def initialize
3
5
  config.searchd.mysql41 = 9307
@@ -10,14 +12,12 @@ class SphinxController
10
12
 
11
13
  ThinkingSphinx::Configuration.reset
12
14
 
13
- ActiveSupport::Dependencies.loaded.each do |path|
14
- $LOADED_FEATURES.delete "#{path}.rb"
15
- end
16
-
17
- ActiveSupport::Dependencies.clear
15
+ if Rails::VERSION::MAJOR < 7
16
+ ActiveSupport::Dependencies.loaded.each do |path|
17
+ $LOADED_FEATURES.delete "#{path}.rb"
18
+ end
18
19
 
19
- if ENV['SPHINX_VERSION'].try :[], /2.0.\d/
20
- ThinkingSphinx::Configuration.instance.settings['utf8'] = false
20
+ ActiveSupport::Dependencies.clear
21
21
  end
22
22
 
23
23
  config.searchd.mysql41 = 9307
@@ -28,14 +28,30 @@ class SphinxController
28
28
 
29
29
  def start
30
30
  config.controller.start
31
+ rescue Riddle::CommandFailedError => error
32
+ puts <<-TXT
33
+
34
+ The Sphinx start command failed:
35
+ Command: #{error.command_result.command}
36
+ Status: #{error.command_result.status}
37
+ Output: #{error.command_result.output}
38
+ TXT
39
+ raise error
31
40
  end
32
41
 
33
42
  def stop
34
- config.controller.stop
43
+ while config.controller.running? do
44
+ config.controller.stop
45
+ sleep(0.1)
46
+ end
35
47
  end
36
48
 
37
49
  def index(*indices)
38
- config.controller.index *indices
50
+ ThinkingSphinx::Commander.call :index_sql, config, :indices => indices
51
+ end
52
+
53
+ def merge
54
+ ThinkingSphinx::Commander.call(:merge_and_update, config, {})
39
55
  end
40
56
 
41
57
  private