thinking-sphinx 1.2.13 → 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 (517) hide show
  1. checksums.yaml +7 -0
  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 +18 -0
  6. data/.travis.yml +36 -0
  7. data/Appraisals +71 -0
  8. data/CHANGELOG.markdown +782 -0
  9. data/Gemfile +18 -0
  10. data/LICENCE +1 -1
  11. data/Procfile.support +2 -0
  12. data/README.textile +91 -136
  13. data/Rakefile +26 -0
  14. data/bin/console +15 -0
  15. data/bin/loadsphinx +99 -0
  16. data/bin/testmatrix +48 -0
  17. data/lib/thinking/sphinx.rb +3 -0
  18. data/lib/thinking-sphinx.rb +3 -0
  19. data/lib/thinking_sphinx/active_record/association.rb +19 -0
  20. data/lib/thinking_sphinx/active_record/association_proxy/attribute_finder.rb +44 -0
  21. data/lib/thinking_sphinx/active_record/association_proxy/attribute_matcher.rb +40 -0
  22. data/lib/thinking_sphinx/active_record/association_proxy.rb +34 -0
  23. data/lib/thinking_sphinx/active_record/attribute/sphinx_presenter.rb +52 -0
  24. data/lib/thinking_sphinx/active_record/attribute/type.rb +106 -0
  25. data/lib/thinking_sphinx/active_record/attribute/values.rb +20 -0
  26. data/lib/thinking_sphinx/active_record/attribute.rb +22 -0
  27. data/lib/thinking_sphinx/active_record/base.rb +91 -0
  28. data/lib/thinking_sphinx/active_record/callbacks/association_delta_callbacks.rb +21 -0
  29. data/lib/thinking_sphinx/active_record/callbacks/delete_callbacks.rb +27 -0
  30. data/lib/thinking_sphinx/active_record/callbacks/delta_callbacks.rb +66 -0
  31. data/lib/thinking_sphinx/active_record/callbacks/update_callbacks.rb +78 -0
  32. data/lib/thinking_sphinx/active_record/column.rb +44 -0
  33. data/lib/thinking_sphinx/active_record/column_sql_presenter.rb +54 -0
  34. data/lib/thinking_sphinx/active_record/database_adapters/abstract_adapter.rb +19 -0
  35. data/lib/thinking_sphinx/active_record/database_adapters/mysql_adapter.rb +51 -0
  36. data/lib/thinking_sphinx/active_record/database_adapters/postgresql_adapter.rb +47 -0
  37. data/lib/thinking_sphinx/active_record/database_adapters.rb +59 -0
  38. data/lib/thinking_sphinx/active_record/depolymorph/association_reflection.rb +32 -0
  39. data/lib/thinking_sphinx/active_record/depolymorph/base_reflection.rb +32 -0
  40. data/lib/thinking_sphinx/active_record/depolymorph/conditions_reflection.rb +40 -0
  41. data/lib/thinking_sphinx/active_record/depolymorph/overridden_reflection.rb +50 -0
  42. data/lib/thinking_sphinx/active_record/depolymorph/scoped_reflection.rb +26 -0
  43. data/lib/thinking_sphinx/active_record/field.rb +18 -0
  44. data/lib/thinking_sphinx/active_record/filter_reflection.rb +18 -0
  45. data/lib/thinking_sphinx/active_record/index.rb +71 -0
  46. data/lib/thinking_sphinx/active_record/interpreter.rb +77 -0
  47. data/lib/thinking_sphinx/active_record/join_association.rb +17 -0
  48. data/lib/thinking_sphinx/active_record/log_subscriber.rb +37 -0
  49. data/lib/thinking_sphinx/active_record/polymorpher.rb +64 -0
  50. data/lib/thinking_sphinx/active_record/property.rb +30 -0
  51. data/lib/thinking_sphinx/active_record/property_query.rb +149 -0
  52. data/lib/thinking_sphinx/active_record/property_sql_presenter.rb +89 -0
  53. data/lib/thinking_sphinx/active_record/simple_many_query.rb +37 -0
  54. data/lib/thinking_sphinx/active_record/source_joins.rb +68 -0
  55. data/lib/thinking_sphinx/active_record/sql_builder/clause_builder.rb +29 -0
  56. data/lib/thinking_sphinx/active_record/sql_builder/query.rb +59 -0
  57. data/lib/thinking_sphinx/active_record/sql_builder/statement.rb +147 -0
  58. data/lib/thinking_sphinx/active_record/sql_builder.rb +107 -0
  59. data/lib/thinking_sphinx/active_record/sql_source/template.rb +55 -0
  60. data/lib/thinking_sphinx/active_record/sql_source.rb +173 -0
  61. data/lib/thinking_sphinx/active_record.rb +39 -301
  62. data/lib/thinking_sphinx/attribute_types.rb +72 -0
  63. data/lib/thinking_sphinx/batched_search.rb +28 -0
  64. data/lib/thinking_sphinx/callbacks/appender.rb +63 -0
  65. data/lib/thinking_sphinx/callbacks.rb +44 -0
  66. data/lib/thinking_sphinx/capistrano/v2.rb +60 -0
  67. data/lib/thinking_sphinx/capistrano/v3.rb +104 -0
  68. data/lib/thinking_sphinx/capistrano.rb +10 -0
  69. data/lib/thinking_sphinx/commander.rb +27 -0
  70. data/lib/thinking_sphinx/commands/base.rb +53 -0
  71. data/lib/thinking_sphinx/commands/clear_real_time.rb +22 -0
  72. data/lib/thinking_sphinx/commands/clear_sql.rb +18 -0
  73. data/lib/thinking_sphinx/commands/configure.rb +15 -0
  74. data/lib/thinking_sphinx/commands/index_real_time.rb +15 -0
  75. data/lib/thinking_sphinx/commands/index_sql.rb +25 -0
  76. data/lib/thinking_sphinx/commands/merge.rb +27 -0
  77. data/lib/thinking_sphinx/commands/merge_and_update.rb +57 -0
  78. data/lib/thinking_sphinx/commands/prepare.rb +15 -0
  79. data/lib/thinking_sphinx/commands/rotate.rb +13 -0
  80. data/lib/thinking_sphinx/commands/running.rb +15 -0
  81. data/lib/thinking_sphinx/commands/start_attached.rb +22 -0
  82. data/lib/thinking_sphinx/commands/start_detached.rb +21 -0
  83. data/lib/thinking_sphinx/commands/stop.rb +24 -0
  84. data/lib/thinking_sphinx/commands.rb +20 -0
  85. data/lib/thinking_sphinx/configuration/consistent_ids.rb +35 -0
  86. data/lib/thinking_sphinx/configuration/defaults.rb +7 -0
  87. data/lib/thinking_sphinx/configuration/distributed_indices.rb +31 -0
  88. data/lib/thinking_sphinx/configuration/duplicate_names.rb +36 -0
  89. data/lib/thinking_sphinx/configuration/minimum_fields.rb +36 -0
  90. data/lib/thinking_sphinx/configuration.rb +196 -269
  91. data/lib/thinking_sphinx/connection/client.rb +74 -0
  92. data/lib/thinking_sphinx/connection/jruby.rb +58 -0
  93. data/lib/thinking_sphinx/connection/mri.rb +26 -0
  94. data/lib/thinking_sphinx/connection.rb +73 -0
  95. data/lib/thinking_sphinx/core/field.rb +11 -0
  96. data/lib/thinking_sphinx/core/index.rb +110 -0
  97. data/lib/thinking_sphinx/core/interpreter.rb +25 -0
  98. data/lib/thinking_sphinx/core/property.rb +15 -0
  99. data/lib/thinking_sphinx/core/settings.rb +11 -0
  100. data/lib/thinking_sphinx/core.rb +11 -0
  101. data/lib/thinking_sphinx/deletion.rb +70 -0
  102. data/lib/thinking_sphinx/deltas/default_delta.rb +57 -66
  103. data/lib/thinking_sphinx/deltas/delete_job.rb +27 -0
  104. data/lib/thinking_sphinx/deltas/index_job.rb +28 -0
  105. data/lib/thinking_sphinx/deltas.rb +52 -27
  106. data/lib/thinking_sphinx/distributed/index.rb +46 -0
  107. data/lib/thinking_sphinx/distributed.rb +7 -0
  108. data/lib/thinking_sphinx/errors.rb +96 -0
  109. data/lib/thinking_sphinx/excerpter.rb +36 -19
  110. data/lib/thinking_sphinx/facet.rb +29 -122
  111. data/lib/thinking_sphinx/facet_search.rb +132 -125
  112. data/lib/thinking_sphinx/float_formatter.rb +35 -0
  113. data/lib/thinking_sphinx/frameworks/plain.rb +10 -0
  114. data/lib/thinking_sphinx/frameworks/rails.rb +11 -0
  115. data/lib/thinking_sphinx/frameworks.rb +11 -0
  116. data/lib/thinking_sphinx/guard/file.rb +28 -0
  117. data/lib/thinking_sphinx/guard/files.rb +40 -0
  118. data/lib/thinking_sphinx/guard/none.rb +7 -0
  119. data/lib/thinking_sphinx/guard.rb +9 -0
  120. data/lib/thinking_sphinx/hooks/guard_presence.rb +34 -0
  121. data/lib/thinking_sphinx/index.rb +50 -92
  122. data/lib/thinking_sphinx/index_set.rb +96 -0
  123. data/lib/thinking_sphinx/indexing_strategies/all_at_once.rb +9 -0
  124. data/lib/thinking_sphinx/indexing_strategies/one_at_a_time.rb +16 -0
  125. data/lib/thinking_sphinx/interfaces/base.rb +13 -0
  126. data/lib/thinking_sphinx/interfaces/daemon.rb +27 -0
  127. data/lib/thinking_sphinx/interfaces/real_time.rb +46 -0
  128. data/lib/thinking_sphinx/interfaces/sql.rb +53 -0
  129. data/lib/thinking_sphinx/interfaces.rb +10 -0
  130. data/lib/thinking_sphinx/logger.rb +9 -0
  131. data/lib/thinking_sphinx/masks/group_enumerators_mask.rb +30 -0
  132. data/lib/thinking_sphinx/masks/pagination_mask.rb +63 -0
  133. data/lib/thinking_sphinx/masks/scopes_mask.rb +56 -0
  134. data/lib/thinking_sphinx/masks/weight_enumerator_mask.rb +17 -0
  135. data/lib/thinking_sphinx/masks.rb +10 -0
  136. data/lib/thinking_sphinx/middlewares/active_record_translator.rb +103 -0
  137. data/lib/thinking_sphinx/middlewares/geographer.rb +94 -0
  138. data/lib/thinking_sphinx/middlewares/glazier.rb +52 -0
  139. data/lib/thinking_sphinx/middlewares/ids_only.rb +15 -0
  140. data/lib/thinking_sphinx/middlewares/inquirer.rb +64 -0
  141. data/lib/thinking_sphinx/middlewares/middleware.rb +11 -0
  142. data/lib/thinking_sphinx/middlewares/sphinxql.rb +256 -0
  143. data/lib/thinking_sphinx/middlewares/stale_id_checker.rb +47 -0
  144. data/lib/thinking_sphinx/middlewares/stale_id_filter.rb +48 -0
  145. data/lib/thinking_sphinx/middlewares/valid_options.rb +25 -0
  146. data/lib/thinking_sphinx/middlewares.rb +35 -0
  147. data/lib/thinking_sphinx/panes/attributes_pane.rb +11 -0
  148. data/lib/thinking_sphinx/panes/distance_pane.rb +15 -0
  149. data/lib/thinking_sphinx/panes/excerpts_pane.rb +43 -0
  150. data/lib/thinking_sphinx/panes/weight_pane.rb +11 -0
  151. data/lib/thinking_sphinx/panes.rb +10 -0
  152. data/lib/thinking_sphinx/processor.rb +71 -0
  153. data/lib/thinking_sphinx/query.rb +11 -0
  154. data/lib/thinking_sphinx/railtie.rb +38 -0
  155. data/lib/thinking_sphinx/rake_interface.rb +34 -0
  156. data/lib/thinking_sphinx/real_time/attribute.rb +27 -0
  157. data/lib/thinking_sphinx/real_time/callbacks/real_time_callbacks.rb +60 -0
  158. data/lib/thinking_sphinx/real_time/field.rb +9 -0
  159. data/lib/thinking_sphinx/real_time/index/template.rb +52 -0
  160. data/lib/thinking_sphinx/real_time/index.rb +102 -0
  161. data/lib/thinking_sphinx/real_time/interpreter.rb +54 -0
  162. data/lib/thinking_sphinx/real_time/populator.rb +46 -0
  163. data/lib/thinking_sphinx/real_time/processor.rb +36 -0
  164. data/lib/thinking_sphinx/real_time/property.rb +21 -0
  165. data/lib/thinking_sphinx/real_time/transcribe_instance.rb +38 -0
  166. data/lib/thinking_sphinx/real_time/transcriber.rb +89 -0
  167. data/lib/thinking_sphinx/real_time/translator.rb +39 -0
  168. data/lib/thinking_sphinx/real_time.rb +40 -0
  169. data/lib/thinking_sphinx/scopes.rb +34 -0
  170. data/lib/thinking_sphinx/search/batch_inquirer.rb +23 -0
  171. data/lib/thinking_sphinx/search/context.rb +31 -0
  172. data/lib/thinking_sphinx/search/glaze.rb +39 -0
  173. data/lib/thinking_sphinx/search/merger.rb +34 -0
  174. data/lib/thinking_sphinx/search/query.rb +33 -0
  175. data/lib/thinking_sphinx/search/stale_ids_exception.rb +15 -0
  176. data/lib/thinking_sphinx/search.rb +166 -704
  177. data/lib/thinking_sphinx/settings.rb +128 -0
  178. data/lib/thinking_sphinx/sinatra.rb +7 -0
  179. data/lib/thinking_sphinx/subscribers/populator_subscriber.rb +48 -0
  180. data/lib/thinking_sphinx/tasks.rb +70 -150
  181. data/lib/thinking_sphinx/test.rb +56 -0
  182. data/lib/thinking_sphinx/utf8.rb +18 -0
  183. data/lib/thinking_sphinx/wildcard.rb +42 -0
  184. data/lib/thinking_sphinx/with_output.rb +13 -0
  185. data/lib/thinking_sphinx.rb +83 -185
  186. data/spec/acceptance/association_scoping_spec.rb +65 -0
  187. data/spec/acceptance/attribute_access_spec.rb +58 -0
  188. data/spec/acceptance/attribute_updates_spec.rb +18 -0
  189. data/spec/acceptance/batch_searching_spec.rb +23 -0
  190. data/spec/acceptance/big_integers_spec.rb +61 -0
  191. data/spec/acceptance/excerpts_spec.rb +50 -0
  192. data/spec/acceptance/facets_spec.rb +141 -0
  193. data/spec/acceptance/geosearching_spec.rb +70 -0
  194. data/spec/acceptance/grouping_by_attributes_spec.rb +79 -0
  195. data/spec/acceptance/index_options_spec.rb +154 -0
  196. data/spec/acceptance/indexing_spec.rb +38 -0
  197. data/spec/acceptance/merging_spec.rb +90 -0
  198. data/spec/acceptance/paginating_search_results_spec.rb +42 -0
  199. data/spec/acceptance/real_time_updates_spec.rb +115 -0
  200. data/spec/acceptance/remove_deleted_records_spec.rb +99 -0
  201. data/spec/acceptance/search_counts_spec.rb +20 -0
  202. data/spec/acceptance/search_for_just_ids_spec.rb +21 -0
  203. data/spec/acceptance/searching_across_models_spec.rb +47 -0
  204. data/spec/acceptance/searching_across_schemas_spec.rb +40 -0
  205. data/spec/acceptance/searching_on_fields_spec.rb +59 -0
  206. data/spec/acceptance/searching_with_filters_spec.rb +159 -0
  207. data/spec/acceptance/searching_with_sti_spec.rb +76 -0
  208. data/spec/acceptance/searching_within_a_model_spec.rb +117 -0
  209. data/spec/acceptance/sorting_search_results_spec.rb +50 -0
  210. data/spec/acceptance/spec_helper.rb +6 -0
  211. data/spec/acceptance/specifying_sql_spec.rb +516 -0
  212. data/spec/acceptance/sphinx_scopes_spec.rb +87 -0
  213. data/spec/acceptance/sql_deltas_spec.rb +78 -0
  214. data/spec/acceptance/support/database_cleaner.rb +13 -0
  215. data/spec/acceptance/support/sphinx_controller.rb +62 -0
  216. data/spec/acceptance/support/sphinx_helpers.rb +45 -0
  217. data/spec/acceptance/suspended_deltas_spec.rb +56 -0
  218. data/spec/fixtures/database.yml +4 -0
  219. data/spec/internal/app/indices/admin_person_index.rb +9 -0
  220. data/spec/internal/app/indices/album_index.rb +9 -0
  221. data/spec/internal/app/indices/animal_index.rb +5 -0
  222. data/spec/internal/app/indices/article_index.rb +31 -0
  223. data/spec/internal/app/indices/bird_index.rb +6 -0
  224. data/spec/internal/app/indices/book_index.rb +11 -0
  225. data/spec/internal/app/indices/car_index.rb +7 -0
  226. data/spec/internal/app/indices/city_index.rb +9 -0
  227. data/spec/internal/app/indices/colour_index.rb +7 -0
  228. data/spec/internal/app/indices/product_index.rb +27 -0
  229. data/spec/internal/app/indices/tee_index.rb +6 -0
  230. data/spec/internal/app/indices/user_index.rb +9 -0
  231. data/spec/internal/app/models/admin/person.rb +9 -0
  232. data/spec/internal/app/models/album.rb +25 -0
  233. data/spec/internal/app/models/animal.rb +5 -0
  234. data/spec/internal/app/models/article.rb +9 -0
  235. data/spec/internal/app/models/bird.rb +5 -0
  236. data/spec/internal/app/models/book.rb +18 -0
  237. data/spec/internal/app/models/car.rb +7 -0
  238. data/spec/internal/app/models/categorisation.rb +15 -0
  239. data/spec/internal/app/models/category.rb +6 -0
  240. data/spec/internal/app/models/city.rb +7 -0
  241. data/spec/internal/app/models/colour.rb +7 -0
  242. data/spec/internal/app/models/event.rb +5 -0
  243. data/spec/internal/app/models/flightless_bird.rb +4 -0
  244. data/spec/internal/app/models/genre.rb +5 -0
  245. data/spec/internal/app/models/hardcover.rb +5 -0
  246. data/spec/internal/app/models/mammal.rb +4 -0
  247. data/spec/internal/app/models/manufacturer.rb +5 -0
  248. data/spec/internal/app/models/product.rb +8 -0
  249. data/spec/internal/app/models/tag.rb +6 -0
  250. data/{features/support → spec/internal/app}/models/tagging.rb +3 -1
  251. data/spec/internal/app/models/tee.rb +10 -0
  252. data/spec/internal/app/models/tweet.rb +5 -0
  253. data/spec/internal/app/models/user.rb +10 -0
  254. data/spec/internal/config/database.yml +17 -0
  255. data/spec/internal/db/schema.rb +115 -0
  256. data/spec/internal/tmp/.gitkeep +0 -0
  257. data/spec/spec_helper.rb +29 -0
  258. data/spec/support/json_column.rb +35 -0
  259. data/spec/support/multi_schema.rb +50 -0
  260. data/spec/support/mysql.rb +25 -0
  261. data/spec/support/sphinx_yaml_helpers.rb +16 -0
  262. data/spec/thinking_sphinx/active_record/association_spec.rb +14 -0
  263. data/spec/thinking_sphinx/active_record/attribute/type_spec.rb +165 -0
  264. data/spec/thinking_sphinx/active_record/base_spec.rb +131 -0
  265. data/spec/thinking_sphinx/active_record/callbacks/delete_callbacks_spec.rb +128 -0
  266. data/spec/thinking_sphinx/active_record/callbacks/delta_callbacks_spec.rb +176 -0
  267. data/spec/thinking_sphinx/active_record/callbacks/update_callbacks_spec.rb +91 -0
  268. data/spec/thinking_sphinx/active_record/column_spec.rb +72 -0
  269. data/spec/thinking_sphinx/active_record/column_sql_presenter_spec.rb +39 -0
  270. data/spec/thinking_sphinx/active_record/database_adapters/abstract_adapter_spec.rb +33 -0
  271. data/spec/thinking_sphinx/active_record/database_adapters/mysql_adapter_spec.rb +70 -0
  272. data/spec/thinking_sphinx/active_record/database_adapters/postgresql_adapter_spec.rb +66 -0
  273. data/spec/thinking_sphinx/active_record/database_adapters_spec.rb +128 -0
  274. data/spec/thinking_sphinx/active_record/field_spec.rb +51 -0
  275. data/spec/thinking_sphinx/active_record/filter_reflection_spec.rb +207 -0
  276. data/spec/thinking_sphinx/active_record/index_spec.rb +220 -0
  277. data/spec/thinking_sphinx/active_record/interpreter_spec.rb +329 -0
  278. data/spec/thinking_sphinx/active_record/polymorpher_spec.rb +87 -0
  279. data/spec/thinking_sphinx/active_record/property_sql_presenter_spec.rb +264 -0
  280. data/spec/thinking_sphinx/active_record/sql_builder_spec.rb +662 -0
  281. data/spec/thinking_sphinx/active_record/sql_source_spec.rb +507 -0
  282. data/spec/thinking_sphinx/attribute_types_spec.rb +52 -0
  283. data/spec/thinking_sphinx/commands/clear_real_time_spec.rb +46 -0
  284. data/spec/thinking_sphinx/commands/clear_sql_spec.rb +52 -0
  285. data/spec/thinking_sphinx/commands/configure_spec.rb +31 -0
  286. data/spec/thinking_sphinx/commands/index_real_time_spec.rb +33 -0
  287. data/spec/thinking_sphinx/commands/index_sql_spec.rb +86 -0
  288. data/spec/thinking_sphinx/commands/merge_and_update_spec.rb +106 -0
  289. data/spec/thinking_sphinx/commands/merge_spec.rb +48 -0
  290. data/spec/thinking_sphinx/commands/prepare_spec.rb +31 -0
  291. data/spec/thinking_sphinx/commands/running_spec.rb +30 -0
  292. data/spec/thinking_sphinx/commands/start_detached_spec.rb +67 -0
  293. data/spec/thinking_sphinx/commands/stop_spec.rb +63 -0
  294. data/spec/thinking_sphinx/configuration/minimum_fields_spec.rb +60 -0
  295. data/spec/thinking_sphinx/configuration_spec.rb +582 -0
  296. data/spec/thinking_sphinx/connection/mri_spec.rb +49 -0
  297. data/spec/thinking_sphinx/connection_spec.rb +87 -0
  298. data/spec/thinking_sphinx/deletion_spec.rb +57 -0
  299. data/spec/thinking_sphinx/deltas/default_delta_spec.rb +123 -0
  300. data/spec/thinking_sphinx/deltas_spec.rb +77 -0
  301. data/spec/thinking_sphinx/errors_spec.rb +103 -0
  302. data/spec/thinking_sphinx/excerpter_spec.rb +53 -0
  303. data/spec/thinking_sphinx/facet_search_spec.rb +133 -0
  304. data/spec/thinking_sphinx/hooks/guard_presence_spec.rb +30 -0
  305. data/spec/thinking_sphinx/index_set_spec.rb +132 -0
  306. data/spec/thinking_sphinx/index_spec.rb +140 -0
  307. data/spec/thinking_sphinx/interfaces/daemon_spec.rb +60 -0
  308. data/spec/thinking_sphinx/interfaces/real_time_spec.rb +109 -0
  309. data/spec/thinking_sphinx/interfaces/sql_spec.rb +122 -0
  310. data/spec/thinking_sphinx/masks/pagination_mask_spec.rb +123 -0
  311. data/spec/thinking_sphinx/masks/scopes_mask_spec.rb +139 -0
  312. data/spec/thinking_sphinx/middlewares/active_record_translator_spec.rb +180 -0
  313. data/spec/thinking_sphinx/middlewares/geographer_spec.rb +102 -0
  314. data/spec/thinking_sphinx/middlewares/glazier_spec.rb +65 -0
  315. data/spec/thinking_sphinx/middlewares/inquirer_spec.rb +72 -0
  316. data/spec/thinking_sphinx/middlewares/sphinxql_spec.rb +401 -0
  317. data/spec/thinking_sphinx/middlewares/stale_id_checker_spec.rb +50 -0
  318. data/spec/thinking_sphinx/middlewares/stale_id_filter_spec.rb +113 -0
  319. data/spec/thinking_sphinx/middlewares/valid_options_spec.rb +51 -0
  320. data/spec/thinking_sphinx/panes/attributes_pane_spec.rb +23 -0
  321. data/spec/thinking_sphinx/panes/distance_pane_spec.rb +43 -0
  322. data/spec/thinking_sphinx/panes/excerpts_pane_spec.rb +53 -0
  323. data/spec/thinking_sphinx/panes/weight_pane_spec.rb +22 -0
  324. data/spec/thinking_sphinx/rake_interface_spec.rb +39 -0
  325. data/spec/thinking_sphinx/real_time/attribute_spec.rb +64 -0
  326. data/spec/thinking_sphinx/real_time/callbacks/real_time_callbacks_spec.rb +238 -0
  327. data/spec/thinking_sphinx/real_time/field_spec.rb +69 -0
  328. data/spec/thinking_sphinx/real_time/index_spec.rb +230 -0
  329. data/spec/thinking_sphinx/real_time/interpreter_spec.rb +203 -0
  330. data/spec/thinking_sphinx/real_time/transcribe_instance_spec.rb +35 -0
  331. data/spec/thinking_sphinx/real_time/transcriber_spec.rb +109 -0
  332. data/spec/thinking_sphinx/real_time/translator_spec.rb +17 -0
  333. data/spec/thinking_sphinx/scopes_spec.rb +51 -0
  334. data/spec/thinking_sphinx/search/glaze_spec.rb +79 -0
  335. data/spec/thinking_sphinx/search/query_spec.rb +87 -0
  336. data/spec/thinking_sphinx/search_spec.rb +214 -0
  337. data/spec/thinking_sphinx/wildcard_spec.rb +53 -0
  338. data/spec/thinking_sphinx_spec.rb +44 -0
  339. data/thinking-sphinx.gemspec +42 -0
  340. metadata +656 -243
  341. data/VERSION.yml +0 -5
  342. data/features/alternate_primary_key.feature +0 -27
  343. data/features/attribute_transformation.feature +0 -22
  344. data/features/attribute_updates.feature +0 -33
  345. data/features/datetime_deltas.feature +0 -66
  346. data/features/delayed_delta_indexing.feature +0 -37
  347. data/features/deleting_instances.feature +0 -64
  348. data/features/direct_attributes.feature +0 -11
  349. data/features/excerpts.feature +0 -13
  350. data/features/extensible_delta_indexing.feature +0 -9
  351. data/features/facets.feature +0 -76
  352. data/features/facets_across_model.feature +0 -29
  353. data/features/handling_edits.feature +0 -92
  354. data/features/retry_stale_indexes.feature +0 -24
  355. data/features/searching_across_models.feature +0 -20
  356. data/features/searching_by_model.feature +0 -175
  357. data/features/searching_with_find_arguments.feature +0 -56
  358. data/features/sphinx_detection.feature +0 -25
  359. data/features/sphinx_scopes.feature +0 -35
  360. data/features/step_definitions/alpha_steps.rb +0 -3
  361. data/features/step_definitions/beta_steps.rb +0 -7
  362. data/features/step_definitions/common_steps.rb +0 -178
  363. data/features/step_definitions/datetime_delta_steps.rb +0 -15
  364. data/features/step_definitions/delayed_delta_indexing_steps.rb +0 -7
  365. data/features/step_definitions/extensible_delta_indexing_steps.rb +0 -7
  366. data/features/step_definitions/facet_steps.rb +0 -92
  367. data/features/step_definitions/find_arguments_steps.rb +0 -36
  368. data/features/step_definitions/gamma_steps.rb +0 -15
  369. data/features/step_definitions/scope_steps.rb +0 -11
  370. data/features/step_definitions/search_steps.rb +0 -89
  371. data/features/step_definitions/sphinx_steps.rb +0 -31
  372. data/features/sti_searching.feature +0 -14
  373. data/features/support/database.example.yml +0 -3
  374. data/features/support/database.yml +0 -5
  375. data/features/support/db/active_record.rb +0 -40
  376. data/features/support/db/database.yml +0 -5
  377. data/features/support/db/fixtures/alphas.rb +0 -10
  378. data/features/support/db/fixtures/authors.rb +0 -1
  379. data/features/support/db/fixtures/betas.rb +0 -10
  380. data/features/support/db/fixtures/boxes.rb +0 -9
  381. data/features/support/db/fixtures/categories.rb +0 -1
  382. data/features/support/db/fixtures/cats.rb +0 -3
  383. data/features/support/db/fixtures/comments.rb +0 -24
  384. data/features/support/db/fixtures/delayed_betas.rb +0 -10
  385. data/features/support/db/fixtures/developers.rb +0 -29
  386. data/features/support/db/fixtures/dogs.rb +0 -3
  387. data/features/support/db/fixtures/extensible_betas.rb +0 -10
  388. data/features/support/db/fixtures/gammas.rb +0 -10
  389. data/features/support/db/fixtures/people.rb +0 -1001
  390. data/features/support/db/fixtures/posts.rb +0 -6
  391. data/features/support/db/fixtures/robots.rb +0 -14
  392. data/features/support/db/fixtures/tags.rb +0 -27
  393. data/features/support/db/fixtures/thetas.rb +0 -10
  394. data/features/support/db/migrations/create_alphas.rb +0 -7
  395. data/features/support/db/migrations/create_animals.rb +0 -5
  396. data/features/support/db/migrations/create_authors.rb +0 -3
  397. data/features/support/db/migrations/create_authors_posts.rb +0 -6
  398. data/features/support/db/migrations/create_betas.rb +0 -5
  399. data/features/support/db/migrations/create_boxes.rb +0 -5
  400. data/features/support/db/migrations/create_categories.rb +0 -3
  401. data/features/support/db/migrations/create_comments.rb +0 -10
  402. data/features/support/db/migrations/create_delayed_betas.rb +0 -17
  403. data/features/support/db/migrations/create_developers.rb +0 -9
  404. data/features/support/db/migrations/create_extensible_betas.rb +0 -5
  405. data/features/support/db/migrations/create_gammas.rb +0 -3
  406. data/features/support/db/migrations/create_people.rb +0 -13
  407. data/features/support/db/migrations/create_posts.rb +0 -5
  408. data/features/support/db/migrations/create_robots.rb +0 -4
  409. data/features/support/db/migrations/create_taggings.rb +0 -5
  410. data/features/support/db/migrations/create_tags.rb +0 -4
  411. data/features/support/db/migrations/create_thetas.rb +0 -5
  412. data/features/support/db/mysql.rb +0 -3
  413. data/features/support/db/postgresql.rb +0 -3
  414. data/features/support/env.rb +0 -18
  415. data/features/support/lib/generic_delta_handler.rb +0 -8
  416. data/features/support/models/alpha.rb +0 -10
  417. data/features/support/models/animal.rb +0 -5
  418. data/features/support/models/author.rb +0 -3
  419. data/features/support/models/beta.rb +0 -8
  420. data/features/support/models/box.rb +0 -8
  421. data/features/support/models/cat.rb +0 -3
  422. data/features/support/models/category.rb +0 -4
  423. data/features/support/models/comment.rb +0 -10
  424. data/features/support/models/delayed_beta.rb +0 -7
  425. data/features/support/models/developer.rb +0 -16
  426. data/features/support/models/dog.rb +0 -3
  427. data/features/support/models/extensible_beta.rb +0 -9
  428. data/features/support/models/gamma.rb +0 -5
  429. data/features/support/models/person.rb +0 -23
  430. data/features/support/models/post.rb +0 -20
  431. data/features/support/models/robot.rb +0 -12
  432. data/features/support/models/tag.rb +0 -3
  433. data/features/support/models/theta.rb +0 -7
  434. data/features/support/post_database.rb +0 -43
  435. data/lib/cucumber/thinking_sphinx/internal_world.rb +0 -125
  436. data/lib/cucumber/thinking_sphinx/sql_logger.rb +0 -20
  437. data/lib/thinking_sphinx/active_record/attribute_updates.rb +0 -48
  438. data/lib/thinking_sphinx/active_record/delta.rb +0 -87
  439. data/lib/thinking_sphinx/active_record/has_many_association.rb +0 -28
  440. data/lib/thinking_sphinx/active_record/scopes.rb +0 -39
  441. data/lib/thinking_sphinx/adapters/abstract_adapter.rb +0 -42
  442. data/lib/thinking_sphinx/adapters/mysql_adapter.rb +0 -54
  443. data/lib/thinking_sphinx/adapters/postgresql_adapter.rb +0 -143
  444. data/lib/thinking_sphinx/association.rb +0 -164
  445. data/lib/thinking_sphinx/attribute.rb +0 -341
  446. data/lib/thinking_sphinx/class_facet.rb +0 -15
  447. data/lib/thinking_sphinx/core/array.rb +0 -7
  448. data/lib/thinking_sphinx/core/string.rb +0 -15
  449. data/lib/thinking_sphinx/deltas/datetime_delta.rb +0 -50
  450. data/lib/thinking_sphinx/deltas/delayed_delta/delta_job.rb +0 -24
  451. data/lib/thinking_sphinx/deltas/delayed_delta/flag_as_deleted_job.rb +0 -27
  452. data/lib/thinking_sphinx/deltas/delayed_delta/job.rb +0 -26
  453. data/lib/thinking_sphinx/deltas/delayed_delta.rb +0 -30
  454. data/lib/thinking_sphinx/deploy/capistrano.rb +0 -100
  455. data/lib/thinking_sphinx/field.rb +0 -82
  456. data/lib/thinking_sphinx/index/builder.rb +0 -286
  457. data/lib/thinking_sphinx/index/faux_column.rb +0 -110
  458. data/lib/thinking_sphinx/property.rb +0 -162
  459. data/lib/thinking_sphinx/rails_additions.rb +0 -150
  460. data/lib/thinking_sphinx/search_methods.rb +0 -421
  461. data/lib/thinking_sphinx/source/internal_properties.rb +0 -46
  462. data/lib/thinking_sphinx/source/sql.rb +0 -128
  463. data/lib/thinking_sphinx/source.rb +0 -150
  464. data/rails/init.rb +0 -14
  465. data/spec/lib/thinking_sphinx/active_record/delta_spec.rb +0 -130
  466. data/spec/lib/thinking_sphinx/active_record/has_many_association_spec.rb +0 -49
  467. data/spec/lib/thinking_sphinx/active_record/scopes_spec.rb +0 -96
  468. data/spec/lib/thinking_sphinx/active_record_spec.rb +0 -353
  469. data/spec/lib/thinking_sphinx/association_spec.rb +0 -239
  470. data/spec/lib/thinking_sphinx/attribute_spec.rb +0 -507
  471. data/spec/lib/thinking_sphinx/configuration_spec.rb +0 -268
  472. data/spec/lib/thinking_sphinx/core/array_spec.rb +0 -9
  473. data/spec/lib/thinking_sphinx/core/string_spec.rb +0 -9
  474. data/spec/lib/thinking_sphinx/deltas/job_spec.rb +0 -32
  475. data/spec/lib/thinking_sphinx/excerpter_spec.rb +0 -57
  476. data/spec/lib/thinking_sphinx/facet_search_spec.rb +0 -176
  477. data/spec/lib/thinking_sphinx/facet_spec.rb +0 -333
  478. data/spec/lib/thinking_sphinx/field_spec.rb +0 -154
  479. data/spec/lib/thinking_sphinx/index/builder_spec.rb +0 -455
  480. data/spec/lib/thinking_sphinx/index/faux_column_spec.rb +0 -30
  481. data/spec/lib/thinking_sphinx/index_spec.rb +0 -45
  482. data/spec/lib/thinking_sphinx/rails_additions_spec.rb +0 -203
  483. data/spec/lib/thinking_sphinx/search_methods_spec.rb +0 -152
  484. data/spec/lib/thinking_sphinx/search_spec.rb +0 -1101
  485. data/spec/lib/thinking_sphinx/source_spec.rb +0 -227
  486. data/spec/lib/thinking_sphinx_spec.rb +0 -162
  487. data/tasks/distribution.rb +0 -53
  488. data/tasks/rails.rake +0 -1
  489. data/tasks/testing.rb +0 -72
  490. data/vendor/after_commit/LICENSE +0 -20
  491. data/vendor/after_commit/README +0 -16
  492. data/vendor/after_commit/Rakefile +0 -22
  493. data/vendor/after_commit/init.rb +0 -8
  494. data/vendor/after_commit/lib/after_commit/active_record.rb +0 -114
  495. data/vendor/after_commit/lib/after_commit/connection_adapters.rb +0 -103
  496. data/vendor/after_commit/lib/after_commit.rb +0 -45
  497. data/vendor/after_commit/test/after_commit_test.rb +0 -53
  498. data/vendor/delayed_job/lib/delayed/job.rb +0 -251
  499. data/vendor/delayed_job/lib/delayed/message_sending.rb +0 -7
  500. data/vendor/delayed_job/lib/delayed/performable_method.rb +0 -55
  501. data/vendor/delayed_job/lib/delayed/worker.rb +0 -54
  502. data/vendor/riddle/lib/riddle/client/filter.rb +0 -53
  503. data/vendor/riddle/lib/riddle/client/message.rb +0 -66
  504. data/vendor/riddle/lib/riddle/client/response.rb +0 -84
  505. data/vendor/riddle/lib/riddle/client.rb +0 -635
  506. data/vendor/riddle/lib/riddle/configuration/distributed_index.rb +0 -48
  507. data/vendor/riddle/lib/riddle/configuration/index.rb +0 -142
  508. data/vendor/riddle/lib/riddle/configuration/indexer.rb +0 -19
  509. data/vendor/riddle/lib/riddle/configuration/remote_index.rb +0 -17
  510. data/vendor/riddle/lib/riddle/configuration/searchd.rb +0 -25
  511. data/vendor/riddle/lib/riddle/configuration/section.rb +0 -43
  512. data/vendor/riddle/lib/riddle/configuration/source.rb +0 -23
  513. data/vendor/riddle/lib/riddle/configuration/sql_source.rb +0 -34
  514. data/vendor/riddle/lib/riddle/configuration/xml_source.rb +0 -28
  515. data/vendor/riddle/lib/riddle/configuration.rb +0 -33
  516. data/vendor/riddle/lib/riddle/controller.rb +0 -53
  517. data/vendor/riddle/lib/riddle.rb +0 -30
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::Processor
4
+ # @param instance [ActiveRecord::Base] an ActiveRecord object
5
+ # @param model [Class] the ActiveRecord model of the instance
6
+ # @param id [Integer] the instance indices primary key (might be different from model primary key)
7
+ def initialize(instance: nil, model: nil, id: nil)
8
+ raise ArgumentError if instance.nil? && (model.nil? || id.nil?)
9
+
10
+ @instance = instance
11
+ @model = model || instance.class
12
+ @id = id
13
+ end
14
+
15
+ def delete
16
+ return if instance&.new_record?
17
+
18
+ indices.each { |index| perform_deletion(index) }
19
+ end
20
+
21
+ # Will insert instance into all matching indices
22
+ def upsert
23
+ real_time_indices.each do |index|
24
+ found = loaded_instance(index)
25
+ ThinkingSphinx::RealTime::Transcriber.new(index).copy found if found
26
+ end
27
+ end
28
+
29
+ # Will upsert or delete instance into all matching indices based on index scope
30
+ def sync
31
+ real_time_indices.each do |index|
32
+ found = find_in(index)
33
+
34
+ if found
35
+ ThinkingSphinx::RealTime::Transcriber.new(index).copy found
36
+ else
37
+ ThinkingSphinx::Deletion.perform(index, index_id(index))
38
+ end
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ attr_reader :instance, :model, :id
45
+
46
+ def indices
47
+ ThinkingSphinx::Configuration.instance.index_set_class.new(
48
+ :instances => [instance].compact, :classes => [model]
49
+ ).to_a
50
+ end
51
+
52
+ def find_in(index)
53
+ index.scope.find_by(index.primary_key => index_id(index))
54
+ end
55
+
56
+ def loaded_instance(index)
57
+ instance || find_in(index)
58
+ end
59
+
60
+ def real_time_indices
61
+ indices.select { |index| index.is_a? ThinkingSphinx::RealTime::Index }
62
+ end
63
+
64
+ def perform_deletion(index)
65
+ ThinkingSphinx::Deletion.perform(index, index_id(index))
66
+ end
67
+
68
+ def index_id(index)
69
+ id || instance.public_send(index.primary_key)
70
+ end
71
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ThinkingSphinx::Query
4
+ def self.escape(query)
5
+ Riddle::Query.escape query
6
+ end
7
+
8
+ def self.wildcard(query, pattern = true)
9
+ ThinkingSphinx::Wildcard.call query, pattern
10
+ end
11
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::Railtie < Rails::Railtie
4
+ config.to_prepare do
5
+ ThinkingSphinx::Configuration.reset
6
+ end
7
+
8
+ config.after_initialize do
9
+ require 'thinking_sphinx/active_record'
10
+ end
11
+
12
+ initializer 'thinking_sphinx.initialisation' do
13
+ ActiveSupport.on_load(:active_record) do
14
+ require 'thinking_sphinx/active_record'
15
+ end
16
+
17
+ if zeitwerk?
18
+ ActiveSupport::Dependencies.autoload_paths.delete(
19
+ Rails.root.join("app", "indices").to_s
20
+ )
21
+ end
22
+
23
+ Rails.application.config.eager_load_paths -=
24
+ ThinkingSphinx::Configuration.instance.index_paths
25
+ Rails.application.config.eager_load_paths.freeze
26
+ end
27
+
28
+ rake_tasks do
29
+ load File.expand_path('../tasks.rb', __FILE__)
30
+ end
31
+
32
+ def zeitwerk?
33
+ return true if ActiveSupport::VERSION::MAJOR >= 7
34
+ return false if ActiveSupport::VERSION::MAJOR <= 5
35
+
36
+ Rails.application.config.autoloader == :zeitwerk
37
+ end
38
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::RakeInterface
4
+ DEFAULT_OPTIONS = {:verbose => true}
5
+
6
+ def initialize(options = {})
7
+ @options = DEFAULT_OPTIONS.merge options
8
+ @options[:verbose] = false if @options[:silent]
9
+ end
10
+
11
+ def configure
12
+ ThinkingSphinx::Commander.call :configure, configuration, options
13
+ end
14
+
15
+ def daemon
16
+ @daemon ||= ThinkingSphinx::Interfaces::Daemon.new configuration, options
17
+ end
18
+
19
+ def rt
20
+ @rt ||= ThinkingSphinx::Interfaces::RealTime.new configuration, options
21
+ end
22
+
23
+ def sql
24
+ @sql ||= ThinkingSphinx::Interfaces::SQL.new configuration, options
25
+ end
26
+
27
+ private
28
+
29
+ attr_reader :options
30
+
31
+ def configuration
32
+ ThinkingSphinx::Configuration.instance
33
+ end
34
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::RealTime::Attribute < ThinkingSphinx::RealTime::Property
4
+ def multi?
5
+ @options[:multi]
6
+ end
7
+
8
+ def type
9
+ @options[:type]
10
+ end
11
+
12
+ def translate(object)
13
+ output = super || default_value
14
+
15
+ json? ? output.to_json : output
16
+ end
17
+
18
+ private
19
+
20
+ def default_value
21
+ type == :string ? '' : 0
22
+ end
23
+
24
+ def json?
25
+ type == :json
26
+ end
27
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::RealTime::Callbacks::RealTimeCallbacks
4
+ def initialize(reference, path = [], &block)
5
+ @reference, @path, @block = reference, path, block
6
+ end
7
+
8
+ def after_commit(instance)
9
+ persist_changes instance
10
+ end
11
+
12
+ def after_save(instance)
13
+ persist_changes instance
14
+ end
15
+
16
+ private
17
+
18
+ attr_reader :reference, :path, :block
19
+
20
+ def callbacks_enabled?
21
+ setting = configuration.settings['real_time_callbacks']
22
+ setting.nil? || setting
23
+ end
24
+
25
+ def configuration
26
+ ThinkingSphinx::Configuration.instance
27
+ end
28
+
29
+ def indices
30
+ configuration.indices_for_references reference
31
+ end
32
+
33
+ def objects_for(instance)
34
+ if block
35
+ results = block.call instance
36
+ else
37
+ results = path.inject(instance) { |object, method| object.send method }
38
+ end
39
+
40
+ Array results
41
+ end
42
+
43
+ def persist_changes(instance)
44
+ return unless real_time_indices? && callbacks_enabled?
45
+
46
+ real_time_indices.each do |index|
47
+ objects_for(instance).each do |object|
48
+ ThinkingSphinx::RealTime::Transcriber.new(index).copy object
49
+ end
50
+ end
51
+ end
52
+
53
+ def real_time_indices?
54
+ real_time_indices.any?
55
+ end
56
+
57
+ def real_time_indices
58
+ indices.select { |index| index.is_a? ThinkingSphinx::RealTime::Index }
59
+ end
60
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::RealTime::Field < ThinkingSphinx::RealTime::Property
4
+ include ThinkingSphinx::Core::Field
5
+
6
+ def translate(object)
7
+ Array(super || '').join(' ')
8
+ end
9
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::RealTime::Index::Template
4
+ attr_reader :index
5
+
6
+ def initialize(index)
7
+ @index = index
8
+ end
9
+
10
+ def apply
11
+ add_field class_column, :sphinx_internal_class_name
12
+
13
+ add_attribute primary_key, :sphinx_internal_id, :bigint
14
+ add_attribute class_column, :sphinx_internal_class, :string, :facet => true
15
+ add_attribute 0, :sphinx_deleted, :integer
16
+
17
+ if tidying?
18
+ add_attribute -> (_) { Time.current.to_i }, :sphinx_updated_at, :timestamp
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def add_attribute(column, name, type, options = {})
25
+ index.add_attribute ThinkingSphinx::RealTime::Attribute.new(
26
+ ThinkingSphinx::ActiveRecord::Column.new(*column),
27
+ options.merge(:as => name, :type => type)
28
+ )
29
+ end
30
+
31
+ def add_field(column, name)
32
+ index.add_field ThinkingSphinx::RealTime::Field.new(
33
+ ThinkingSphinx::ActiveRecord::Column.new(*column), :as => name
34
+ )
35
+ end
36
+
37
+ def class_column
38
+ [:class, :name]
39
+ end
40
+
41
+ def config
42
+ ThinkingSphinx::Configuration.instance
43
+ end
44
+
45
+ def primary_key
46
+ index.primary_key.to_sym
47
+ end
48
+
49
+ def tidying?
50
+ config.settings["real_time_tidy"]
51
+ end
52
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::RealTime::Index < Riddle::Configuration::RealtimeIndex
4
+ include ThinkingSphinx::Core::Index
5
+
6
+ attr_writer :fields, :attributes, :conditions, :scope
7
+
8
+ def initialize(reference, options = {})
9
+ @fields = []
10
+ @attributes = []
11
+ @conditions = []
12
+
13
+ super reference, options
14
+
15
+ Template.new(self).apply
16
+ end
17
+
18
+ def add_attribute(attribute)
19
+ @attributes.delete_if { |existing| existing.name == attribute.name }
20
+
21
+ @attributes << attribute
22
+ end
23
+
24
+ def add_field(field)
25
+ @fields.delete_if { |existing| existing.name == field.name }
26
+
27
+ @fields << field
28
+ end
29
+
30
+ def attributes
31
+ interpret_definition!
32
+
33
+ @attributes
34
+ end
35
+
36
+ def conditions
37
+ interpret_definition!
38
+
39
+ @conditions
40
+ end
41
+
42
+ def facets
43
+ properties.select(&:facet?)
44
+ end
45
+
46
+ def fields
47
+ interpret_definition!
48
+
49
+ @fields
50
+ end
51
+
52
+ def scope
53
+ @scope.nil? ? model : @scope.call
54
+ end
55
+
56
+ def unique_attribute_names
57
+ attributes.collect(&:name)
58
+ end
59
+
60
+ private
61
+
62
+ def append_unique_attribute(collection, attribute)
63
+ collection << attribute.name unless collection.include?(attribute.name)
64
+ end
65
+
66
+ def collection_for(attribute)
67
+ case attribute.type
68
+ when :integer, :boolean, :timestamp
69
+ attribute.multi? ? @rt_attr_multi : @rt_attr_uint
70
+ when :string
71
+ @rt_attr_string
72
+ when :float
73
+ @rt_attr_float
74
+ when :bigint
75
+ attribute.multi? ? @rt_attr_multi_64 : @rt_attr_bigint
76
+ when :json
77
+ @rt_attr_json
78
+ else
79
+ raise "Unknown attribute type '#{attribute.type}'"
80
+ end
81
+ end
82
+
83
+ def interpreter
84
+ ThinkingSphinx::RealTime::Interpreter
85
+ end
86
+
87
+ def pre_render
88
+ super
89
+
90
+ @rt_field = fields.collect &:name
91
+
92
+ attributes.each do |attribute|
93
+ append_unique_attribute collection_for(attribute), attribute
94
+ end
95
+ end
96
+
97
+ def properties
98
+ fields + attributes
99
+ end
100
+ end
101
+
102
+ require 'thinking_sphinx/real_time/index/template'
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::RealTime::Interpreter <
4
+ ::ThinkingSphinx::Core::Interpreter
5
+
6
+ def has(*columns)
7
+ options = columns.extract_options!
8
+
9
+ columns.collect { |column|
10
+ ::ThinkingSphinx::RealTime::Attribute.new column, options
11
+ }.each { |attribute| @index.add_attribute attribute }
12
+ end
13
+
14
+ def indexes(*columns)
15
+ options = columns.extract_options!
16
+
17
+ columns.collect { |column|
18
+ ::ThinkingSphinx::RealTime::Field.new column, options
19
+ }.each { |field| @index.add_field field }
20
+
21
+ append_sortable_attributes columns, options if options[:sortable]
22
+ end
23
+
24
+ def scope(&block)
25
+ @index.scope = block
26
+ end
27
+
28
+ def set_property(properties)
29
+ properties.each do |key, value|
30
+ @index.send("#{key}=", value) if @index.class.settings.include?(key)
31
+ @index.options[key] = value if search_option?(key)
32
+ end
33
+ end
34
+
35
+ def where(condition)
36
+ @index.conditions << condition
37
+ end
38
+
39
+ private
40
+
41
+ def append_sortable_attributes(columns, options)
42
+ options = options.except(:sortable).merge(:type => :string)
43
+
44
+ columns.collect { |column|
45
+ aliased_name = options[:as]
46
+ aliased_name ||= column.__name.to_sym if column.respond_to?(:__name)
47
+ aliased_name ||= column
48
+
49
+ options[:as] = "#{aliased_name}_sort".to_sym
50
+
51
+ ::ThinkingSphinx::RealTime::Attribute.new column, options
52
+ }.each { |attribute| @index.add_attribute attribute }
53
+ end
54
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::RealTime::Populator
4
+ def self.populate(index)
5
+ new(index).populate
6
+ end
7
+
8
+ def initialize(index)
9
+ @index = index
10
+ @started_at = Time.current
11
+ end
12
+
13
+ def populate
14
+ instrument 'start_populating'
15
+
16
+ scope.find_in_batches(:batch_size => batch_size) do |instances|
17
+ transcriber.copy *instances
18
+ instrument 'populated', :instances => instances
19
+ end
20
+
21
+ transcriber.clear_before(started_at) if configuration.settings["real_time_tidy"]
22
+
23
+ instrument 'finish_populating'
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :index, :started_at
29
+
30
+ delegate :controller, :batch_size, :to => :configuration
31
+ delegate :scope, :to => :index
32
+
33
+ def configuration
34
+ ThinkingSphinx::Configuration.instance
35
+ end
36
+
37
+ def instrument(message, options = {})
38
+ ActiveSupport::Notifications.instrument(
39
+ "#{message}.thinking_sphinx.real_time", options.merge(:index => index)
40
+ )
41
+ end
42
+
43
+ def transcriber
44
+ @transcriber ||= ThinkingSphinx::RealTime::Transcriber.new index
45
+ end
46
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::RealTime::Processor
4
+ def self.call(indices, &block)
5
+ new(indices).call(&block)
6
+ end
7
+
8
+ def initialize(indices)
9
+ @indices = indices
10
+ end
11
+
12
+ def call(&block)
13
+ subscribe_to_progress
14
+
15
+ indices.each do |index|
16
+ ThinkingSphinx::RealTime.populator.populate index
17
+
18
+ block.call
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :indices
25
+
26
+ def command
27
+ ThinkingSphinx::Commander.call(
28
+ command, configuration, options, stream
29
+ )
30
+ end
31
+
32
+ def subscribe_to_progress
33
+ ThinkingSphinx::Subscribers::PopulatorSubscriber.
34
+ attach_to 'thinking_sphinx.real_time'
35
+ end
36
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::RealTime::Property
4
+ include ThinkingSphinx::Core::Property
5
+
6
+ attr_reader :column, :options
7
+
8
+ def initialize(column, options = {})
9
+ @options = options
10
+ @column = column.respond_to?(:__name) ? column :
11
+ ThinkingSphinx::ActiveRecord::Column.new(column)
12
+ end
13
+
14
+ def name
15
+ (@options[:as] || @column.__name).to_s
16
+ end
17
+
18
+ def translate(object)
19
+ ThinkingSphinx::RealTime::Translator.call(object, @column)
20
+ end
21
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::RealTime::TranscribeInstance
4
+ def self.call(instance, index, properties)
5
+ new(instance, index, properties).call
6
+ end
7
+
8
+ def initialize(instance, index, properties)
9
+ @instance, @index, @properties = instance, index, properties
10
+ end
11
+
12
+ def call
13
+ properties.each_with_object([document_id]) do |property, instance_values|
14
+ begin
15
+ instance_values << property.translate(instance)
16
+ rescue StandardError => error
17
+ raise_wrapper error, property
18
+ end
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :instance, :index, :properties
25
+
26
+ def document_id
27
+ index.document_id_for_key instance.public_send(index.primary_key)
28
+ end
29
+
30
+ def raise_wrapper(error, property)
31
+ wrapper = ThinkingSphinx::TranscriptionError.new
32
+ wrapper.inner_exception = error
33
+ wrapper.instance = instance
34
+ wrapper.property = property
35
+
36
+ raise wrapper
37
+ end
38
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ThinkingSphinx::RealTime::Transcriber
4
+ def initialize(index)
5
+ @index = index
6
+ end
7
+
8
+ def clear_before(time)
9
+ execute <<~SQL.strip
10
+ DELETE FROM #{@index.name} WHERE sphinx_updated_at < #{time.to_i}
11
+ SQL
12
+ end
13
+
14
+ def copy(*instances)
15
+ items = instances.select { |instance|
16
+ instance.persisted? && copy?(instance)
17
+ }
18
+ return unless items.present?
19
+
20
+ delete_existing items
21
+ insert_replacements items
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :index
27
+
28
+ def columns
29
+ @columns ||= properties.each_with_object(['id']) do |property, columns|
30
+ columns << property.name
31
+ end
32
+ end
33
+
34
+ def copy?(instance)
35
+ index.conditions.empty? || index.conditions.all? { |condition|
36
+ case condition
37
+ when Symbol
38
+ instance.send(condition)
39
+ when Proc
40
+ condition.call instance
41
+ else
42
+ "Unexpected condition: #{condition}. Expecting Symbol or Proc."
43
+ end
44
+ }
45
+ end
46
+
47
+ def delete_existing(instances)
48
+ ids = instances.collect(&index.primary_key.to_sym)
49
+
50
+ execute <<~SQL.strip
51
+ DELETE FROM #{@index.name} WHERE sphinx_internal_id IN (#{ids.join(', ')})
52
+ SQL
53
+ end
54
+
55
+ def execute(sphinxql)
56
+ ThinkingSphinx::Logger.log :query, sphinxql do
57
+ ThinkingSphinx::Connection.take do |connection|
58
+ connection.execute sphinxql
59
+ end
60
+ end
61
+ end
62
+
63
+ def insert_replacements(instances)
64
+ insert = Riddle::Query::Insert.new index.name, columns, values(instances)
65
+ execute insert.replace!.to_sql
66
+ end
67
+
68
+ def instrument(message, options = {})
69
+ ActiveSupport::Notifications.instrument(
70
+ "#{message}.thinking_sphinx.real_time", options.merge(:index => index)
71
+ )
72
+ end
73
+
74
+ def properties
75
+ @properties ||= index.fields + index.attributes
76
+ end
77
+
78
+ def values(instances)
79
+ instances.each_with_object([]) do |instance, array|
80
+ begin
81
+ array << ThinkingSphinx::RealTime::TranscribeInstance.call(
82
+ instance, index, properties
83
+ )
84
+ rescue ThinkingSphinx::TranscriptionError => error
85
+ instrument 'error', :error => error
86
+ end
87
+ end
88
+ end
89
+ end