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
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ # New versions of MySQL don't allow NULL values for primary keys, but old
4
+ # versions of Rails do. To use both at the same time, we need to update Rails'
5
+ # default primary key type to no longer have a default NULL value.
6
+ #
7
+ class PatchAdapter
8
+ def call
9
+ return unless using_mysql? && using_rails_pre_4_1?
10
+
11
+ require 'active_record/connection_adapters/abstract_mysql_adapter'
12
+ ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter::
13
+ NATIVE_DATABASE_TYPES[:primary_key] = "int(11) auto_increment PRIMARY KEY"
14
+ end
15
+
16
+ def using_mysql?
17
+ ENV.fetch('DATABASE', 'mysql2') == 'mysql2'
18
+ end
19
+
20
+ def using_rails_pre_4_1?
21
+ ActiveRecord::VERSION::STRING.to_f < 4.1
22
+ end
23
+ end
24
+
25
+ PatchAdapter.new.call
@@ -1,6 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module SphinxYamlHelpers
2
4
  def write_configuration(hash)
3
- File.stub :read => {'test' => hash}.to_yaml, :exists? => true
5
+ allow(File).to receive(:read).and_return({'test' => hash}.to_yaml)
6
+ allow(File).to receive(:exist?).and_wrap_original do |original, path|
7
+ next true if path.to_s == File.absolute_path("config/thinking_sphinx.yml", Rails.root.to_s)
8
+
9
+ original.call(path)
10
+ end
4
11
  end
5
12
  end
6
13
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe ThinkingSphinx::ActiveRecord::Association do
@@ -6,7 +8,7 @@ describe ThinkingSphinx::ActiveRecord::Association do
6
8
 
7
9
  describe '#stack' do
8
10
  it "returns the column's stack and name" do
9
- association.stack.should == [:users, :post]
11
+ expect(association.stack).to eq([:users, :post])
10
12
  end
11
13
  end
12
14
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ThinkingSphinx
2
4
  module ActiveRecord
3
5
  class Attribute; end
@@ -23,52 +25,55 @@ describe ThinkingSphinx::ActiveRecord::Attribute::Type do
23
25
  before :each do
24
26
  column.__stack << :foo
25
27
 
26
- model.stub :reflect_on_association => association
28
+ allow(model).to receive(:reflect_on_association).and_return(association)
27
29
  end
28
30
 
29
31
  it "returns true if there are has_many associations" do
30
- association.stub :macro => :has_many
32
+ allow(association).to receive(:macro).and_return(:has_many)
31
33
 
32
- type.should be_multi
34
+ expect(type).to be_multi
33
35
  end
34
36
 
35
37
  it "returns true if there are has_and_belongs_to_many associations" do
36
- association.stub :macro => :has_and_belongs_to_many
38
+ allow(association).to receive(:macro).and_return(:has_and_belongs_to_many)
37
39
 
38
- type.should be_multi
40
+ expect(type).to be_multi
39
41
  end
40
42
 
41
43
  it "returns false if there are no associations" do
42
44
  column.__stack.clear
43
45
 
44
- type.should_not be_multi
46
+ expect(type).not_to be_multi
45
47
  end
46
48
 
47
49
  it "returns false if there are only belongs_to associations" do
48
- association.stub :macro => :belongs_to
50
+ allow(association).to receive(:macro).and_return(:belongs_to)
49
51
 
50
- type.should_not be_multi
52
+ expect(type).not_to be_multi
51
53
  end
52
54
 
53
55
  it "returns false if there are only has_one associations" do
54
- association.stub :macro => :has_one
56
+ allow(association).to receive(:macro).and_return(:has_one)
55
57
 
56
- type.should_not be_multi
58
+ expect(type).not_to be_multi
57
59
  end
58
60
 
59
61
  it "returns true if deeper associations have many" do
60
62
  column.__stack << :bar
61
63
  deep_association = double(:klass => double, :macro => :has_many)
62
- association.stub :macro => :belongs_to,
63
- :klass => double(:reflect_on_association => deep_association)
64
64
 
