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
  module ThinkingSphinx
2
4
  module ActiveRecord
3
5
  class SQLBuilder::Query
@@ -18,10 +20,17 @@ module ThinkingSphinx
18
20
 
19
21
  def filter_by_query_pre
20
22
  scope_by_time_zone
23
+ scope_by_delta_processor
21
24
  scope_by_session
22
25
  scope_by_utf8
23
26
  end
24
27
 
28
+ def scope_by_delta_processor
29
+ return unless delta_processor && !source.delta?
30
+
31
+ self.scope << delta_processor.reset_query
32
+ end
33
+
25
34
  def scope_by_session
26
35
  return unless max_len = source.options[:group_concat_max_len]
27
36
 
@@ -38,6 +47,10 @@ module ThinkingSphinx
38
47
  self.scope += utf8_query_pre if source.options[:utf8?]
39
48
  end
40
49
 
50
+ def source
51
+ report.source
52
+ end
53
+
41
54
  def method_missing(*args, &block)
42
55
  report.send *args, &block
43
56
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'thinking_sphinx/active_record/sql_builder/clause_builder'
2
4
 
3
5
  module ThinkingSphinx
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ThinkingSphinx
2
4
  module ActiveRecord
3
5
  class SQLBuilder
@@ -20,12 +22,6 @@ module ThinkingSphinx
20
22
  query.to_query
21
23
  end
22
24
 
23
- def sql_query_post_index
24
- return [] unless delta_processor && !source.delta?
25
-
26
- [delta_processor.reset_query]
27
- end
28
-
29
25
  private
30
26
 
31
27
  delegate :adapter, :model, :delta_processor, :to => :source
@@ -49,18 +45,9 @@ module ThinkingSphinx
49
45
  end
50
46
 
51
47
  def associations
52
- @associations ||= begin
53
- joins = Joiner::Joins.new model
54
- if joins.respond_to?(:join_association_class)
55
- joins.join_association_class = ThinkingSphinx::ActiveRecord::JoinAssociation
56
- end
57
-
58
- source.associations.reject(&:string?).each do |association|
59
- joins.add_join_to association.stack
60
- end
61
-
62
- joins
63
- end
48
+ @associations ||= ThinkingSphinx::ActiveRecord::SourceJoins.call(
49
+ model, source
50
+ )
64
51
  end
65
52
 
66
53
  def quote_column(column)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class ThinkingSphinx::ActiveRecord::SQLSource::Template
2
4
  attr_reader :source
3
5
 
@@ -16,14 +18,14 @@ class ThinkingSphinx::ActiveRecord::SQLSource::Template
16
18
  private
17
19
 
18
20
  def add_attribute(column, name, type, options = {})
