thinking-sphinx 3.1.4 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (347) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +99 -0
  3. data/.github/actions/test/action.yml +46 -0
  4. data/.github/workflows/ci.yml +75 -0
  5. data/.gitignore +7 -2
  6. data/.travis.yml +31 -16
  7. data/Appraisals +68 -12
  8. data/CHANGELOG.markdown +782 -0
  9. data/Gemfile +13 -4
  10. data/Procfile.support +2 -0
  11. data/README.textile +41 -27
  12. data/Rakefile +2 -0
  13. data/bin/console +15 -0
  14. data/bin/loadsphinx +99 -0
  15. data/bin/testmatrix +48 -0
  16. data/lib/thinking/sphinx.rb +2 -0
  17. data/lib/thinking-sphinx.rb +2 -0
  18. data/lib/thinking_sphinx/active_record/association.rb +2 -0
  19. data/lib/thinking_sphinx/active_record/association_proxy/attribute_finder.rb +3 -1
  20. data/lib/thinking_sphinx/active_record/association_proxy/attribute_matcher.rb +2 -0
  21. data/lib/thinking_sphinx/active_record/association_proxy.rb +3 -2
  22. data/lib/thinking_sphinx/active_record/attribute/sphinx_presenter.rb +3 -1
  23. data/lib/thinking_sphinx/active_record/attribute/type.rb +20 -4
  24. data/lib/thinking_sphinx/active_record/attribute/values.rb +2 -0
  25. data/lib/thinking_sphinx/active_record/attribute.rb +2 -0
  26. data/lib/thinking_sphinx/active_record/base.rb +43 -11
  27. data/lib/thinking_sphinx/active_record/callbacks/association_delta_callbacks.rb +21 -0
  28. data/lib/thinking_sphinx/active_record/callbacks/delete_callbacks.rb +15 -9
  29. data/lib/thinking_sphinx/active_record/callbacks/delta_callbacks.rb +20 -5
  30. data/lib/thinking_sphinx/active_record/callbacks/update_callbacks.rb +18 -4
  31. data/lib/thinking_sphinx/active_record/column.rb +2 -0
  32. data/lib/thinking_sphinx/active_record/column_sql_presenter.rb +7 -1
  33. data/lib/thinking_sphinx/active_record/database_adapters/abstract_adapter.rb +2 -0
  34. data/lib/thinking_sphinx/active_record/database_adapters/mysql_adapter.rb +9 -1
  35. data/lib/thinking_sphinx/active_record/database_adapters/postgresql_adapter.rb +2 -0
  36. data/lib/thinking_sphinx/active_record/database_adapters.rb +3 -1
  37. data/lib/thinking_sphinx/active_record/depolymorph/association_reflection.rb +32 -0
  38. data/lib/thinking_sphinx/active_record/depolymorph/base_reflection.rb +32 -0
  39. data/lib/thinking_sphinx/active_record/depolymorph/conditions_reflection.rb +40 -0
  40. data/lib/thinking_sphinx/active_record/depolymorph/overridden_reflection.rb +50 -0
  41. data/lib/thinking_sphinx/active_record/depolymorph/scoped_reflection.rb +26 -0
  42. data/lib/thinking_sphinx/active_record/field.rb +2 -0
  43. data/lib/thinking_sphinx/active_record/filter_reflection.rb +13 -71
  44. data/lib/thinking_sphinx/active_record/index.rb +7 -5
  45. data/lib/thinking_sphinx/active_record/interpreter.rb +6 -4
  46. data/lib/thinking_sphinx/active_record/join_association.rb +5 -1
  47. data/lib/thinking_sphinx/active_record/log_subscriber.rb +22 -3
  48. data/lib/thinking_sphinx/active_record/polymorpher.rb +2 -0
  49. data/lib/thinking_sphinx/active_record/property.rb +2 -0
  50. data/lib/thinking_sphinx/active_record/property_query.rb +4 -1
  51. data/lib/thinking_sphinx/active_record/property_sql_presenter.rb +2 -0
  52. data/lib/thinking_sphinx/active_record/simple_many_query.rb +2 -0
  53. data/lib/thinking_sphinx/active_record/source_joins.rb +68 -0
  54. data/lib/thinking_sphinx/active_record/sql_builder/clause_builder.rb +2 -0
  55. data/lib/thinking_sphinx/active_record/sql_builder/query.rb +13 -0
  56. data/lib/thinking_sphinx/active_record/sql_builder/statement.rb +2 -0
  57. data/lib/thinking_sphinx/active_record/sql_builder.rb +5 -18
  58. data/lib/thinking_sphinx/active_record/sql_source/template.rb +5 -3
  59. data/lib/thinking_sphinx/active_record/sql_source.rb +35 -9
  60. data/lib/thinking_sphinx/active_record.rb +14 -1
  61. data/lib/thinking_sphinx/attribute_types.rb +72 -0
  62. data/lib/thinking_sphinx/batched_search.rb +2 -0
  63. data/lib/thinking_sphinx/callbacks/appender.rb +63 -0
  64. data/lib/thinking_sphinx/callbacks.rb +29 -0
  65. data/lib/thinking_sphinx/capistrano/v2.rb +2 -0
  66. data/lib/thinking_sphinx/capistrano/v3.rb +2 -0
  67. data/lib/thinking_sphinx/capistrano.rb +2 -0
  68. data/lib/thinking_sphinx/commander.rb +27 -0
  69. data/lib/thinking_sphinx/commands/base.rb +53 -0
  70. data/lib/thinking_sphinx/commands/clear_real_time.rb +22 -0
  71. data/lib/thinking_sphinx/commands/clear_sql.rb +18 -0
  72. data/lib/thinking_sphinx/commands/configure.rb +15 -0
  73. data/lib/thinking_sphinx/commands/index_real_time.rb +15 -0
  74. data/lib/thinking_sphinx/commands/index_sql.rb +25 -0
  75. data/lib/thinking_sphinx/commands/merge.rb +27 -0
  76. data/lib/thinking_sphinx/commands/merge_and_update.rb +57 -0
  77. data/lib/thinking_sphinx/commands/prepare.rb +15 -0
  78. data/lib/thinking_sphinx/commands/rotate.rb +13 -0
  79. data/lib/thinking_sphinx/commands/running.rb +15 -0
  80. data/lib/thinking_sphinx/commands/start_attached.rb +22 -0
  81. data/lib/thinking_sphinx/commands/start_detached.rb +21 -0
  82. data/lib/thinking_sphinx/commands/stop.rb +24 -0
  83. data/lib/thinking_sphinx/commands.rb +20 -0
  84. data/lib/thinking_sphinx/configuration/consistent_ids.rb +2 -0
  85. data/lib/thinking_sphinx/configuration/defaults.rb +2 -0
  86. data/lib/thinking_sphinx/configuration/distributed_indices.rb +3 -1
  87. data/lib/thinking_sphinx/configuration/duplicate_names.rb +36 -0
  88. data/lib/thinking_sphinx/configuration/minimum_fields.rb +17 -12
  89. data/lib/thinking_sphinx/configuration.rb +90 -74
  90. data/lib/thinking_sphinx/connection/client.rb +74 -0
  91. data/lib/thinking_sphinx/connection/jruby.rb +58 -0
  92. data/lib/thinking_sphinx/connection/mri.rb +26 -0
  93. data/lib/thinking_sphinx/connection.rb +13 -114
  94. data/lib/thinking_sphinx/core/field.rb +2 -0
  95. data/lib/thinking_sphinx/core/index.rb +22 -2
  96. data/lib/thinking_sphinx/core/interpreter.rb +2 -0
  97. data/lib/thinking_sphinx/core/property.rb +2 -0
  98. data/lib/thinking_sphinx/core/settings.rb +2 -0
  99. data/lib/thinking_sphinx/core.rb +2 -0
  100. data/lib/thinking_sphinx/deletion.rb +33 -13
  101. data/lib/thinking_sphinx/deltas/default_delta.rb +3 -1
  102. data/lib/thinking_sphinx/deltas/delete_job.rb +16 -4
  103. data/lib/thinking_sphinx/deltas/index_job.rb +14 -2
  104. data/lib/thinking_sphinx/deltas.rb +2 -0
  105. data/lib/thinking_sphinx/distributed/index.rb +25 -3
  106. data/lib/thinking_sphinx/distributed.rb +2 -0
  107. data/lib/thinking_sphinx/errors.rb +47 -3
  108. data/lib/thinking_sphinx/excerpter.rb +2 -0
  109. data/lib/thinking_sphinx/facet.rb +4 -3
  110. data/lib/thinking_sphinx/facet_search.rb +4 -2
  111. data/lib/thinking_sphinx/float_formatter.rb +2 -0
  112. data/lib/thinking_sphinx/frameworks/plain.rb +2 -0
  113. data/lib/thinking_sphinx/frameworks/rails.rb +2 -0
  114. data/lib/thinking_sphinx/frameworks.rb +2 -0
  115. data/lib/thinking_sphinx/guard/file.rb +3 -1
  116. data/lib/thinking_sphinx/guard/files.rb +2 -0
  117. data/lib/thinking_sphinx/guard/none.rb +7 -0
  118. data/lib/thinking_sphinx/guard.rb +3 -0
  119. data/lib/thinking_sphinx/hooks/guard_presence.rb +34 -0
  120. data/lib/thinking_sphinx/index.rb +2 -0
  121. data/lib/thinking_sphinx/index_set.rb +27 -4
  122. data/lib/thinking_sphinx/indexing_strategies/all_at_once.rb +9 -0
  123. data/lib/thinking_sphinx/indexing_strategies/one_at_a_time.rb +16 -0
  124. data/lib/thinking_sphinx/interfaces/base.rb +13 -0
  125. data/lib/thinking_sphinx/interfaces/daemon.rb +27 -0
  126. data/lib/thinking_sphinx/interfaces/real_time.rb +46 -0
  127. data/lib/thinking_sphinx/interfaces/sql.rb +53 -0
  128. data/lib/thinking_sphinx/interfaces.rb +10 -0
  129. data/lib/thinking_sphinx/logger.rb +2 -0
  130. data/lib/thinking_sphinx/masks/group_enumerators_mask.rb +6 -4
  131. data/lib/thinking_sphinx/masks/pagination_mask.rb +2 -0
  132. data/lib/thinking_sphinx/masks/scopes_mask.rb +8 -0
  133. data/lib/thinking_sphinx/masks/weight_enumerator_mask.rb +3 -1
  134. data/lib/thinking_sphinx/masks.rb +2 -0
  135. data/lib/thinking_sphinx/middlewares/active_record_translator.rb +32 -9
  136. data/lib/thinking_sphinx/middlewares/geographer.rb +2 -0
  137. data/lib/thinking_sphinx/middlewares/glazier.rb +14 -1
  138. data/lib/thinking_sphinx/middlewares/ids_only.rb +2 -0
  139. data/lib/thinking_sphinx/middlewares/inquirer.rb +3 -1
  140. data/lib/thinking_sphinx/middlewares/middleware.rb +2 -0
  141. data/lib/thinking_sphinx/middlewares/sphinxql.rb +18 -16
  142. data/lib/thinking_sphinx/middlewares/stale_id_checker.rb +3 -1
  143. data/lib/thinking_sphinx/middlewares/stale_id_filter.rb +4 -2
  144. data/lib/thinking_sphinx/middlewares/valid_options.rb +25 -0
  145. data/lib/thinking_sphinx/middlewares.rb +7 -3
  146. data/lib/thinking_sphinx/panes/attributes_pane.rb +2 -0
  147. data/lib/thinking_sphinx/panes/distance_pane.rb +2 -0
  148. data/lib/thinking_sphinx/panes/excerpts_pane.rb +2 -0
  149. data/lib/thinking_sphinx/panes/weight_pane.rb +3 -1
  150. data/lib/thinking_sphinx/panes.rb +2 -0
  151. data/lib/thinking_sphinx/processor.rb +71 -0
  152. data/lib/thinking_sphinx/query.rb +2 -0
  153. data/lib/thinking_sphinx/railtie.rb +29 -2
  154. data/lib/thinking_sphinx/rake_interface.rb +14 -69
  155. data/lib/thinking_sphinx/real_time/attribute.rb +9 -1
  156. data/lib/thinking_sphinx/real_time/callbacks/real_time_callbacks.rb +17 -7
  157. data/lib/thinking_sphinx/real_time/field.rb +2 -0
  158. data/lib/thinking_sphinx/real_time/index/template.rb +19 -1
  159. data/lib/thinking_sphinx/real_time/index.rb +11 -5
  160. data/lib/thinking_sphinx/real_time/interpreter.rb +10 -6
  161. data/lib/thinking_sphinx/real_time/populator.rb +12 -14
  162. data/lib/thinking_sphinx/real_time/processor.rb +36 -0
  163. data/lib/thinking_sphinx/real_time/property.rb +3 -5
  164. data/lib/thinking_sphinx/real_time/transcribe_instance.rb +38 -0
  165. data/lib/thinking_sphinx/real_time/transcriber.rb +63 -15
  166. data/lib/thinking_sphinx/real_time/translator.rb +39 -0
  167. data/lib/thinking_sphinx/real_time.rb +22 -1
  168. data/lib/thinking_sphinx/scopes.rb +6 -0
  169. data/lib/thinking_sphinx/search/batch_inquirer.rb +2 -0
  170. data/lib/thinking_sphinx/search/context.rb +11 -0
  171. data/lib/thinking_sphinx/search/glaze.rb +2 -0
  172. data/lib/thinking_sphinx/search/merger.rb +2 -0
  173. data/lib/thinking_sphinx/search/query.rb +9 -1
  174. data/lib/thinking_sphinx/search/stale_ids_exception.rb +7 -3
  175. data/lib/thinking_sphinx/search.rb +30 -2
  176. data/lib/thinking_sphinx/settings.rb +128 -0
  177. data/lib/thinking_sphinx/sinatra.rb +3 -1
  178. data/lib/thinking_sphinx/subscribers/populator_subscriber.rb +19 -5
  179. data/lib/thinking_sphinx/tasks.rb +55 -28
  180. data/lib/thinking_sphinx/test.rb +3 -1
  181. data/lib/thinking_sphinx/utf8.rb +2 -0
  182. data/lib/thinking_sphinx/wildcard.rb +3 -1
  183. data/lib/thinking_sphinx/with_output.rb +13 -0
  184. data/lib/thinking_sphinx.rb +35 -4
  185. data/spec/acceptance/association_scoping_spec.rb +7 -5
  186. data/spec/acceptance/attribute_access_spec.rb +29 -12
  187. data/spec/acceptance/attribute_updates_spec.rb +5 -3
  188. data/spec/acceptance/batch_searching_spec.rb +6 -4
  189. data/spec/acceptance/big_integers_spec.rb +9 -7
  190. data/spec/acceptance/excerpts_spec.rb +11 -10
  191. data/spec/acceptance/facets_spec.rb +29 -16
  192. data/spec/acceptance/geosearching_spec.rb +22 -10
  193. data/spec/acceptance/grouping_by_attributes_spec.rb +30 -28
  194. data/spec/acceptance/index_options_spec.rb +18 -16
  195. data/spec/acceptance/indexing_spec.rb +5 -3
  196. data/spec/acceptance/merging_spec.rb +90 -0
  197. data/spec/acceptance/paginating_search_results_spec.rb +21 -3
  198. data/spec/acceptance/real_time_updates_spec.rb +103 -5
  199. data/spec/acceptance/remove_deleted_records_spec.rb +64 -8
  200. data/spec/acceptance/search_counts_spec.rb +4 -2
  201. data/spec/acceptance/search_for_just_ids_spec.rb +4 -2
  202. data/spec/acceptance/searching_across_models_spec.rb +15 -6
  203. data/spec/acceptance/searching_across_schemas_spec.rb +12 -10
  204. data/spec/acceptance/searching_on_fields_spec.rb +11 -9
  205. data/spec/acceptance/searching_with_filters_spec.rb +35 -20
  206. data/spec/acceptance/searching_with_sti_spec.rb +11 -9
  207. data/spec/acceptance/searching_within_a_model_spec.rb +44 -17
  208. data/spec/acceptance/sorting_search_results_spec.rb +21 -19
  209. data/spec/acceptance/spec_helper.rb +2 -13
  210. data/spec/acceptance/specifying_sql_spec.rb +118 -62
  211. data/spec/acceptance/sphinx_scopes_spec.rb +30 -21
  212. data/spec/acceptance/sql_deltas_spec.rb +35 -9
  213. data/spec/acceptance/support/database_cleaner.rb +3 -1
  214. data/spec/acceptance/support/sphinx_controller.rb +25 -9
  215. data/spec/acceptance/support/sphinx_helpers.rb +17 -2
  216. data/spec/acceptance/suspended_deltas_spec.rb +14 -12
  217. data/spec/fixtures/database.yml +1 -1
  218. data/spec/internal/app/indices/admin_person_index.rb +6 -0
  219. data/spec/internal/app/indices/album_index.rb +9 -0
  220. data/spec/internal/app/indices/animal_index.rb +2 -0
  221. data/spec/internal/app/indices/article_index.rb +10 -3
  222. data/spec/internal/app/indices/bird_index.rb +2 -0
  223. data/spec/internal/app/indices/book_index.rb +4 -1
  224. data/spec/internal/app/indices/car_index.rb +2 -0
  225. data/spec/internal/app/indices/city_index.rb +2 -0
  226. data/spec/internal/app/indices/colour_index.rb +7 -0
  227. data/spec/internal/app/indices/product_index.rb +3 -2
  228. data/spec/internal/app/indices/tee_index.rb +3 -1
  229. data/spec/internal/app/indices/user_index.rb +2 -0
  230. data/spec/internal/app/models/admin/person.rb +6 -0
  231. data/spec/internal/app/models/album.rb +25 -0
  232. data/spec/internal/app/models/animal.rb +3 -0
  233. data/spec/internal/app/models/article.rb +4 -0
  234. data/spec/internal/app/models/bird.rb +3 -0
  235. data/spec/internal/app/models/book.rb +9 -5
  236. data/spec/internal/app/models/car.rb +3 -1
  237. data/spec/internal/app/models/categorisation.rb +10 -1
  238. data/spec/internal/app/models/category.rb +2 -0
  239. data/spec/internal/app/models/city.rb +4 -0
  240. data/spec/internal/app/models/colour.rb +4 -0
  241. data/spec/internal/app/models/event.rb +2 -0
  242. data/spec/internal/app/models/flightless_bird.rb +2 -0
  243. data/spec/internal/app/models/genre.rb +2 -0
  244. data/spec/internal/app/models/hardcover.rb +2 -0
  245. data/spec/internal/app/models/mammal.rb +2 -0
  246. data/spec/internal/app/models/manufacturer.rb +2 -0
  247. data/spec/internal/app/models/product.rb +3 -1
  248. data/spec/internal/app/models/tag.rb +2 -0
  249. data/spec/internal/app/models/tagging.rb +2 -0
  250. data/spec/internal/app/models/tee.rb +7 -0
  251. data/spec/internal/app/models/tweet.rb +2 -0
  252. data/spec/internal/app/models/user.rb +4 -0
  253. data/spec/internal/config/database.yml +12 -1
  254. data/spec/internal/db/schema.rb +13 -1
  255. data/spec/spec_helper.rb +12 -1
  256. data/spec/support/json_column.rb +35 -0
  257. data/spec/support/multi_schema.rb +5 -1
  258. data/spec/support/mysql.rb +25 -0
  259. data/spec/support/sphinx_yaml_helpers.rb +8 -1
  260. data/spec/thinking_sphinx/active_record/association_spec.rb +3 -1
  261. data/spec/thinking_sphinx/active_record/attribute/type_spec.rb +43 -38
  262. data/spec/thinking_sphinx/active_record/base_spec.rb +31 -29
  263. data/spec/thinking_sphinx/active_record/callbacks/delete_callbacks_spec.rb +81 -10
  264. data/spec/thinking_sphinx/active_record/callbacks/delta_callbacks_spec.rb +56 -29
  265. data/spec/thinking_sphinx/active_record/callbacks/update_callbacks_spec.rb +27 -10
  266. data/spec/thinking_sphinx/active_record/column_spec.rb +15 -13
  267. data/spec/thinking_sphinx/active_record/column_sql_presenter_spec.rb +39 -0
  268. data/spec/thinking_sphinx/active_record/database_adapters/abstract_adapter_spec.rb +7 -5
  269. data/spec/thinking_sphinx/active_record/database_adapters/mysql_adapter_spec.rb +26 -12
  270. data/spec/thinking_sphinx/active_record/database_adapters/postgresql_adapter_spec.rb +15 -13
  271. data/spec/thinking_sphinx/active_record/database_adapters_spec.rb +50 -48
  272. data/spec/thinking_sphinx/active_record/field_spec.rb +9 -7
  273. data/spec/thinking_sphinx/active_record/filter_reflection_spec.rb +113 -80
  274. data/spec/thinking_sphinx/active_record/index_spec.rb +41 -37
  275. data/spec/thinking_sphinx/active_record/interpreter_spec.rb +62 -59
  276. data/spec/thinking_sphinx/active_record/polymorpher_spec.rb +16 -14
  277. data/spec/thinking_sphinx/active_record/property_sql_presenter_spec.rb +69 -67
  278. data/spec/thinking_sphinx/active_record/sql_builder_spec.rb +146 -154
  279. data/spec/thinking_sphinx/active_record/sql_source_spec.rb +185 -109
  280. data/spec/thinking_sphinx/attribute_types_spec.rb +52 -0
  281. data/spec/thinking_sphinx/commands/clear_real_time_spec.rb +46 -0
  282. data/spec/thinking_sphinx/commands/clear_sql_spec.rb +52 -0
  283. data/spec/thinking_sphinx/commands/configure_spec.rb +31 -0
  284. data/spec/thinking_sphinx/commands/index_real_time_spec.rb +33 -0
  285. data/spec/thinking_sphinx/commands/index_sql_spec.rb +86 -0
  286. data/spec/thinking_sphinx/commands/merge_and_update_spec.rb +106 -0
  287. data/spec/thinking_sphinx/commands/merge_spec.rb +48 -0
  288. data/spec/thinking_sphinx/commands/prepare_spec.rb +31 -0
  289. data/spec/thinking_sphinx/commands/running_spec.rb +30 -0
  290. data/spec/thinking_sphinx/commands/start_detached_spec.rb +67 -0
  291. data/spec/thinking_sphinx/commands/stop_spec.rb +63 -0
  292. data/spec/thinking_sphinx/configuration/minimum_fields_spec.rb +60 -0
  293. data/spec/thinking_sphinx/configuration_spec.rb +247 -94
  294. data/spec/thinking_sphinx/connection/mri_spec.rb +49 -0
  295. data/spec/thinking_sphinx/connection_spec.rb +15 -13
  296. data/spec/thinking_sphinx/deletion_spec.rb +17 -17
  297. data/spec/thinking_sphinx/deltas/default_delta_spec.rb +28 -21
  298. data/spec/thinking_sphinx/deltas_spec.rb +14 -12
  299. data/spec/thinking_sphinx/errors_spec.rb +59 -27
  300. data/spec/thinking_sphinx/excerpter_spec.rb +12 -9
  301. data/spec/thinking_sphinx/facet_search_spec.rb +24 -22
  302. data/spec/thinking_sphinx/hooks/guard_presence_spec.rb +30 -0
  303. data/spec/thinking_sphinx/index_set_spec.rb +59 -18
  304. data/spec/thinking_sphinx/index_spec.rb +28 -26
  305. data/spec/thinking_sphinx/interfaces/daemon_spec.rb +60 -0
  306. data/spec/thinking_sphinx/interfaces/real_time_spec.rb +109 -0
  307. data/spec/thinking_sphinx/interfaces/sql_spec.rb +122 -0
  308. data/spec/thinking_sphinx/masks/pagination_mask_spec.rb +22 -20
  309. data/spec/thinking_sphinx/masks/scopes_mask_spec.rb +20 -18
  310. data/spec/thinking_sphinx/middlewares/active_record_translator_spec.rb +45 -21
  311. data/spec/thinking_sphinx/middlewares/geographer_spec.rb +11 -9
  312. data/spec/thinking_sphinx/middlewares/glazier_spec.rb +12 -9
  313. data/spec/thinking_sphinx/middlewares/inquirer_spec.rb +9 -7
  314. data/spec/thinking_sphinx/middlewares/sphinxql_spec.rb +60 -58
  315. data/spec/thinking_sphinx/middlewares/stale_id_checker_spec.rb +7 -4
  316. data/spec/thinking_sphinx/middlewares/stale_id_filter_spec.rb +39 -17
  317. data/spec/thinking_sphinx/middlewares/valid_options_spec.rb +51 -0
  318. data/spec/thinking_sphinx/panes/attributes_pane_spec.rb +3 -1
  319. data/spec/thinking_sphinx/panes/distance_pane_spec.rb +6 -4
  320. data/spec/thinking_sphinx/panes/excerpts_pane_spec.rb +8 -6
  321. data/spec/thinking_sphinx/panes/weight_pane_spec.rb +4 -2
  322. data/spec/thinking_sphinx/rake_interface_spec.rb +17 -235
  323. data/spec/thinking_sphinx/real_time/attribute_spec.rb +15 -13
  324. data/spec/thinking_sphinx/real_time/callbacks/real_time_callbacks_spec.rb +114 -28
  325. data/spec/thinking_sphinx/real_time/field_spec.rb +16 -14
  326. data/spec/thinking_sphinx/real_time/index_spec.rb +83 -32
  327. data/spec/thinking_sphinx/real_time/interpreter_spec.rb +44 -42
  328. data/spec/thinking_sphinx/real_time/transcribe_instance_spec.rb +35 -0
  329. data/spec/thinking_sphinx/real_time/transcriber_spec.rb +109 -0
  330. data/spec/thinking_sphinx/real_time/translator_spec.rb +17 -0
  331. data/spec/thinking_sphinx/scopes_spec.rb +11 -5
  332. data/spec/thinking_sphinx/search/glaze_spec.rb +17 -15
  333. data/spec/thinking_sphinx/search/query_spec.rb +19 -10
  334. data/spec/thinking_sphinx/search_spec.rb +30 -28
  335. data/spec/thinking_sphinx/wildcard_spec.rb +18 -11
  336. data/spec/thinking_sphinx_spec.rb +10 -7
  337. data/thinking-sphinx.gemspec +17 -10
  338. metadata +157 -49
  339. data/HISTORY +0 -248
  340. data/gemfiles/.gitignore +0 -1
  341. data/gemfiles/rails_3_2.gemfile +0 -11
  342. data/gemfiles/rails_4_0.gemfile +0 -11
  343. data/gemfiles/rails_4_1.gemfile +0 -11
  344. data/gemfiles/rails_4_2.gemfile +0 -11
  345. data/lib/thinking_sphinx/controller.rb +0 -10
  346. data/lib/thinking_sphinx/middlewares/utf8.rb +0 -27
  347. data/lib/thinking_sphinx/sphinxql.rb +0 -23
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe ThinkingSphinx::RealTime::Interpreter do
@@ -8,19 +10,23 @@ describe ThinkingSphinx::RealTime::Interpreter do
8
10
  let(:index) { Struct.new(:attributes, :fields, :options).new([], [], {}) }