65
- type.should be_multi
65
+ allow(association).to receive(:macro).and_return(:belongs_to)
66
+ allow(association).to receive(:klass).and_return(
67
+ double(:reflect_on_association => deep_association)
68
+ )
69
+
70
+ expect(type).to be_multi
66
71
  end
67
72
 
68
73
  it "respects the provided setting" do
69
74
  attribute.options[:multi] = true
70
75
 
71
- type.should be_multi
76
+ expect(type).to be_multi
72
77
  end
73
78
  end
74
79
 
@@ -76,79 +81,79 @@ describe ThinkingSphinx::ActiveRecord::Attribute::Type do
76
81
  it "returns the type option provided" do
77
82
  attribute.options[:type] = :datetime
78
83
 
79
- type.type.should == :datetime
84
+ expect(type.type).to eq(:datetime)
80
85
  end
81
86
 
82
87
  it "detects integer types from the database" do
83
- db_column.stub!(:type => :integer, :sql_type => 'integer(11)')
88
+ allow(db_column).to receive_messages(:type => :integer, :sql_type => 'integer(11)')
84
89
 
85
- type.type.should == :integer
90
+ expect(type.type).to eq(:integer)
86
91
  end
87
92
 
88
93
  it "detects boolean types from the database" do
89
- db_column.stub!(:type => :boolean)
94
+ allow(db_column).to receive_messages(:type => :boolean)
90
95
 
91
- type.type.should == :boolean
96
+ expect(type.type).to eq(:boolean)
92
97
  end
93
98
 
94
99
  it "detects datetime types from the database as timestamps" do
95
- db_column.stub!(:type => :datetime)
100
+ allow(db_column).to receive_messages(:type => :datetime)
96
101
 
97
- type.type.should == :timestamp
102
+ expect(type.type).to eq(:timestamp)
98
103
  end
99
104
 
100
105
  it "detects date types from the database as timestamps" do
101
- db_column.stub!(:type => :date)
106
+ allow(db_column).to receive_messages(:type => :date)
102
107
 
103
- type.type.should == :timestamp
108
+ expect(type.type).to eq(:timestamp)
104
109
  end
105
110
 
106
111
  it "detects string types from the database" do
107
- db_column.stub!(:type => :string)
112
+ allow(db_column).to receive_messages(:type => :string)
108
113
 
109
- type.type.should == :string
114
+ expect(type.type).to eq(:string)
110
115
  end
111
116
 
112
117
  it "detects text types from the database as strings" do
113
- db_column.stub!(:type => :text)
118
+ allow(db_column).to receive_messages(:type => :text)
114
119
 
115
- type.type.should == :string
120
+ expect(type.type).to eq(:string)
116
121
  end
117
122
 
118
123
  it "detects float types from the database" do
119
- db_column.stub!(:type => :float)
124
+ allow(db_column).to receive_messages(:type => :float)
120
125
 
121
- type.type.should == :float
126
+ expect(type.type).to eq(:float)
122
127
  end
123
128
 
124
129
  it "detects decimal types from the database as floats" do
125
- db_column.stub!(:type => :decimal)
130
+ allow(db_column).to receive_messages(:type => :decimal)
126
131
 
127
- type.type.should == :float
132
+ expect(type.type).to eq(:float)
128
133
  end
129
134
 
130
135
  it "detects big ints as big ints" do
131
- db_column.stub :type => :bigint
136
+ allow(db_column).to receive_messages :type => :bigint
132
137
 
133
- type.type.should == :bigint
138
+ expect(type.type).to eq(:bigint)
134
139
  end
135
140
 
136
141
  it "detects large integers as big ints" do
137
- db_column.stub :type => :integer, :sql_type => 'bigint(20)'
142
+ allow(db_column).to receive_messages :type => :integer, :sql_type => 'bigint(20)'
138
143
 
139
- type.type.should == :bigint
144
+ expect(type.type).to eq(:bigint)
140
145
  end
141
146
 
142
147
  it "detects JSON" do
143
- db_column.stub :type => :json
148
+ allow(db_column).to receive_messages :type => :json
144
149
 
145
- type.type.should == :json
150
+ expect(type.type).to eq(:json)
146
151
  end
147
152
 
148
153
  it "respects provided type setting" do
