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,329 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe ThinkingSphinx::ActiveRecord::Interpreter do
6
+ let(:instance) {
7
+ ThinkingSphinx::ActiveRecord::Interpreter.new index, block
8
+ }
9
+ let(:model) { double('model') }
10
+ let(:index) { double('index', :append_source => source, :options => {}) }
11
+ let(:source) {
12
+ Struct.new(:attributes, :fields, :associations, :groupings, :conditions).
13
+ new([], [], [], [], [])
14
+ }
15
+ let(:block) { Proc.new { } }
16
+
17
+ before :each do
18
+ allow(ThinkingSphinx::ActiveRecord::SQLSource).to receive_messages(
19
+ :new => source
20
+ )
21
+
22
+ allow(source).to receive_messages(
23
+ :model => model, :add_attribute => nil, :add_field => nil
24
+ )
25
+ end
26
+
27
+ describe '.translate!' do
28
+ let(:instance) { double('interpreter', :translate! => true) }
29
+
30
+ it "creates a new interpreter instance with the given block and index" do
31
+ expect(ThinkingSphinx::ActiveRecord::Interpreter).to receive(:new).
32
+ with(index, block).and_return(instance)
33
+
34
+ ThinkingSphinx::ActiveRecord::Interpreter.translate! index, block
35
+ end
36
+
37
+ it "calls translate! on the instance" do
38
+ allow(ThinkingSphinx::ActiveRecord::Interpreter).to receive_messages(:new => instance)
39
+ expect(instance).to receive(:translate!)
40
+
41
+ ThinkingSphinx::ActiveRecord::Interpreter.translate! index, block
42
+ end
43
+ end
44
+
45
+ describe '#group_by' do
46
+ it "adds a source to the index" do
47
+ expect(index).to receive(:append_source).and_return(source)
48
+
49
+ instance.group_by 'lat'
50
+ end
51
+
52
+ it "only adds a single source for the given context" do
53
+ expect(index).to receive(:append_source).once.and_return(source)
54
+
55
+ instance.group_by 'lat'
56
+ instance.group_by 'lng'
57
+ end
58
+
59
+ it "appends a new grouping statement to the source" do
60
+ instance.group_by 'lat'
61
+
62
+ expect(source.groupings).to include('lat')
63
+ end
64
+ end
65
+
66
+ describe '#has' do
67
+ let(:column) { double('column') }
68
+ let(:attribute) { double('attribute') }
69
+
70
+ before :each do
71
+ allow(ThinkingSphinx::ActiveRecord::Attribute).to receive_messages :new => attribute
72
+ end
73
+
74
+ it "adds a source to the index" do
75
+ expect(index).to receive(:append_source).and_return(source)
76
+
77
+ instance.has column
78
+ end
79
+
80
+ it "only adds a single source for the given context" do
81
+ expect(index).to receive(:append_source).once.and_return(source)
82
+
83
+ instance.has column
84
+ instance.has column
85
+ end
86
+
87
+ it "creates a new attribute with the provided column" do
88
+ expect(ThinkingSphinx::ActiveRecord::Attribute).to receive(:new).
89
+ with(model, column, {}).and_return(attribute)
90
+
91
+ instance.has column
92
+ end
93
+
94
+ it "passes through options to the attribute" do
95
+ expect(ThinkingSphinx::ActiveRecord::Attribute).to receive(:new).
96
+ with(model, column, { :as => :other_name }).and_return(attribute)
97
+
98
+ instance.has column, :as => :other_name
99
+ end
100
+
101
+ it "adds an attribute to the source" do
102
+ expect(source).to receive(:add_attribute).with(attribute)
103
+
104
+ instance.has column
105
+ end
106
+
107
+ it "adds multiple attributes when passed multiple columns" do
108
+ expect(source).to receive(:add_attribute).with(attribute).twice
109
+
110
+ instance.has column, column
111
+ end
112
+ end
113
+
114
+ describe '#indexes' do
115
+ let(:column) { double('column') }
116
+ let(:field) { double('field') }
117
+
118
+ before :each do
119
+ allow(ThinkingSphinx::ActiveRecord::Field).to receive_messages :new => field
120
+ end
121
+
122
+ it "adds a source to the index" do
123
+ expect(index).to receive(:append_source).and_return(source)
124
+
125
+ instance.indexes column
126
+ end
127
+
128
+ it "only adds a single source for the given context" do
129
+ expect(index).to receive(:append_source).once.and_return(source)
130
+
131
+ instance.indexes column
132
+ instance.indexes column
133
+ end
134
+
135
+ it "creates a new field with the provided column" do
136
+ expect(ThinkingSphinx::ActiveRecord::Field).to receive(:new).
137
+ with(model, column, {}).and_return(field)
138
+
139
+ instance.indexes column
140
+ end
141
+
142
+ it "passes through options to the field" do
143
+ expect(ThinkingSphinx::ActiveRecord::Field).to receive(:new).
144
+ with(model, column, { :as => :other_name }).and_return(field)
145
+
146
+ instance.indexes column, :as => :other_name
147
+ end
148
+
149
+ it "adds a field to the source" do
150
+ expect(source).to receive(:add_field).with(field)
151
+
152
+ instance.indexes column
153
+ end
154
+
155
+ it "adds multiple fields when passed multiple columns" do
156
+ expect(source).to receive(:add_field).with(field).twice
157
+
158
+ instance.indexes column, column
159
+ end
160
+ end
161
+
162
+ describe '#join' do
163
+ let(:column) { double('column') }
164
+ let(:association) { double('association') }
165
+
166
+ before :each do
167
+ allow(ThinkingSphinx::ActiveRecord::Association).to receive_messages :new => association
168
+ end
169
+
170
+ it "adds a source to the index" do
171
+ expect(index).to receive(:append_source).and_return(source)
172
+
173
+ instance.join column
174
+ end
175
+
176
+ it "only adds a single source for the given context" do
177
+ expect(index).to receive(:append_source).once.and_return(source)
178
+
179
+ instance.join column
180
+ instance.join column
181
+ end
182
+
183
+ it "creates a new association with the provided column" do
184
+ expect(ThinkingSphinx::ActiveRecord::Association).to receive(:new).
185
+ with(column).and_return(association)
186
+
187
+ instance.join column
188
+ end
189
+
190
+ it "adds an association to the source" do
191
+ instance.join column
192
+
193
+ expect(source.associations).to include(association)
194
+ end
195
+
196
+ it "adds multiple fields when passed multiple columns" do
197
+ instance.join column, column
198
+
199
+ expect(source.associations.select { |saved_assoc|
200
+ saved_assoc == association
201
+ }.length).to eq(2)
202
+ end
203
+ end
204
+
205
+ describe '#method_missing' do
206
+ let(:column) { double('column') }
207
+
208
+ before :each do
209
+ allow(ThinkingSphinx::ActiveRecord::Column).to receive_messages(:new => column)
210
+ end
211
+
212
+ it "returns a new column for the given method" do
213
+ expect(instance.id).to eq(column)
214
+ end
215
+
216
+ it "should initialise the column with the method name and arguments" do
217
+ expect(ThinkingSphinx::ActiveRecord::Column).to receive(:new).
218
+ with(:users, :posts, :subject).and_return(column)
219
+
220
+ instance.users(:posts, :subject)
221
+ end
222
+ end
223
+
224
+ describe '#set_database' do
225
+ before :each do
226
+ allow(source).to receive_messages :set_database_settings => true
227
+
228
+ stub_const 'ActiveRecord::Base',
229
+ double(:configurations => {'other' => {'baz' => 'qux'}})
230
+ end
231
+
232
+ it "sends through a hash if provided" do
233
+ expect(source).to receive(:set_database_settings).with({ :foo => :bar })
234
+
235
+ instance.set_database :foo => :bar
236
+ end
237
+
238
+ it "finds the environment settings if given a string key" do
239
+ expect(source).to receive(:set_database_settings).with({ :baz => 'qux' })
240
+
241
+ instance.set_database 'other'
242
+ end
243
+
244
+ it "finds the environment settings if given a symbol key" do
245
+ expect(source).to receive(:set_database_settings).with({ :baz => 'qux' })
246
+
247
+ instance.set_database :other
248
+ end
249
+ end
250
+
251
+ describe '#set_property' do
252
+ before :each do
253
+ allow(index.class).to receive_messages :settings => [:morphology]
254
+ allow(source.class).to receive_messages :settings => [:mysql_ssl_cert]
255
+ end
256
+
257
+ it 'saves other settings as index options' do
258
+ instance.set_property :field_weights => {:name => 10}
259
+
260
+ expect(index.options[:field_weights]).to eq({:name => 10})
261
+ end
262
+
263
+ context 'index settings' do
264
+ it "sets the provided setting" do
265
+ expect(index).to receive(:morphology=).with('stem_en')
266
+
267
+ instance.set_property :morphology => 'stem_en'
268
+ end
269
+ end
270
+
271
+ context 'source settings' do
272
+ before :each do
273
+ allow(source).to receive_messages :mysql_ssl_cert= => true
274
+ end
275
+
276
+ it "adds a source to the index" do
277
+ expect(index).to receive(:append_source).and_return(source)
278
+
279
+ instance.set_property :mysql_ssl_cert => 'private.cert'
280
+ end
281
+
282
+ it "only adds a single source for the given context" do
283
+ expect(index).to receive(:append_source).once.and_return(source)
284
+
285
+ instance.set_property :mysql_ssl_cert => 'private.cert'
286
+ instance.set_property :mysql_ssl_cert => 'private.cert'
287
+ end
288
+
289
+ it "sets the provided setting" do
290
+ expect(source).to receive(:mysql_ssl_cert=).with('private.cert')
291
+
292
+ instance.set_property :mysql_ssl_cert => 'private.cert'
293
+ end
294
+ end
295
+ end
296
+
297
+ describe '#translate!' do
298
+ it "returns the block evaluated within the context of the interpreter" do
299
+ block = Proc.new {
300
+ __id__
301
+ }
302
+
303
+ interpreter = ThinkingSphinx::ActiveRecord::Interpreter.new index, block
304
+ expect(interpreter.translate!).
305
+ to eq(interpreter.__id__)
306
+ end
307
+ end
308
+
309
+ describe '#where' do
310
+ it "adds a source to the index" do
311
+ expect(index).to receive(:append_source).and_return(source)
312
+
313
+ instance.where 'id > 100'
314
+ end
315
+
316
+ it "only adds a single source for the given context" do
317
+ expect(index).to receive(:append_source).once.and_return(source)
318
+
319
+ instance.where 'id > 100'
320
+ instance.where 'id < 150'
321
+ end
322
+
323
+ it "appends a new grouping statement to the source" do
324
+ instance.where 'id > 100'
325
+
326
+ expect(source.conditions).to include('id > 100')
327
+ end
328
+ end
329
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe ThinkingSphinx::ActiveRecord::Polymorpher do
6
+ let(:polymorpher) { ThinkingSphinx::ActiveRecord::Polymorpher.new source,
7
+ column, class_names }
8
+ let(:source) { double 'Source', :model => outer, :fields => [field],
9
+ :attributes => [attribute] }
10
+ let(:column) { double 'Column', :__name => :foo, :__stack => [:a, :b],
11
+ :__path => [:a, :b, :foo] }
12
+ let(:class_names) { %w( Article Animal ) }
13
+ let(:field) { double :rebase => true }
14
+ let(:attribute) { double :rebase => true }
15
+ let(:outer) { double(
16
+ :reflect_on_association => double(:klass => inner)) }
17
+ let(:inner) { double(
18
+ :reflect_on_association => double(:klass => model)) }
19
+ let(:model) { double 'Model', :reflections => {},
20
+ :reflect_on_association => reflection }
21
+ let(:reflection) { double 'Polymorphic Reflection' }
22
+
23
+ describe '#morph!' do
24
+ let(:article_reflection) { double 'Article Reflection' }
25
+ let(:animal_reflection) { double 'Animal Reflection' }
26
+
27
+ before :each do
28
+ allow(ThinkingSphinx::ActiveRecord::FilterReflection).
29
+ to receive(:call).
30
+ and_return(article_reflection, animal_reflection)
31
+
32
+ allow(model).to receive(:reflect_on_association) do |name|
33
+ name == :foo ? reflection : nil
34
+ end
35
+
36
+ if ActiveRecord::Reflection.respond_to?(:add_reflection)
37
+ allow(ActiveRecord::Reflection).to receive :add_reflection
38
+ end
39
+ end
40
+
41
+ it "creates a new reflection for each class" do
42
+ allow(ThinkingSphinx::ActiveRecord::FilterReflection).
43
+ to receive(:call).and_call_original
44
+
45
+ expect(ThinkingSphinx::ActiveRecord::FilterReflection).
46
+ to receive(:call).
47
+ with(reflection, :foo_article, 'Article').
48
+ and_return(article_reflection)
49
+ expect(ThinkingSphinx::ActiveRecord::FilterReflection).
50
+ to receive(:call).
51
+ with(reflection, :foo_animal, 'Animal').
52
+ and_return(animal_reflection)
53
+
54
+ polymorpher.morph!
55
+ end
56
+
57
+ it "adds the new reflections to the end-of-stack model" do
58
+ if ActiveRecord::Reflection.respond_to?(:add_reflection)
59
+ expect(ActiveRecord::Reflection).to receive(:add_reflection).
60
+ with(model, :foo_article, article_reflection)
61
+ expect(ActiveRecord::Reflection).to receive(:add_reflection).
62
+ with(model, :foo_animal, animal_reflection)
63
+
64
+ polymorpher.morph!
65
+ else
66
+ polymorpher.morph!
67
+
68
+ expect(model.reflections[:foo_article]).to eq(article_reflection)
69
+ expect(model.reflections[:foo_animal]).to eq(animal_reflection)
70
+ end
71
+ end
72
+
73
+ it "rebases each field" do
74
+ expect(field).to receive(:rebase).with([:a, :b, :foo],
75
+ :to => [[:a, :b, :foo_article], [:a, :b, :foo_animal]])
76
+
77
+ polymorpher.morph!
78
+ end
79
+
80
+ it "rebases each attribute" do
81
+ expect(attribute).to receive(:rebase).with([:a, :b, :foo],
82
+ :to => [[:a, :b, :foo_article], [:a, :b, :foo_animal]])
83
+
84
+ polymorpher.morph!
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,264 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe ThinkingSphinx::ActiveRecord::PropertySQLPresenter do
6
+ let(:adapter) { double 'adapter' }
7
+ let(:associations) { double 'associations', :alias_for => 'articles' }
8
+ let(:model) { double :column_names => ['title', 'created_at'] }
9
+ let(:path) { double :aggregate? => false, :model => model }
10
+
11
+ before :each do
12
+ allow(adapter).to receive(:quote) { |column| column }
13
+
14
+ stub_const 'Joiner::Path', double(:new => path)
15
+ end
16
+
17
+ context 'with a field' do
18
+ let(:presenter) {
19
+ ThinkingSphinx::ActiveRecord::PropertySQLPresenter.new(
20
+ field, adapter, associations
21
+ )
22
+ }
23
+ let(:field) { double('field', :name => 'title', :columns => [column],
24
+ :type => nil, :multi? => false, :source_type => nil, :model => double) }
25
+ let(:column) { double('column', :string? => false, :__stack => [],
26
+ :__name => 'title') }
27
+
28
+ describe '#to_group' do
29
+ it "returns the column name as a string" do
30
+ expect(presenter.to_group).to eq('articles.title')
31
+ end
32
+
33
+ it "gets the column's table alias from the associations object" do
34
+ allow(column).to receive_messages(:__stack => [:users, :posts])
35
+
36
+ expect(associations).to receive(:alias_for).with([:users, :posts]).
37
+ and_return('posts')
38
+
39
+ presenter.to_group
40
+ end
41
+
42
+ it "returns nil if the property is an aggregate" do
43
+ allow(path).to receive_messages :aggregate? => true
44
+
45
+ expect(presenter.to_group).to be_nil
46
+ end
47
+
48
+ it "returns nil if the field is sourced via a separate query" do
49
+ allow(field).to receive_messages :source_type => 'query'
50
+
51
+ expect(presenter.to_group).to be_nil
52
+ end
53
+ end
54
+
55
+ describe '#to_select' do
56
+ it "returns the column name as a string" do
57
+ expect(presenter.to_select).to eq('articles.title AS title')
58
+ end
59
+
60
+ it "gets the column's table alias from the associations object" do
61
+ allow(column).to receive_messages(:__stack => [:users, :posts])
62
+
63
+ expect(associations).to receive(:alias_for).with([:users, :posts]).
64
+ and_return('posts')
65
+
66
+ presenter.to_select
67
+ end
68
+
69
+ it "returns the column name with an alias when provided" do
70
+ allow(field).to receive_messages(:name => :subject)
71
+
72
+ expect(presenter.to_select).to eq('articles.title AS subject')
73
+ end
74
+
75
+ it "groups and concatenates aggregated columns" do
76
+ allow(adapter).to receive :group_concatenate do |clause, separator|
77
+ "GROUP_CONCAT(#{clause} SEPARATOR '#{separator}')"
78
+ end
79
+
80
+ allow(path).to receive_messages :aggregate? => true
81
+
82
+ expect(presenter.to_select).
83
+ to eq("GROUP_CONCAT(articles.title SEPARATOR ' ') AS title")
84
+ end
85
+
86
+ it "concatenates multiple columns" do
87
+ allow(adapter).to receive :concatenate do |clause, separator|
88
+ "CONCAT_WS('#{separator}', #{clause})"
89
+ end
90
+
91
+ allow(field).to receive_messages(:columns => [column, column])
92
+
93
+ expect(presenter.to_select).
94
+ to eq("CONCAT_WS(' ', articles.title, articles.title) AS title")
95
+ end
96
+
97
+ it "does not include columns that don't exist" do
98
+ allow(adapter).to receive :concatenate do |clause, separator|
99
+ "CONCAT_WS('#{separator}', #{clause})"
100
+ end
101
+
102
+ allow(field).to receive_messages(:columns => [column, double('column', :string? => false,
103
+ :__stack => [], :__name => 'body')])
104
+
105
+ expect(presenter.to_select).
106
+ to eq("CONCAT_WS(' ', articles.title) AS title")
107
+ end
108
+
109
+ it "returns nil for query sourced fields" do
110
+ allow(field).to receive_messages :source_type => :query
111
+
112
+ expect(presenter.to_select).to be_nil
113
+ end
114
+
115
+ it "returns nil for ranged query sourced fields" do
116
+ allow(field).to receive_messages :source_type => :ranged_query
117
+
118
+ expect(presenter.to_select).to be_nil
119
+ end
120
+ end
121
+ end
122
+
123
+ context 'with an attribute' do
124
+ let(:presenter) {
125
+ ThinkingSphinx::ActiveRecord::PropertySQLPresenter.new(
126
+ attribute, adapter, associations
127
+ )
128
+ }
129
+ let(:attribute) { double('attribute', :name => 'created_at',
130
+ :columns => [column], :type => :integer, :multi? => false,
131
+ :source_type => nil, :model => double) }
132
+ let(:column) { double('column', :string? => false, :__stack => [],
133
+ :__name => 'created_at') }
134
+
135
+ before :each do
136
+ allow(adapter).to receive :cast_to_timestamp do |clause|
137
+ "UNIX_TIMESTAMP(#{clause})"
138
+ end
139
+ end
140
+
141
+ describe '#to_group' do
142
+ it "returns the column name as a string" do
143
+ expect(presenter.to_group).to eq('articles.created_at')
144
+ end
145
+
146
+ it "gets the column's table alias from the associations object" do
147
+ allow(column).to receive_messages(:__stack => [:users, :posts])
148
+
149
+ expect(associations).to receive(:alias_for).with([:users, :posts]).
150
+ and_return('posts')
151
+
152
+ presenter.to_group
153
+ end
154
+
155
+ it "returns nil if the column is a string" do
156
+ allow(column).to receive_messages(:string? => true)
157
+
158
+ expect(presenter.to_group).to be_nil
159
+ end
160
+
161
+ it "returns nil if the property is an aggregate" do
162
+ allow(path).to receive_messages :aggregate? => true
163
+
164
+ expect(presenter.to_group).to be_nil
165
+ end
166
+
167
+ it "returns nil if the attribute is sourced via a separate query" do
168
+ allow(attribute).to receive_messages :source_type => 'query'
169
+
170
+ expect(presenter.to_group).to be_nil
171
+ end
172
+ end
173
+
174
+ describe '#to_select' do
175
+ it "returns the column name as a string" do
176
+ expect(presenter.to_select).to eq('articles.created_at AS created_at')
177
+ end
178
+
179
+ it "gets the column's table alias from the associations object" do
180
+ allow(column).to receive_messages(:__stack => [:users, :posts])
181
+
182
+ expect(associations).to receive(:alias_for).with([:users, :posts]).
183
+ and_return('posts')
184
+
185
+ presenter.to_select
186
+ end
187
+
188
+ it "returns the column name with an alias when provided" do
189
+ allow(attribute).to receive_messages(:name => :creation_timestamp)
190
+
191
+ expect(presenter.to_select).
192
+ to eq('articles.created_at AS creation_timestamp')
193
+ end
194
+
195
+ it "ensures datetime attributes are converted to timestamps" do
196
+ allow(attribute).to receive_messages :type => :timestamp
197
+
198
+ expect(presenter.to_select).
199
+ to eq('UNIX_TIMESTAMP(articles.created_at) AS created_at')
200
+ end
201
+
202
+ it "does not include columns that don't exist" do
203
+ allow(adapter).to receive :concatenate do |clause, separator|
204
+ "CONCAT_WS('#{separator}', #{clause})"
205
+ end
206
+ allow(adapter).to receive :cast_to_string do |clause|
207
+ "CAST(#{clause} AS varchar)"
208
+ end
209
+
210
+ allow(attribute).to receive_messages(:columns => [column, double('column',
211
+ :string? => false, :__stack => [], :__name => 'updated_at')])
212
+
213
+ expect(presenter.to_select).to eq("CONCAT_WS(',', CAST(articles.created_at AS varchar)) AS created_at")
214
+ end
215
+
216
+ it "casts and concatenates multiple columns for attributes" do
217
+ allow(adapter).to receive :concatenate do |clause, separator|
218
+ "CONCAT_WS('#{separator}', #{clause})"
219
+ end
220
+ allow(adapter).to receive :cast_to_string do |clause|
221
+ "CAST(#{clause} AS varchar)"
222
+ end
223
+
224
+ allow(attribute).to receive_messages(:columns => [column, column])
225
+
226
+ expect(presenter.to_select).to eq("CONCAT_WS(',', CAST(articles.created_at AS varchar), CAST(articles.created_at AS varchar)) AS created_at")
227
+ end
228
+
229
+ it "double-casts and concatenates multiple columns for timestamp attributes" do
230
+ allow(adapter).to receive :concatenate do |clause, separator|
231
+ "CONCAT_WS('#{separator}', #{clause})"
232
+ end
233
+ allow(adapter).to receive :cast_to_string do |clause|
234
+ "CAST(#{clause} AS varchar)"
235
+ end
236
+
237
+ allow(attribute).to receive_messages :columns => [column, column], :type => :timestamp
238
+
239
+ expect(presenter.to_select).to eq("CONCAT_WS(',', CAST(UNIX_TIMESTAMP(articles.created_at) AS varchar), CAST(UNIX_TIMESTAMP(articles.created_at) AS varchar)) AS created_at")
240
+ end
241
+
242
+ it "does not split attribute clause for timestamp casting if it looks like a function call" do
243
+ allow(column).to receive_messages :__name => "COALESCE(articles.updated_at, articles.created_at)", :string? => true
244
+
245
+ allow(attribute).to receive_messages :name => 'mod_date', :columns => [column],
246
+ :type => :timestamp
247
+
248
+ expect(presenter.to_select).to eq("UNIX_TIMESTAMP(COALESCE(articles.updated_at, articles.created_at)) AS mod_date")
249
+ end
250
+
251
+ it "returns nil for query sourced attributes" do
252
+ allow(attribute).to receive_messages :source_type => :query
253
+
254
+ expect(presenter.to_select).to be_nil
255
+ end
256
+
257
+ it "returns nil for ranged query sourced attributes" do
258
+ allow(attribute).to receive_messages :source_type => :ranged_query
259
+
260
+ expect(presenter.to_select).to be_nil
261
+ end
262
+ end
263
+ end
264
+ end