9
11
  let(:block) { Proc.new { } }
10
12
 
13
+ before :each do
14
+ allow(index).to receive_messages(:add_attribute => nil, :add_field => nil)
15
+ end
16
+
11
17
  describe '.translate!' do
12
18
  let(:instance) { double('interpreter', :translate! => true) }
13
19
 
14
20
  it "creates a new interpreter instance with the given block and index" do
15
- ThinkingSphinx::RealTime::Interpreter.should_receive(:new).
21
+ expect(ThinkingSphinx::RealTime::Interpreter).to receive(:new).
16
22
  with(index, block).and_return(instance)
17
23
 
18
24
  ThinkingSphinx::RealTime::Interpreter.translate! index, block
19
25
  end
20
26
 
21
27
  it "calls translate! on the instance" do
22
- ThinkingSphinx::RealTime::Interpreter.stub!(:new => instance)
23
- instance.should_receive(:translate!)
28
+ allow(ThinkingSphinx::RealTime::Interpreter).to receive_messages(:new => instance)
29
+ expect(instance).to receive(:translate!)
24
30
 
25
31
  ThinkingSphinx::RealTime::Interpreter.translate! index, block
26
32
  end
@@ -31,35 +37,33 @@ describe ThinkingSphinx::RealTime::Interpreter do
31
37
  let(:attribute) { double('attribute') }