149
154
  attribute.options[:type] = :timestamp
150
155
 
151
- type.type.should == :timestamp
156
+ expect(type.type).to eq(:timestamp)
152
157
  end
153
158
 
154
159
  it 'raises an error if the database column does not exist' do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe ThinkingSphinx::ActiveRecord::Base do
@@ -16,34 +18,34 @@ describe ThinkingSphinx::ActiveRecord::Base do
16
18
 
17
19
  describe '.facets' do
18
20
  it "returns a new search object" do
19
- model.facets.should be_a(ThinkingSphinx::FacetSearch)
21
+ expect(model.facets).to be_a(ThinkingSphinx::FacetSearch)
20
22
  end
21
23
 
22
24
  it "passes through arguments to the search object" do
23
- model.facets('pancakes').query.should == 'pancakes'
25
+ expect(model.facets('pancakes').query).to eq('pancakes')
24
26
  end
25
27
 
26
28
  it "scopes the search to a given model" do
27
- model.facets('pancakes').options[:classes].should == [model]
29
+ expect(model.facets('pancakes').options[:classes]).to eq([model])
28
30
  end
29
31
 
30
32
  it "merges the :classes option with the model" do
31
- model.facets('pancakes', :classes => [sub_model]).
32
- options[:classes].should == [sub_model, model]
33
+ expect(model.facets('pancakes', :classes => [sub_model]).
34
+ options[:classes]).to eq([sub_model, model])
33
35
  end
34
36
 
35
37
  it "applies the default scope if there is one" do
36
- model.stub :default_sphinx_scope => :default,
38
+ allow(model).to receive_messages :default_sphinx_scope => :default,
37
39
  :sphinx_scopes => {:default => Proc.new { {:order => :created_at} }}
38
40
 
39
- model.facets.options[:order].should == :created_at
41
+ expect(model.facets.options[:order]).to eq(:created_at)
40
42
  end
41
43
 
42
44
  it "does not apply a default scope if one is not set" do
43
- model.stub :default_sphinx_scope => nil,
45
+ allow(model).to receive_messages :default_sphinx_scope => nil,
44
46
  :default => {:order => :created_at}
45
47
 
46
- model.facets.options[:order].should be_nil
48
+ expect(model.facets.options[:order]).to be_nil
47
49
  end
48
50
  end
49
51
 
@@ -55,55 +57,55 @@ describe ThinkingSphinx::ActiveRecord::Base do
55
57
  end
56
58
 
57
59
  it "returns a new search object" do
58
- model.search.should be_a(ThinkingSphinx::Search)
60
+ expect(model.search).to be_a(ThinkingSphinx::Search)
59
61
  end
60
62
 
61
63
  it "passes through arguments to the search object" do
62
- model.search('pancakes').query.should == 'pancakes'
64
+ expect(model.search('pancakes').query).to eq('pancakes')
63
65
  end
64
66
 
65
67
  it "scopes the search to a given model" do
66
- model.search('pancakes').options[:classes].should == [model]
68
+ expect(model.search('pancakes').options[:classes]).to eq([model])
67
69
  end
68
70
 
69
71
  it "passes through options to the search object" do
70
- model.search('pancakes', populate: true).
71
- options[:populate].should be_true
72
+ expect(model.search('pancakes', populate: true).
73
+ options[:populate]).to be_truthy
72
74
  end
73
75
 
74
76
  it "should automatically populate when :populate is set to true" do
75
- stack.should_receive(:call).and_return(true)
77
+ expect(stack).to receive(:call).and_return(true)
76
78
 
77
79
  model.search('pancakes', populate: true)
78
80
  end
79
81
 
80
82
  it "merges the :classes option with the model" do
81
- model.search('pancakes', :classes => [sub_model]).
82
- options[:classes].should == [sub_model, model]
83
+ expect(model.search('pancakes', :classes => [sub_model]).
84
+ options[:classes]).to eq([sub_model, model])
83
85
  end
84
86
 
85
87
  it "respects provided middleware" do