19
- source.attributes << ThinkingSphinx::ActiveRecord::Attribute.new(
21
+ source.add_attribute ThinkingSphinx::ActiveRecord::Attribute.new(
20
22
  source.model, ThinkingSphinx::ActiveRecord::Column.new(column),
21
23
  options.merge(:as => name, :type => type)
22
24
  )
23
25
  end
24
26
 
25
27
  def add_field(column, name, options = {})
26
- source.fields << ThinkingSphinx::ActiveRecord::Field.new(
28
+ source.add_field ThinkingSphinx::ActiveRecord::Field.new(
27
29
  source.model, ThinkingSphinx::ActiveRecord::Column.new(column),
28
30
  options.merge(:as => name)
29
31
  )
@@ -48,6 +50,6 @@ class ThinkingSphinx::ActiveRecord::SQLSource::Template
48
50
  end
49
51
 
50
52
  def primary_key
51
- source.model.primary_key.to_sym
53
+ source.options[:primary_key].to_sym
52
54
  end
53
55
  end
@@ -1,8 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ThinkingSphinx
2
4
  module ActiveRecord
3
5
  class SQLSource < Riddle::Configuration::SQLSource
4
6
  include ThinkingSphinx::Core::Settings
5
- attr_reader :model, :database_settings, :options
7
+
8
+ attr_reader :model, :options
6
9
  attr_accessor :fields, :attributes, :associations, :conditions,
7
10
  :groupings, :polymorphs
8
11
 
@@ -12,9 +15,8 @@ module ThinkingSphinx
12
15
 
13
16
  def initialize(model, options = {})
14
17
  @model = model
15
- @database_settings = model.connection.instance_variable_get(:@config).clone
16
18
  @options = {
17
- :utf8? => (@database_settings[:encoding] == 'utf8')
19
+ :utf8? => (database_settings[:encoding].to_s[/^utf8/])
18
20
  }.merge options
19
21
 
20
22
  @fields = []
@@ -37,6 +39,18 @@ module ThinkingSphinx
37
39
  @adapter ||= DatabaseAdapters.adapter_for(@model)
38
40
  end
39
41
 
42
+ def add_attribute(attribute)
43
+ attributes.delete_if { |existing| existing.name == attribute.name }
44
+
45
+ attributes << attribute
46
+ end
47
+
48
+ def add_field(field)
49
+ fields.delete_if { |existing| existing.name == field.name }
50
+
51
+ fields << field
52
+ end
53
+
40
54
  def delta_processor
41
55
  options[:delta_processor].try(:new, adapter, @options[:delta_options] || {})
42
56
  end
@@ -61,6 +75,10 @@ module ThinkingSphinx
61
75
  options[:primary_key]
62
76
  end
63
77
 
78
+ def properties
79
+ fields + attributes
80
+ end
81
+
64
82
  def render
65
83
  prepare_for_render unless @prepared
66
84
 
@@ -74,6 +92,9 @@ module ThinkingSphinx
74
92
  @sql_db ||= settings[:database]
75
93
  @sql_port ||= settings[:port]
76
94
  @sql_sock ||= settings[:socket]
95
+ @mysql_ssl_cert ||= settings[:sslcert]
96
+ @mysql_ssl_key ||= settings[:sslkey]
97
+ @mysql_ssl_ca ||= settings[:sslca]
77
98
  end
78
99
 
79
100
  def type
@@ -83,7 +104,7 @@ module ThinkingSphinx
83
104
  when DatabaseAdapters::PostgreSQLAdapter
84
105
  'pgsql'
85
106
  else
86
- raise "Unknown Adapter Type: #{adapter.class.name}"
107
+ raise UnknownDatabaseAdapter, "Provided type: #{adapter.class.name}"
87
108
  end
88
109
  end
89
110
 
@@ -119,13 +140,22 @@ module ThinkingSphinx
119
140
  @sql_query = builder.sql_query
120
141
  @sql_query_range ||= builder.sql_query_range
121
142
  @sql_query_pre += builder.sql_query_pre
122
- @sql_query_post_index += builder.sql_query_post_index
123
143
  end
124
144
 
125
145
  def config
126
146
  ThinkingSphinx::Configuration.instance
127
147
  end
128
148
 
149
+ def database_settings
150
+ @database_settings ||= begin
151
+ if model.connection.respond_to?(:config)
152
+ model.connection.config.clone
153
+ else
154
+ model.connection.instance_variable_get(:@config).clone
155
+ end
156
+ end
157
+ end
158
+
129
159
  def prepare_for_render
130
160
  polymorphs.each &:morph!
131
161
  append_presenter_to_attribute_array
@@ -136,10 +166,6 @@ module ThinkingSphinx
136
166
 
137
167
  @prepared = true
138
168
  end
139
-
140
- def properties
141
- fields + attributes
142
- end
143
169
  end
144
170
  end
145
171
  end
@@ -1,8 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_record'
2
4
  require 'joiner'
3
5
 
4
6
  module ThinkingSphinx::ActiveRecord
5
7
  module Callbacks; end
8
+ module Depolymorph; end
6
9
  end
7
10
 
8
11
  require 'thinking_sphinx/active_record/property'
@@ -14,7 +17,6 @@ require 'thinking_sphinx/active_record/column'
14
17
  require 'thinking_sphinx/active_record/column_sql_presenter'
15
18
  require 'thinking_sphinx/active_record/database_adapters'
16
19
  require 'thinking_sphinx/active_record/field'
17
- require 'thinking_sphinx/active_record/filter_reflection'
18
20
  require 'thinking_sphinx/active_record/index'
19
21
  require 'thinking_sphinx/active_record/interpreter'
20
22
  require 'thinking_sphinx/active_record/join_association'
@@ -23,9 +25,20 @@ require 'thinking_sphinx/active_record/polymorpher'
23
25
  require 'thinking_sphinx/active_record/property_query'
24
26
  require 'thinking_sphinx/active_record/property_sql_presenter'
25
27
  require 'thinking_sphinx/active_record/simple_many_query'
28
+ require 'thinking_sphinx/active_record/source_joins'
26
29
  require 'thinking_sphinx/active_record/sql_builder'
27
30
  require 'thinking_sphinx/active_record/sql_source'
28
31
 
32
+ require 'thinking_sphinx/active_record/callbacks/association_delta_callbacks'
29
33
  require 'thinking_sphinx/active_record/callbacks/delete_callbacks'
30
34
  require 'thinking_sphinx/active_record/callbacks/delta_callbacks'
31
35
  require 'thinking_sphinx/active_record/callbacks/update_callbacks'
36
+
37
+ require 'thinking_sphinx/active_record/depolymorph/base_reflection'
38
+ require 'thinking_sphinx/active_record/depolymorph/association_reflection'
39
+ require 'thinking_sphinx/active_record/depolymorph/conditions_reflection'
40
+ require 'thinking_sphinx/active_record/depolymorph/overridden_reflection'
41
+ require 'thinking_sphinx/active_record/depolymorph/scoped_reflection'
42
+ require 'thinking_sphinx/active_record/filter_reflection'
43
+
44
+ ActiveRecord::Base.include ThinkingSphinx::ActiveRecord::Base
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::AttributeTypes
4
+ def self.call
5
+ @call ||= new.call
6
+ end
7
+
8
+ def self.reset
9
+ @call = nil
10
+ end
11
+
12
+ def call
13
+ return {} unless File.exist?(configuration_file)
14
+
15
+ realtime_indices.each { |index|
16
+ map_types_with_prefix index, :rt,
17
+ [:uint, :bigint, :float, :timestamp, :string, :bool, :json]
18
+
19
+ index.rt_attr_multi.each { |name| attributes[name] << :uint }
20
+ index.rt_attr_multi_64.each { |name| attributes[name] << :bigint }
21
+ }
22
+
23
+ plain_sources.each { |source|
24
+ map_types_with_prefix source, :sql,
25
+ [:uint, :bigint, :float, :timestamp, :string, :bool, :json]
26
+
27
+ source.sql_attr_str2ordinal { |name| attributes[name] << :uint }
28
+ source.sql_attr_str2wordcount { |name| attributes[name] << :uint }
29
+ source.sql_attr_multi.each { |setting|
30
+ type, name, *ignored = setting.split(/\s+/)
31
+ attributes[name] << type.to_sym
32
+ }
33
+ }
34
+
35
+ attributes.values.each &:uniq!
36
+ attributes
37
+ end
38
+
39
+ private
40
+
41
+ def attributes
42
+ @attributes ||= Hash.new { |hash, key| hash[key] = [] }
43
+ end
44
+
45
+ def configuration
46
+ @configuration ||= Riddle::Configuration.parse!(
47
+ File.read(configuration_file)
48
+ )
49
+ end
50
+
51
+ def configuration_file
52
+ ThinkingSphinx::Configuration.instance.configuration_file
53
+ end
54
+
55
+ def map_types_with_prefix(object, prefix, types)
56
+ types.each do |type|
57
+ object.public_send("#{prefix}_attr_#{type}").each do |name|
58
+ attributes[name] << type
59
+ end
60
+ end
61
+ end
62
+
63
+ def plain_sources
64
+ configuration.indices.select { |index|
65
+ index.type == 'plain' || index.type.nil?
66
+ }.collect(&:sources).flatten
67
+ end
68
+
69
+ def realtime_indices
70
+ configuration.indices.select { |index| index.type == 'rt' }
71
+ end
72
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class ThinkingSphinx::BatchedSearch
2
4
  attr_accessor :searches
3
5
 
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::Callbacks::Appender
4
+ def self.call(model, reference, options, &block)
5
+ new(model, reference, options, &block).call
6
+ end
7
+
8
+ def initialize(model, reference, options, &block)
9
+ @model = model
10
+ @reference = reference
11
+ @options = options
12
+ @block = block
13
+ end
14
+
15
+ def call
16
+ add_core_callbacks
17
+ add_delta_callbacks if behaviours.include?(:deltas)
18
+ add_real_time_callbacks if behaviours.include?(:real_time)
19
+ add_update_callbacks if behaviours.include?(:updates)
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :model, :reference, :options, :block
25
+
26
+ def add_core_callbacks
27
+ model.after_commit(
28
+ ThinkingSphinx::ActiveRecord::Callbacks::DeleteCallbacks,
29
+ on: :destroy
30
+ )
31
+ end
32
+
33
+ def add_delta_callbacks
34
+ if path.empty?
35
+ model.before_save ThinkingSphinx::ActiveRecord::Callbacks::DeltaCallbacks
36
+ model.after_commit ThinkingSphinx::ActiveRecord::Callbacks::DeltaCallbacks
37
+ else
38
+ model.after_commit(
39
+ ThinkingSphinx::ActiveRecord::Callbacks::AssociationDeltaCallbacks
40
+ .new(path)
41
+ )
42
+ end
43
+ end
44
+
45
+ def add_real_time_callbacks
46
+ model.after_commit(
47
+ ThinkingSphinx::RealTime.callback_for(reference, path, &block),
48
+ on: [:create, :update]
49
+ )
50
+ end
51
+
52
+ def add_update_callbacks
53
+ model.after_update ThinkingSphinx::ActiveRecord::Callbacks::UpdateCallbacks
54
+ end
55
+
56
+ def behaviours
57
+ options[:behaviours] || []
58
+ end
59
+
60
+ def path
61
+ options[:path] || []
62
+ end
63
+ end
@@ -1,6 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class ThinkingSphinx::Callbacks
2
4
  attr_reader :instance
3
5
 
6
+ def self.append(model, reference = nil, options, &block)
7
+ reference ||= ThinkingSphinx::Configuration.instance.index_set_class.
8
+ reference_name(model)
9
+
10
+ ThinkingSphinx::Callbacks::Appender.call(model, reference, options, &block)
11
+ end
12
+
4
13
  def self.callbacks(*methods)
5
14
  mod = Module.new
6
15
  methods.each do |method|
@@ -9,7 +18,27 @@ class ThinkingSphinx::Callbacks
9
18
  extend mod
10
19
  end
11
20
 
21
+ def self.resume!
22
+ @suspended = false
23
+ end
24
+
25
+ def self.suspend(&block)
26
+ suspend!
27
+ yield
28
+ resume!
29
+ end
30
+
31
+ def self.suspend!
32
+ @suspended = true
33
+ end
34
+
35
+ def self.suspended?
36
+ @suspended
37
+ end
38
+
12
39
  def initialize(instance)
13
40
  @instance = instance
14
41
  end
15
42
  end
43
+
44
+ require "thinking_sphinx/callbacks/appender"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Capistrano::Configuration.instance(:must_exist).load do
2
4
  _cset(:thinking_sphinx_roles) { :db }
3
5
  _cset(:thinking_sphinx_options) { {:roles => fetch(:thinking_sphinx_roles)} }
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  namespace :load do
2
4
  task :defaults do
3
5
  set :thinking_sphinx_roles, :db
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  if defined?(Capistrano::VERSION)
2
4
  if Gem::Version.new(Capistrano::VERSION).release >= Gem::Version.new('3.0.0')
3
5
  recipe_version = 3
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::Commander
4
+ def self.call(command, configuration, options, stream = STDOUT)
5
+ raise ThinkingSphinx::UnknownCommand unless registry.keys.include?(command)
6
+
7
+ registry[command].call configuration, options, stream
8
+ end
9
+
10
+ def self.registry
11
+ @registry ||= {
12
+ :clear_real_time => ThinkingSphinx::Commands::ClearRealTime,
13
+ :clear_sql => ThinkingSphinx::Commands::ClearSQL,
14
+ :configure => ThinkingSphinx::Commands::Configure,
15
+ :index_sql => ThinkingSphinx::Commands::IndexSQL,
16
+ :index_real_time => ThinkingSphinx::Commands::IndexRealTime,
17
+ :merge => ThinkingSphinx::Commands::Merge,
18
+ :merge_and_update => ThinkingSphinx::Commands::MergeAndUpdate,
19
+ :prepare => ThinkingSphinx::Commands::Prepare,
20
+ :rotate => ThinkingSphinx::Commands::Rotate,
21
+ :running => ThinkingSphinx::Commands::Running,
22
+ :start_attached => ThinkingSphinx::Commands::StartAttached,
23
+ :start_detached => ThinkingSphinx::Commands::StartDetached,
24
+ :stop => ThinkingSphinx::Commands::Stop
25
+ }
26
+ end
27
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::Commands::Base
4
+ include ThinkingSphinx::WithOutput
5
+
6
+ def self.call(configuration, options, stream = STDOUT)
7
+ new(configuration, options, stream).call_with_handling
8
+ end
9
+
10
+ def call_with_handling
11
+ call
12
+ rescue Riddle::CommandFailedError => error
13
+ handle_failure error.command_result
14
+ end
15
+
16
+ private
17
+
18
+ delegate :controller, :to => :configuration
19
+
20
+ def command(command, extra_options = {})
21
+ ThinkingSphinx::Commander.call(
22
+ command, configuration, options.merge(extra_options), stream
23
+ )
24
+ end
25
+
26
+ def command_output(output)
27
+ return "See above\n" if output.nil?
28
+
29
+ "\n\t" + output.gsub("\n", "\n\t")
30
+ end
31
+
32
+ def handle_failure(result)
33
+ stream.puts <<-TXT
34
+
35
+ The Sphinx #{type} command failed:
36
+ Command: #{result.command}
37
+ Status: #{result.status}
38
+ Output: #{command_output result.output}
39
+ There may be more information about the failure in #{configuration.searchd.log}.
40
+ TXT
41
+ exit(result.status || 1)
42
+ end
43
+
44
+ def log(message)
45
+ return if options[:silent]
46
+
47
+ stream.puts message
48
+ end
49
+
50
+ def skip_directories?
51
+ configuration.settings['skip_directory_creation']
52
+ end
53
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::Commands::ClearRealTime < ThinkingSphinx::Commands::Base
4
+ def call
5
+ options[:indices].each do |index|
6
+ index.render
7
+ Dir["#{index.path}.*"].each { |path| FileUtils.rm path }
8
+ end
9
+
10
+ FileUtils.rm_rf(binlog_path) if File.exist?(binlog_path)
11
+ end
12
+
13
+ private
14
+
15
+ def binlog_path
16
+ configuration.searchd.binlog_path
17
+ end
18
+
19
+ def type
20
+ 'clear_realtime'
21
+ end
22
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::Commands::ClearSQL < ThinkingSphinx::Commands::Base
4
+ def call
5
+ options[:indices].each do |index|
6
+ index.render
7
+ Dir["#{index.path}.*"].each { |path| FileUtils.rm path }
8
+ end
9
+
10
+ FileUtils.rm_rf Dir["#{configuration.indices_location}/ts-*.tmp"]
11
+ end
12
+
13
+ private
14
+
15
+ def type
16
+ 'clear_sql'
17
+ end
18
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::Commands::Configure < ThinkingSphinx::Commands::Base
4
+ def call
5
+ log "Generating configuration to #{configuration.configuration_file}"
6
+
7
+ configuration.render_to_file
8
+ end
9
+
10
+ private
11
+
12
+ def type
13
+ 'configure'
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::Commands::IndexRealTime < ThinkingSphinx::Commands::Base
4
+ def call
5
+ ThinkingSphinx::RealTime.processor.call options[:indices] do
6
+ command :rotate
7
+ end
8
+ end
9
+
10
+ private
11
+
12
+ def type
13
+ 'indexing'
14
+ end
15
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::Commands::IndexSQL < ThinkingSphinx::Commands::Base
4
+ def call
5
+ if indices.empty?
6
+ ThinkingSphinx.before_index_hooks.each { |hook| hook.call }
7
+ end
8
+
9
+ configuration.indexing_strategy.call(indices) do |index_names|
10
+ configuration.guarding_strategy.call(index_names) do |names|
11
+ controller.index *names, :verbose => options[:verbose]
12
+ end
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def indices
19
+ options[:indices] || []
20
+ end
21
+
22
+ def type
23
+ 'indexing'
24
+ end
25
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::Commands::Merge < ThinkingSphinx::Commands::Base
4
+ def call
5
+ return unless indices_exist?
6
+
7
+ controller.merge(
8
+ options[:core_index].name,
9
+ options[:delta_index].name,
10
+ :filters => options[:filters],
11
+ :verbose => options[:verbose]
12
+ )
13
+ end
14
+
15
+ private
16
+
17
+ delegate :controller, :to => :configuration
18
+
19
+ def indices_exist?
20
+ File.exist?("#{options[:core_index].path}.spi") &&
21
+ File.exist?("#{options[:delta_index].path}.spi")
22
+ end
23
+
24
+ def type
25
+ 'merging'
26
+ end
27
+ end