32
38
 
33
39
  before :each do
34
- ThinkingSphinx::RealTime::Attribute.stub! :new => attribute
40
+ allow(ThinkingSphinx::RealTime::Attribute).to receive_messages :new => attribute
35
41
  end
36
42
 
37
43
  it "creates a new attribute with the provided column" do
38
- ThinkingSphinx::RealTime::Attribute.should_receive(:new).
44
+ expect(ThinkingSphinx::RealTime::Attribute).to receive(:new).
39
45
  with(column, {}).and_return(attribute)
40
46
 
41
47
  instance.has column
42
48
  end
43
49
 
44
50
  it "passes through options to the attribute" do
45
- ThinkingSphinx::RealTime::Attribute.should_receive(:new).
46
- with(column, :as => :other_name).and_return(attribute)
51
+ expect(ThinkingSphinx::RealTime::Attribute).to receive(:new).
52
+ with(column, { :as => :other_name }).and_return(attribute)
47
53
 
48
54
  instance.has column, :as => :other_name
49
55
  end
50
56
 
51
57
  it "adds an attribute to the index" do
52
- instance.has column
58
+ expect(index).to receive(:add_attribute).with(attribute)
53
59
 
54
- index.attributes.should include(attribute)
60
+ instance.has column
55
61
  end