86
- model.search(:middleware => ThinkingSphinx::Middlewares::RAW_ONLY).
87
- options[:middleware].should == ThinkingSphinx::Middlewares::RAW_ONLY
88
+ expect(model.search(:middleware => ThinkingSphinx::Middlewares::RAW_ONLY).
89
+ options[:middleware]).to eq(ThinkingSphinx::Middlewares::RAW_ONLY)
88
90
  end
89
91
 
90
92
  it "respects provided masks" do
91
- model.search(:masks => [ThinkingSphinx::Masks::PaginationMask]).
92
- masks.should == [ThinkingSphinx::Masks::PaginationMask]
93
+ expect(model.search(:masks => [ThinkingSphinx::Masks::PaginationMask]).
94
+ masks).to eq([ThinkingSphinx::Masks::PaginationMask])
93
95
  end
94
96
 
95
97
  it "applies the default scope if there is one" do
96
- model.stub :default_sphinx_scope => :default,
98
+ allow(model).to receive_messages :default_sphinx_scope => :default,
97
99
  :sphinx_scopes => {:default => Proc.new { {:order => :created_at} }}
98
100
 
99
- model.search.options[:order].should == :created_at
101
+ expect(model.search.options[:order]).to eq(:created_at)
100
102
  end
101
103
 
102
104
  it "does not apply a default scope if one is not set" do
103
- model.stub :default_sphinx_scope => nil,
105
+ allow(model).to receive_messages :default_sphinx_scope => nil,
104
106
  :default => {:order => :created_at}
105
107
 
106
- model.search.options[:order].should be_nil
108
+ expect(model.search.options[:order]).to be_nil
107
109
  end
108
110
  end
109
111
 
@@ -112,18 +114,18 @@ describe ThinkingSphinx::ActiveRecord::Base do
112
114
  :populated? => false) }
113
115
 
114
116
  before :each do
115
- ThinkingSphinx.stub :search => search
116
- FileUtils.stub :mkdir_p => true
117
+ allow(ThinkingSphinx).to receive_messages :search => search
118
+ allow(FileUtils).to receive_messages :mkdir_p => true
117
119
  end
118
120
 
119
121
  it "returns the search object's total entries count" do
120
- model.search_count.should == search.total_entries
122
+ expect(model.search_count).to eq(search.total_entries)
121
123
  end
122
124
 
123
125
  it "scopes the search to a given model" do
124
126
  model.search_count
125
127
 
126
- search.options[:classes].should == [model]
128
+ expect(search.options[:classes]).to eq([model])
127
129
  end
128
130
  end
129
131
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe ThinkingSphinx::ActiveRecord::Callbacks::DeleteCallbacks do
@@ -10,20 +12,20 @@ describe ThinkingSphinx::ActiveRecord::Callbacks::DeleteCallbacks do
10
12
  let(:callbacks) { double('callbacks', :after_destroy => nil) }
11
13
 
12
14
  before :each do
13
- ThinkingSphinx::ActiveRecord::Callbacks::DeleteCallbacks.
14
- stub :new => callbacks
15
+ allow(ThinkingSphinx::ActiveRecord::Callbacks::DeleteCallbacks).
16
+ to receive_messages :new => callbacks
15
17
  end
16
18
 
17
19
  it "builds an object from the instance" do
18
- ThinkingSphinx::ActiveRecord::Callbacks::DeleteCallbacks.
19
- should_receive(:new).with(instance).and_return(callbacks)
20
+ expect(ThinkingSphinx::ActiveRecord::Callbacks::DeleteCallbacks).
21
+ to receive(:new).with(instance).and_return(callbacks)
20
22
 
21
23
  ThinkingSphinx::ActiveRecord::Callbacks::DeleteCallbacks.
22
24
  after_destroy(instance)
23
25
  end
24
26
 
25
27
  it "invokes after_destroy on the object" do
26
- callbacks.should_receive(:after_destroy)
28
+ expect(callbacks).to receive(:after_destroy)
27
29
 
28
30
  ThinkingSphinx::ActiveRecord::Callbacks::DeleteCallbacks.
29
31
  after_destroy(instance)
@@ -32,26 +34,95 @@ describe ThinkingSphinx::ActiveRecord::Callbacks::DeleteCallbacks do
32
34
 
33
35
  describe '#after_destroy' do