56
62
 
57
63
  it "adds multiple attributes when passed multiple columns" do
58
- instance.has column, column
64
+ expect(index).to receive(:add_attribute).with(attribute).twice
59
65
 
60
- index.attributes.select { |saved_attribute|
61
- saved_attribute == attribute
62
- }.length.should == 2
66
+ instance.has column, column
63
67
  end
64
68
  end
65
69
 
@@ -68,74 +72,72 @@ describe ThinkingSphinx::RealTime::Interpreter do
68
72
  let(:field) { double('field') }
69
73
 
70
74
  before :each do
71
- ThinkingSphinx::RealTime::Field.stub! :new => field
75
+ allow(ThinkingSphinx::RealTime::Field).to receive_messages :new => field
72
76
  end
73
77
 
74
78
  it "creates a new field with the provided column" do
75
- ThinkingSphinx::RealTime::Field.should_receive(:new).
79
+ expect(ThinkingSphinx::RealTime::Field).to receive(:new).
76
80
  with(column, {}).and_return(field)
77
81
 
78
82
  instance.indexes column
79
83
  end
80
84
 
81
85
  it "passes through options to the field" do
82
- ThinkingSphinx::RealTime::Field.should_receive(:new).
83
- with(column, :as => :other_name).and_return(field)
86
+ expect(ThinkingSphinx::RealTime::Field).to receive(:new).
87
+ with(column, { :as => :other_name }).and_return(field)
84
88
 
85
89
  instance.indexes column, :as => :other_name
86
90
  end
87
91
 
88
92
  it "adds a field to the index" do
89
- instance.indexes column
93
+ expect(index).to receive(:add_field).with(field)
90
94
 
91
- index.fields.should include(field)
95
+ instance.indexes column
92
96
  end
93
97
 
94
98
  it "adds multiple fields when passed multiple columns" do
95
- instance.indexes column, column
99
+ expect(index).to receive(:add_field).with(field).twice
96
100
 
97
- index.fields.select { |saved_field|
98
- saved_field == field
99
- }.length.should == 2
101
+ instance.indexes column, column
100
102
  end
101
103
 
102
104
  context 'sortable' do
103
105
  let(:attribute) { double('attribute') }
104
106
 
105
107
  before :each do
106
- ThinkingSphinx::RealTime::Attribute.stub! :new => attribute
108
+ allow(ThinkingSphinx::RealTime::Attribute).to receive_messages :new => attribute
107
109
 
108
- column.stub :__name => :col
110
+ allow(column).to receive_messages :__name => :col
109
111
  end
110
112
 
111
113
  it "adds the _sort suffix to the field's name" do
112
- ThinkingSphinx::RealTime::Attribute.should_receive(:new).
113
- with(column, :as => :col_sort, :type => :string).
114
+ expect(ThinkingSphinx::RealTime::Attribute).to receive(:new).
115
+ with(column, { :as => :col_sort, :type => :string }).
114
116
  and_return(attribute)