34
36
  let(:index_set) { double 'index set', :to_a => [index] }
35
- let(:index) { double('index', :name => 'foo_core',
37
+ let(:index) { double('index', :name => 'foo_core', :primary_key => :id,
36
38
  :document_id_for_key => 14, :type => 'plain', :distributed? => false) }
37
39
  let(:instance) { double('instance', :id => 7, :new_record? => false) }
38
40
 
39
41
  before :each do
40
- ThinkingSphinx::IndexSet.stub :new => index_set
42
+ allow(ThinkingSphinx::IndexSet).to receive_messages :new => index_set
41
43
  end
42
44
 
43
45
  it "performs the deletion for the index and instance" do
44
- ThinkingSphinx::Deletion.should_receive(:perform).with(index, 7)
46
+ expect(ThinkingSphinx::Deletion).to receive(:perform).with(index, 7)
45
47
 
46
48
  callbacks.after_destroy
47
49
  end
48
50
 
49
51
  it "doesn't do anything if the instance is a new record" do
50
- instance.stub :new_record? => true
52
+ allow(instance).to receive_messages :new_record? => true
53
+
54
+ expect(ThinkingSphinx::Deletion).not_to receive(:perform)
55
+
56
+ callbacks.after_destroy
57
+ end
58
+
59
+ it 'does nothing if callbacks are suspended' do
60
+ ThinkingSphinx::Callbacks.suspend!
51
61
 
52
- ThinkingSphinx::Deletion.should_not_receive(:perform)
62
+ expect(ThinkingSphinx::Deletion).not_to receive(:perform)
53
63
 
54
64
  callbacks.after_destroy
65
+
66
+ ThinkingSphinx::Callbacks.resume!
67
+ end
68
+ end
69
+
70
+ describe '.after_rollback' do
71
+ let(:callbacks) { double('callbacks', :after_rollback => nil) }
72
+
73
+ before :each do
74
+ allow(ThinkingSphinx::ActiveRecord::Callbacks::DeleteCallbacks).
75
+ to receive_messages :new => callbacks
76
+ end
77
+
78
+ it "builds an object from the instance" do
79
+ expect(ThinkingSphinx::ActiveRecord::Callbacks::DeleteCallbacks).
80
+ to receive(:new).with(instance).and_return(callbacks)
81
+
82
+ ThinkingSphinx::ActiveRecord::Callbacks::DeleteCallbacks.
83
+ after_rollback(instance)
84
+ end
85
+
86
+ it "invokes after_rollback on the object" do
87
+ expect(callbacks).to receive(:after_rollback)
88
+
89
+ ThinkingSphinx::ActiveRecord::Callbacks::DeleteCallbacks.
90
+ after_rollback(instance)
91
+ end
92
+ end
93
+
94
+ describe '#after_rollback' do
95
+ let(:index_set) { double 'index set', :to_a => [index] }
96
+ let(:index) { double('index', :name => 'foo_core', :primary_key => :id,
97
+ :document_id_for_key => 14, :type => 'plain', :distributed? => false) }
98
+ let(:instance) { double('instance', :id => 7, :new_record? => false) }
99
+
100
+ before :each do
101
+ allow(ThinkingSphinx::IndexSet).to receive_messages :new => index_set
102
+ end
103
+
104
+ it "performs the deletion for the index and instance" do
105
+ expect(ThinkingSphinx::Deletion).to receive(:perform).with(index, 7)
106
+
107
+ callbacks.after_rollback
108
+ end
109
+
110
+ it "doesn't do anything if the instance is a new record" do
111
+ allow(instance).to receive_messages :new_record? => true
112
+
113
+ expect(ThinkingSphinx::Deletion).not_to receive(:perform)
114
+
115
+ callbacks.after_rollback
116
+ end
117
+
118
+ it 'does nothing if callbacks are suspended' do
119
+ ThinkingSphinx::Callbacks.suspend!
120
+
121
+ expect(ThinkingSphinx::Deletion).not_to receive(:perform)
122
+
123
+ callbacks.after_rollback
124
+
125
+ ThinkingSphinx::Callbacks.resume!
55
126
  end
56
127
  end
57
128
  end