115
117
 
116
118
  instance.indexes column, :sortable => true
117
119
  end
118
120
 
119
121
  it "respects given aliases" do
120
- ThinkingSphinx::RealTime::Attribute.should_receive(:new).
121
- with(column, :as => :other_sort, :type => :string).
122
+ expect(ThinkingSphinx::RealTime::Attribute).to receive(:new).
123
+ with(column, { :as => :other_sort, :type => :string }).
122
124
  and_return(attribute)
123
125
 
124
126
  instance.indexes column, :sortable => true, :as => :other
125
127
  end
126
128
 
127
129
  it "respects symbols instead of columns" do
128
- ThinkingSphinx::RealTime::Attribute.should_receive(:new).
129
- with(:title, :as => :title_sort, :type => :string).
130
+ expect(ThinkingSphinx::RealTime::Attribute).to receive(:new).
131
+ with(:title, { :as => :title_sort, :type => :string }).
130
132
  and_return(attribute)
131
133
 
132
134
  instance.indexes :title, :sortable => true
133
135
  end
134
136
 
135
137
  it "adds an attribute to the index" do
136
- instance.indexes column, :sortable => true
138
+ expect(index).to receive(:add_attribute).with(attribute)
137
139
 
138
- index.attributes.should include(attribute)
140
+ instance.indexes column, :sortable => true
139
141
  end
140
142
  end
141
143
  end
@@ -144,15 +146,15 @@ describe ThinkingSphinx::RealTime::Interpreter do
144
146
  let(:column) { double('column') }
145
147
 
146
148
  before :each do
147
- ThinkingSphinx::ActiveRecord::Column.stub!(:new => column)
149
+ allow(ThinkingSphinx::ActiveRecord::Column).to receive_messages(:new => column)
148
150
  end
149
151
 
150
152
  it "returns a new column for the given method" do
151
- instance.id.should == column
153
+ expect(instance.id).to eq(column)
152
154
  end
153
155
 
154
156
  it "should initialise the column with the method name and arguments" do
155
- ThinkingSphinx::ActiveRecord::Column.should_receive(:new).
157
+ expect(ThinkingSphinx::ActiveRecord::Column).to receive(:new).
156
158
  with(:users, :posts, :subject).and_return(column)
157
159
 
158
160
  instance.users(:posts, :subject)
@@ -161,7 +163,7 @@ describe ThinkingSphinx::RealTime::Interpreter do
161
163
 
162
164
  describe '#scope' do
163
165
  it "passes the scope block through to the index" do
164
- index.should_receive(:scope=).with(instance_of(Proc))
166
+ expect(index).to receive(:scope=).with(instance_of(Proc))
165
167
 
166
168
  instance.scope { :foo }
167
169
  end
@@ -169,18 +171,18 @@ describe ThinkingSphinx::RealTime::Interpreter do
169
171
 
170
172
  describe '#set_property' do
171
173
  before :each do
172
- index.class.stub :settings => [:morphology]
174
+ allow(index.class).to receive_messages :settings => [:morphology]
173
175
  end
174
176
 
175
177
  it 'saves other settings as index options' do
176
178
  instance.set_property :field_weights => {:name => 10}
177
179
 
178
- index.options[:field_weights].should == {:name => 10}
180
+ expect(index.options[:field_weights]).to eq({:name => 10})
179
181
  end
180
182
 
181
183
  context 'index settings' do
182
184
  it "sets the provided setting" do
183
- index.should_receive(:morphology=).with('stem_en')
185
+ expect(index).to receive(:morphology=).with('stem_en')
184
186
 
185
187
  instance.set_property :morphology => 'stem_en'
186
188
  end
@@ -194,8 +196,8 @@ describe ThinkingSphinx::RealTime::Interpreter do
194
196
  }
195
197
 
196
198
  interpreter = ThinkingSphinx::RealTime::Interpreter.new index, block
197
- interpreter.translate!.
198
- should == interpreter.__id__
199
+ expect(interpreter.translate!).
200
+ to eq(interpreter.__id__)
199
201
  end
200
202
  end
201
203
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe ThinkingSphinx::RealTime::TranscribeInstance do
6
+ let(:subject) do
7
+ ThinkingSphinx::RealTime::TranscribeInstance.call(
8
+ instance, index, [property_a, property_b, property_c]
9
+ )
10
+ end
11
+ let(:instance) { double :id => 43 }
12
+ let(:index) { double :document_id_for_key => 46, :primary_key => :id }
13
+ let(:property_a) { double :translate => 'A' }
14
+ let(:property_b) { double :translate => 'B' }
15
+ let(:property_c) { double :translate => 'C' }
16
+
17
+ it 'returns an array of each translated property, and the document id' do
18
+ expect(subject).to eq([46, 'A', 'B', 'C'])
19
+ end
20
+
21
+ it 'raises an error if something goes wrong' do
22
+ allow(property_b).to receive(:translate).and_raise(StandardError)
23
+
24
+ expect { subject }.to raise_error(ThinkingSphinx::TranscriptionError)
25
+ end
26
+
27
+ it 'notes the instance and property in the wrapper error' do
28
+ allow(property_b).to receive(:translate).and_raise(StandardError)
29
+
30
+ expect { subject }.to raise_error do |wrapper|
31
+ expect(wrapper.instance).to eq(instance)
32
+ expect(wrapper.property).to eq(property_b)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe ThinkingSphinx::RealTime::Transcriber do
6
+ let(:subject) { ThinkingSphinx::RealTime::Transcriber.new index }
7
+ let(:index) { double 'index', :name => 'foo_core', :conditions => [],
8
+ :fields => [double(:name => 'field_a'), double(:name => 'field_b')],
9
+ :attributes => [double(:name => 'attr_a'), double(:name => 'attr_b')],
10
+ :primary_key => :id }
11
+ let(:insert) { double :replace! => replace }
12
+ let(:replace) { double :to_sql => 'REPLACE QUERY' }
13
+ let(:connection) { double :execute => true }
14
+ let(:instance_a) { double :id => 48, :persisted? => true }
15
+ let(:instance_b) { double :id => 49, :persisted? => true }
16
+ let(:properties_a) { double }
17
+ let(:properties_b) { double }
18
+
19
+ before :each do
20
+ allow(Riddle::Query::Insert).to receive(:new).and_return(insert)
21
+ allow(ThinkingSphinx::Connection).to receive(:take).and_yield(connection)
22
+ allow(ThinkingSphinx::RealTime::TranscribeInstance).to receive(:call).
23
+ with(instance_a, index, anything).and_return(properties_a)
24
+ allow(ThinkingSphinx::RealTime::TranscribeInstance).to receive(:call).
25
+ with(instance_b, index, anything).and_return(properties_b)
26
+ end
27
+
28
+ it "generates a SphinxQL command" do
29
+ expect(Riddle::Query::Insert).to receive(:new).with(
30
+ 'foo_core',
31
+ ['id', 'field_a', 'field_b', 'attr_a', 'attr_b'],
32
+ [properties_a, properties_b]
33
+ )
34
+
35
+ subject.copy instance_a, instance_b
36
+ end
37
+
38
+ it "executes the SphinxQL command" do
39
+ expect(connection).to receive(:execute).with('REPLACE QUERY')
40
+
41
+ subject.copy instance_a, instance_b
42
+ end
43
+
44
+ it "deletes previous records" do
45
+ expect(connection).to receive(:execute).
46
+ with('DELETE FROM foo_core WHERE sphinx_internal_id IN (48, 49)')
47
+
48
+ subject.copy instance_a, instance_b
49
+ end
50
+
51
+ it "skips instances that aren't in the database" do
52
+ allow(instance_a).to receive(:persisted?).and_return(false)
53
+
54
+ expect(Riddle::Query::Insert).to receive(:new).with(
55
+ 'foo_core',
56
+ ['id', 'field_a', 'field_b', 'attr_a', 'attr_b'],
57
+ [properties_b]
58
+ )
59
+
60
+ subject.copy instance_a, instance_b
61
+ end
62
+
63
+ it "skips instances that fail a symbol condition" do
64
+ index.conditions << :ok?
65
+ allow(instance_a).to receive(:ok?).and_return(true)
66
+ allow(instance_b).to receive(:ok?).and_return(false)
67
+
68
+ expect(Riddle::Query::Insert).to receive(:new).with(
69
+ 'foo_core',
70
+ ['id', 'field_a', 'field_b', 'attr_a', 'attr_b'],
71
+ [properties_a]
72
+ )
73
+
74
+ subject.copy instance_a, instance_b
75
+ end
76
+
77
+ it "skips instances that fail a Proc condition" do
78
+ index.conditions << Proc.new { |instance| instance.ok? }
79
+ allow(instance_a).to receive(:ok?).and_return(true)
80
+ allow(instance_b).to receive(:ok?).and_return(false)
81
+
82
+ expect(Riddle::Query::Insert).to receive(:new).with(
83
+ 'foo_core',
84
+ ['id', 'field_a', 'field_b', 'attr_a', 'attr_b'],
85
+ [properties_a]
86
+ )
87
+
88
+ subject.copy instance_a, instance_b
89
+ end
90
+
91
+ it "skips instances that throw an error while transcribing values" do
92
+ error = ThinkingSphinx::TranscriptionError.new
93
+ error.instance = instance_a
94
+ error.inner_exception = StandardError.new
95
+
96
+ allow(ThinkingSphinx::RealTime::TranscribeInstance).to receive(:call).
97
+ with(instance_a, index, anything).
98
+ and_raise(error)
99
+ allow(ThinkingSphinx.output).to receive(:puts).and_return(nil)
100
+
101
+ expect(Riddle::Query::Insert).to receive(:new).with(
102
+ 'foo_core',
103
+ ['id', 'field_a', 'field_b', 'attr_a', 'attr_b'],
104
+ [properties_b]
105
+ )
106
+
107
+ subject.copy instance_a, instance_b
108
+ end
109
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe ThinkingSphinx::RealTime::Translator do
6
+ let(:subject) { ThinkingSphinx::RealTime::Translator.call object, column }
7
+ let(:object) { double }
8
+ let(:column) { double :__stack => [], :__name => :title }
9
+
10
+ it "converts non-UTF-8 strings to UTF-8" do
11
+ allow(object).to receive(:title).
12
+ and_return "hello".dup.force_encoding("ASCII-8BIT")
13
+
14
+ expect(subject).to eq("hello")
15
+ expect(subject.encoding.name).to eq("UTF-8")
16
+ end
17
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe ThinkingSphinx::Scopes do
@@ -16,30 +18,34 @@ describe ThinkingSphinx::Scopes do
16
18
  model.sphinx_scopes[:foo] = Proc.new { {:with => {:foo => :bar}} }
17
19
  end
18
20
 
21
+ it "implements respond_to" do
22
+ expect(model).to respond_to(:foo)
23
+ end
24
+
19
25
  it "creates new search" do
20
- model.foo.class.should == ThinkingSphinx::Search
26
+ expect(model.foo.class).to eq(ThinkingSphinx::Search)
21
27
  end
22
28
 
23
29
  it "passes block result to constructor" do
24
- model.foo.options[:with].should == {:foo => :bar}
30
+ expect(model.foo.options[:with]).to eq({:foo => :bar})
25
31
  end
26
32
 
27
33
  it "passes non-scopes through to the standard method error call" do
28
- lambda { model.bar }.should raise_error(NoMethodError)
34
+ expect { model.bar }.to raise_error(NoMethodError)
29
35
  end
30
36
  end
31
37
 
32
38
  describe '#sphinx_scope' do
33
39
  it "saves the given block with a name" do
34
40
  model.sphinx_scope(:foo) { 27 }
35
- model.sphinx_scopes[:foo].call.should == 27
41
+ expect(model.sphinx_scopes[:foo].call).to eq(27)
36
42
  end
37
43
  end
38
44
 
39
45
  describe '#default_sphinx_scope' do
40
46
  it "gets and sets the default scope depending on the argument" do
41
47
  model.default_sphinx_scope :foo
42
- model.default_sphinx_scope.should == :foo
48
+ expect(model.default_sphinx_scope).to eq(:foo)
43
49
  end
44
50
  end
45
51
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ThinkingSphinx
2
4
  class Search; end
3
5
  end
@@ -12,11 +14,11 @@ describe ThinkingSphinx::Search::Glaze do
12
14
 
13
15
  describe '#!=' do
14
16
  it "is true for objects that don't match" do
15
- (glaze != double('foo')).should be_true
17
+ expect(glaze != double('foo')).to be_truthy
16
18
  end
17
19
 
18
20
  it "is false when the underlying object is a match" do
19
- (glaze != object).should be_false
21
+ expect(glaze != object).to be_falsey
20
22
  end
21
23
  end
22
24
 
@@ -28,50 +30,50 @@ describe ThinkingSphinx::Search::Glaze do
28
30
  let(:pane_two) { double('pane two', :foo => 'two', :bar => 'two') }
29
31
 
30
32
  before :each do
31
- klass.stub(:new).and_return(pane_one, pane_two)
33
+ allow(klass).to receive(:new).and_return(pane_one, pane_two)
32
34
  end
33
35
 
34
36
  it "respects objects existing methods" do
35
- object.stub :foo => 'original'
37
+ allow(object).to receive_messages :foo => 'original'
36
38
 
37
- glaze.foo.should == 'original'
39
+ expect(glaze.foo).to eq('original')
38
40
  end
39
41
 
40
42
  it "uses the first pane that responds to the method" do
41
- glaze.foo.should == 'one'
42
- glaze.bar.should == 'two'
43
+ expect(glaze.foo).to eq('one')
44
+ expect(glaze.bar).to eq('two')
43
45
  end
44
46
 
45
47
  it "raises the method missing error otherwise" do
46
- object.stub :respond_to? => false
47
- object.stub(:baz).and_raise(NoMethodError)
48
+ allow(object).to receive_messages :respond_to? => false
49
+ allow(object).to receive(:baz).and_raise(NoMethodError)
48
50
 
49
- lambda { glaze.baz }.should raise_error(NoMethodError)
51
+ expect { glaze.baz }.to raise_error(NoMethodError)
50
52
  end
51
53
  end
52
54
 
53
55
  describe '#respond_to?' do
54
56
  it "responds to underlying object methods" do
55
- object.stub :foo => true
57
+ allow(object).to receive_messages :foo => true
56
58
 
57
- glaze.respond_to?(:foo).should be_true
59
+ expect(glaze.respond_to?(:foo)).to be_truthy
58
60
  end
59
61
 
60
62
  it "responds to underlying pane methods" do
61
63
  pane = double('Pane Class', :new => double('pane', :bar => true))
62
64
  glaze = ThinkingSphinx::Search::Glaze.new context, object, raw, [pane]
63
65
 
64
- glaze.respond_to?(:bar).should be_true
66
+ expect(glaze.respond_to?(:bar)).to be_truthy
65
67
  end
66
68
 
67
69
  it "does not to respond to methods that don't exist" do
68
- glaze.respond_to?(:something).should be_false
70
+ expect(glaze.respond_to?(:something)).to be_falsey
69
71
  end
70
72
  end
71
73
 
72
74
  describe '#unglazed' do
73
75
  it "returns the original object" do
74
- glaze.unglazed.should == object
76
+ expect(glaze.unglazed).to eq(object)
75
77
  end
76
78
  end
77
79
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ThinkingSphinx
2
4
  class Search; end
3
5
  end
@@ -14,30 +16,30 @@ describe ThinkingSphinx::Search::Query do
14
16
  it "passes through the keyword as provided" do
15
17
  query = ThinkingSphinx::Search::Query.new 'pancakes'
16
18
 
17
- query.to_s.should == 'pancakes'
19
+ expect(query.to_s).to eq('pancakes')
18
20
  end
19
21
 
20
22
  it "pairs fields and keywords for given conditions" do
21
23
  query = ThinkingSphinx::Search::Query.new '', :title => 'pancakes'
22
24
 
23
- query.to_s.should == '@title pancakes'
25
+ expect(query.to_s).to eq('@title pancakes')
24
26
  end
25
27
 
26
28
  it "combines both keywords and conditions" do
27
29
  query = ThinkingSphinx::Search::Query.new 'tasty', :title => 'pancakes'
28
30
 
29
- query.to_s.should == 'tasty @title pancakes'
31
+ expect(query.to_s).to eq('tasty @title pancakes')
30
32
  end
31
33
 
32
34
  it "automatically stars keywords if requested" do
33
- ThinkingSphinx::Query.should_receive(:wildcard).with('cake', true).
35
+ expect(ThinkingSphinx::Query).to receive(:wildcard).with('cake', true).
34
36
  and_return('*cake*')
35
37
 
36
38
  ThinkingSphinx::Search::Query.new('cake', {}, true).to_s
37
39
  end
38
40
 
39
41
  it "automatically stars condition keywords if requested" do
40
- ThinkingSphinx::Query.should_receive(:wildcard).with('pan', true).
42
+ expect(ThinkingSphinx::Query).to receive(:wildcard).with('pan', true).
41
43
  and_return('*pan*')
42
44
 
43
45
  ThinkingSphinx::Search::Query.new('', {:title => 'pan'}, true).to_s
@@ -47,32 +49,39 @@ describe ThinkingSphinx::Search::Query do
47
49
  query = ThinkingSphinx::Search::Query.new '',
48
50
  {:sphinx_internal_class_name => 'article'}, true
49
51
 
50
- query.to_s.should == '@sphinx_internal_class_name article'
52
+ expect(query.to_s).to eq('@sphinx_internal_class_name article')
51
53
  end
52
54
 
53
55
  it "handles null values by removing them from the conditions hash" do
54
56
  query = ThinkingSphinx::Search::Query.new '', :title => nil
55
57
 
56
- query.to_s.should == ''
58
+ expect(query.to_s).to eq('')
57
59
  end
58
60
 
59
61
  it "handles empty string values by removing them from the conditions hash" do
60
62
  query = ThinkingSphinx::Search::Query.new '', :title => ''
61
63
 
62
- query.to_s.should == ''
64
+ expect(query.to_s).to eq('')
63
65
  end
64
66
 
65
67
  it "handles nil queries" do
66
68
  query = ThinkingSphinx::Search::Query.new nil, {}
67
69
 
68
- query.to_s.should == ''
70
+ expect(query.to_s).to eq('')
69
71
  end
70
72
 
71
73
  it "allows mixing of blank and non-blank conditions" do
72
74
  query = ThinkingSphinx::Search::Query.new 'tasty', :title => 'pancakes',
73
75
  :ingredients => nil
74
76
 
75
- query.to_s.should == 'tasty @title pancakes'
77
+ expect(query.to_s).to eq('tasty @title pancakes')
78
+ end
79
+
80
+ it "handles multiple fields for a single condition" do
81
+ query = ThinkingSphinx::Search::Query.new '',
82
+ [:title, :content] => 'pancakes'
83
+
84
+ expect(query.to_s).to eq('@(title,content) pancakes')
76
85
  end
77
86
  end
78
87
  end