sequel 5.20.0 → 5.49.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 (511) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +398 -1922
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +7 -7
  5. data/doc/advanced_associations.rdoc +4 -4
  6. data/doc/association_basics.rdoc +80 -16
  7. data/doc/cheat_sheet.rdoc +6 -5
  8. data/doc/code_order.rdoc +10 -12
  9. data/doc/dataset_filtering.rdoc +17 -2
  10. data/doc/fork_safety.rdoc +84 -0
  11. data/doc/migration.rdoc +11 -5
  12. data/doc/model_dataset_method_design.rdoc +1 -1
  13. data/doc/model_plugins.rdoc +1 -1
  14. data/doc/opening_databases.rdoc +10 -2
  15. data/doc/postgresql.rdoc +82 -3
  16. data/doc/querying.rdoc +4 -4
  17. data/doc/release_notes/5.21.0.txt +87 -0
  18. data/doc/release_notes/5.22.0.txt +48 -0
  19. data/doc/release_notes/5.23.0.txt +56 -0
  20. data/doc/release_notes/5.24.0.txt +56 -0
  21. data/doc/release_notes/5.25.0.txt +32 -0
  22. data/doc/release_notes/5.26.0.txt +35 -0
  23. data/doc/release_notes/5.27.0.txt +21 -0
  24. data/doc/release_notes/5.28.0.txt +16 -0
  25. data/doc/release_notes/5.29.0.txt +22 -0
  26. data/doc/release_notes/5.30.0.txt +20 -0
  27. data/doc/release_notes/5.31.0.txt +148 -0
  28. data/doc/release_notes/5.32.0.txt +46 -0
  29. data/doc/release_notes/5.33.0.txt +24 -0
  30. data/doc/release_notes/5.34.0.txt +40 -0
  31. data/doc/release_notes/5.35.0.txt +56 -0
  32. data/doc/release_notes/5.36.0.txt +60 -0
  33. data/doc/release_notes/5.37.0.txt +30 -0
  34. data/doc/release_notes/5.38.0.txt +28 -0
  35. data/doc/release_notes/5.39.0.txt +19 -0
  36. data/doc/release_notes/5.40.0.txt +40 -0
  37. data/doc/release_notes/5.41.0.txt +25 -0
  38. data/doc/release_notes/5.42.0.txt +136 -0
  39. data/doc/release_notes/5.43.0.txt +98 -0
  40. data/doc/release_notes/5.44.0.txt +32 -0
  41. data/doc/release_notes/5.45.0.txt +34 -0
  42. data/doc/release_notes/5.46.0.txt +87 -0
  43. data/doc/release_notes/5.47.0.txt +59 -0
  44. data/doc/release_notes/5.48.0.txt +14 -0
  45. data/doc/release_notes/5.49.0.txt +59 -0
  46. data/doc/sharding.rdoc +2 -0
  47. data/doc/sql.rdoc +13 -1
  48. data/doc/testing.rdoc +20 -7
  49. data/doc/transactions.rdoc +0 -8
  50. data/doc/validations.rdoc +1 -1
  51. data/doc/virtual_rows.rdoc +1 -1
  52. data/lib/sequel/adapters/ado/access.rb +1 -1
  53. data/lib/sequel/adapters/ado.rb +43 -35
  54. data/lib/sequel/adapters/ibmdb.rb +2 -2
  55. data/lib/sequel/adapters/jdbc/mysql.rb +6 -6
  56. data/lib/sequel/adapters/jdbc/postgresql.rb +11 -17
  57. data/lib/sequel/adapters/jdbc/sqlite.rb +29 -0
  58. data/lib/sequel/adapters/jdbc.rb +24 -6
  59. data/lib/sequel/adapters/mysql.rb +1 -1
  60. data/lib/sequel/adapters/mysql2.rb +2 -3
  61. data/lib/sequel/adapters/odbc.rb +8 -6
  62. data/lib/sequel/adapters/oracle.rb +5 -4
  63. data/lib/sequel/adapters/postgres.rb +15 -9
  64. data/lib/sequel/adapters/shared/access.rb +6 -6
  65. data/lib/sequel/adapters/shared/mssql.rb +66 -21
  66. data/lib/sequel/adapters/shared/mysql.rb +27 -10
  67. data/lib/sequel/adapters/shared/oracle.rb +29 -23
  68. data/lib/sequel/adapters/shared/postgres.rb +271 -32
  69. data/lib/sequel/adapters/shared/sqlanywhere.rb +9 -9
  70. data/lib/sequel/adapters/shared/sqlite.rb +161 -19
  71. data/lib/sequel/adapters/sqlanywhere.rb +1 -1
  72. data/lib/sequel/adapters/sqlite.rb +1 -1
  73. data/lib/sequel/adapters/tinytds.rb +15 -2
  74. data/lib/sequel/adapters/utils/mysql_mysql2.rb +4 -1
  75. data/lib/sequel/ast_transformer.rb +6 -0
  76. data/lib/sequel/connection_pool/sharded_single.rb +4 -1
  77. data/lib/sequel/connection_pool/sharded_threaded.rb +12 -12
  78. data/lib/sequel/connection_pool/single.rb +1 -1
  79. data/lib/sequel/connection_pool/threaded.rb +2 -2
  80. data/lib/sequel/core.rb +333 -319
  81. data/lib/sequel/database/connecting.rb +3 -4
  82. data/lib/sequel/database/logging.rb +7 -1
  83. data/lib/sequel/database/misc.rb +31 -12
  84. data/lib/sequel/database/query.rb +3 -1
  85. data/lib/sequel/database/schema_generator.rb +53 -51
  86. data/lib/sequel/database/schema_methods.rb +38 -23
  87. data/lib/sequel/database/transactions.rb +17 -18
  88. data/lib/sequel/dataset/actions.rb +14 -9
  89. data/lib/sequel/dataset/features.rb +16 -0
  90. data/lib/sequel/dataset/misc.rb +2 -2
  91. data/lib/sequel/dataset/placeholder_literalizer.rb +3 -7
  92. data/lib/sequel/dataset/prepared_statements.rb +2 -0
  93. data/lib/sequel/dataset/query.rb +26 -9
  94. data/lib/sequel/dataset/sql.rb +76 -25
  95. data/lib/sequel/dataset.rb +4 -2
  96. data/lib/sequel/deprecated.rb +3 -1
  97. data/lib/sequel/exceptions.rb +2 -0
  98. data/lib/sequel/extensions/_pretty_table.rb +1 -2
  99. data/lib/sequel/extensions/any_not_empty.rb +45 -0
  100. data/lib/sequel/extensions/async_thread_pool.rb +438 -0
  101. data/lib/sequel/extensions/blank.rb +8 -0
  102. data/lib/sequel/extensions/columns_introspection.rb +1 -2
  103. data/lib/sequel/extensions/connection_expiration.rb +2 -2
  104. data/lib/sequel/extensions/connection_validator.rb +2 -2
  105. data/lib/sequel/extensions/core_refinements.rb +2 -0
  106. data/lib/sequel/extensions/date_arithmetic.rb +36 -24
  107. data/lib/sequel/extensions/duplicate_columns_handler.rb +3 -1
  108. data/lib/sequel/extensions/eval_inspect.rb +2 -0
  109. data/lib/sequel/extensions/exclude_or_null.rb +68 -0
  110. data/lib/sequel/extensions/fiber_concurrency.rb +24 -0
  111. data/lib/sequel/extensions/index_caching.rb +9 -7
  112. data/lib/sequel/extensions/inflector.rb +9 -1
  113. data/lib/sequel/extensions/integer64.rb +2 -0
  114. data/lib/sequel/extensions/migration.rb +11 -3
  115. data/lib/sequel/extensions/named_timezones.rb +56 -8
  116. data/lib/sequel/extensions/pagination.rb +1 -1
  117. data/lib/sequel/extensions/pg_array.rb +5 -0
  118. data/lib/sequel/extensions/pg_array_ops.rb +14 -6
  119. data/lib/sequel/extensions/pg_enum.rb +11 -3
  120. data/lib/sequel/extensions/pg_extended_date_support.rb +2 -2
  121. data/lib/sequel/extensions/pg_hstore.rb +6 -0
  122. data/lib/sequel/extensions/pg_hstore_ops.rb +54 -2
  123. data/lib/sequel/extensions/pg_inet.rb +15 -5
  124. data/lib/sequel/extensions/pg_interval.rb +36 -8
  125. data/lib/sequel/extensions/pg_json.rb +387 -123
  126. data/lib/sequel/extensions/pg_json_ops.rb +238 -0
  127. data/lib/sequel/extensions/pg_loose_count.rb +3 -1
  128. data/lib/sequel/extensions/pg_range.rb +17 -9
  129. data/lib/sequel/extensions/pg_range_ops.rb +2 -0
  130. data/lib/sequel/extensions/pg_row.rb +4 -2
  131. data/lib/sequel/extensions/pg_row_ops.rb +24 -0
  132. data/lib/sequel/extensions/pg_timestamptz.rb +2 -0
  133. data/lib/sequel/extensions/query.rb +3 -0
  134. data/lib/sequel/extensions/run_transaction_hooks.rb +72 -0
  135. data/lib/sequel/extensions/s.rb +2 -0
  136. data/lib/sequel/extensions/schema_dumper.rb +24 -7
  137. data/lib/sequel/extensions/server_block.rb +18 -7
  138. data/lib/sequel/extensions/sql_comments.rb +2 -2
  139. data/lib/sequel/extensions/string_agg.rb +1 -1
  140. data/lib/sequel/extensions/symbol_aref_refinement.rb +2 -0
  141. data/lib/sequel/extensions/symbol_as_refinement.rb +2 -0
  142. data/lib/sequel/extensions/to_dot.rb +9 -3
  143. data/lib/sequel/model/associations.rb +356 -117
  144. data/lib/sequel/model/base.rb +107 -68
  145. data/lib/sequel/model/errors.rb +10 -1
  146. data/lib/sequel/model/inflections.rb +1 -1
  147. data/lib/sequel/model/plugins.rb +9 -3
  148. data/lib/sequel/model.rb +3 -1
  149. data/lib/sequel/plugins/association_lazy_eager_option.rb +66 -0
  150. data/lib/sequel/plugins/association_multi_add_remove.rb +85 -0
  151. data/lib/sequel/plugins/association_pks.rb +60 -18
  152. data/lib/sequel/plugins/association_proxies.rb +8 -2
  153. data/lib/sequel/plugins/async_thread_pool.rb +39 -0
  154. data/lib/sequel/plugins/auto_validations.rb +39 -5
  155. data/lib/sequel/plugins/auto_validations_constraint_validations_presence_message.rb +68 -0
  156. data/lib/sequel/plugins/blacklist_security.rb +1 -2
  157. data/lib/sequel/plugins/boolean_subsets.rb +4 -1
  158. data/lib/sequel/plugins/caching.rb +3 -0
  159. data/lib/sequel/plugins/class_table_inheritance.rb +33 -28
  160. data/lib/sequel/plugins/column_encryption.rb +728 -0
  161. data/lib/sequel/plugins/composition.rb +7 -2
  162. data/lib/sequel/plugins/concurrent_eager_loading.rb +174 -0
  163. data/lib/sequel/plugins/constraint_validations.rb +2 -1
  164. data/lib/sequel/plugins/csv_serializer.rb +28 -9
  165. data/lib/sequel/plugins/dataset_associations.rb +4 -1
  166. data/lib/sequel/plugins/dirty.rb +60 -22
  167. data/lib/sequel/plugins/empty_failure_backtraces.rb +38 -0
  168. data/lib/sequel/plugins/forbid_lazy_load.rb +216 -0
  169. data/lib/sequel/plugins/insert_conflict.rb +72 -0
  170. data/lib/sequel/plugins/instance_specific_default.rb +113 -0
  171. data/lib/sequel/plugins/json_serializer.rb +57 -35
  172. data/lib/sequel/plugins/lazy_attributes.rb +1 -1
  173. data/lib/sequel/plugins/many_through_many.rb +108 -9
  174. data/lib/sequel/plugins/nested_attributes.rb +15 -3
  175. data/lib/sequel/plugins/pg_array_associations.rb +58 -41
  176. data/lib/sequel/plugins/pg_auto_constraint_validations.rb +91 -30
  177. data/lib/sequel/plugins/prepared_statements.rb +15 -12
  178. data/lib/sequel/plugins/prepared_statements_safe.rb +1 -3
  179. data/lib/sequel/plugins/rcte_tree.rb +43 -35
  180. data/lib/sequel/plugins/serialization.rb +8 -3
  181. data/lib/sequel/plugins/serialization_modification_detection.rb +1 -1
  182. data/lib/sequel/plugins/sharding.rb +11 -5
  183. data/lib/sequel/plugins/single_table_inheritance.rb +22 -15
  184. data/lib/sequel/plugins/skip_saving_columns.rb +108 -0
  185. data/lib/sequel/plugins/static_cache.rb +9 -4
  186. data/lib/sequel/plugins/static_cache_cache.rb +53 -0
  187. data/lib/sequel/plugins/string_stripper.rb +1 -1
  188. data/lib/sequel/plugins/subclasses.rb +2 -0
  189. data/lib/sequel/plugins/throw_failures.rb +1 -1
  190. data/lib/sequel/plugins/timestamps.rb +1 -1
  191. data/lib/sequel/plugins/tree.rb +9 -4
  192. data/lib/sequel/plugins/typecast_on_load.rb +3 -2
  193. data/lib/sequel/plugins/unused_associations.rb +521 -0
  194. data/lib/sequel/plugins/update_or_create.rb +1 -1
  195. data/lib/sequel/plugins/validation_class_methods.rb +5 -1
  196. data/lib/sequel/plugins/validation_helpers.rb +18 -11
  197. data/lib/sequel/plugins/xml_serializer.rb +1 -1
  198. data/lib/sequel/sql.rb +20 -5
  199. data/lib/sequel/timezones.rb +63 -17
  200. data/lib/sequel/version.rb +1 -1
  201. metadata +113 -381
  202. data/Rakefile +0 -151
  203. data/doc/release_notes/4.0.0.txt +0 -262
  204. data/doc/release_notes/4.1.0.txt +0 -85
  205. data/doc/release_notes/4.10.0.txt +0 -226
  206. data/doc/release_notes/4.11.0.txt +0 -147
  207. data/doc/release_notes/4.12.0.txt +0 -105
  208. data/doc/release_notes/4.13.0.txt +0 -169
  209. data/doc/release_notes/4.14.0.txt +0 -68
  210. data/doc/release_notes/4.15.0.txt +0 -56
  211. data/doc/release_notes/4.16.0.txt +0 -36
  212. data/doc/release_notes/4.17.0.txt +0 -38
  213. data/doc/release_notes/4.18.0.txt +0 -36
  214. data/doc/release_notes/4.19.0.txt +0 -45
  215. data/doc/release_notes/4.2.0.txt +0 -129
  216. data/doc/release_notes/4.20.0.txt +0 -79
  217. data/doc/release_notes/4.21.0.txt +0 -94
  218. data/doc/release_notes/4.22.0.txt +0 -72
  219. data/doc/release_notes/4.23.0.txt +0 -65
  220. data/doc/release_notes/4.24.0.txt +0 -99
  221. data/doc/release_notes/4.25.0.txt +0 -181
  222. data/doc/release_notes/4.26.0.txt +0 -44
  223. data/doc/release_notes/4.27.0.txt +0 -78
  224. data/doc/release_notes/4.28.0.txt +0 -57
  225. data/doc/release_notes/4.29.0.txt +0 -41
  226. data/doc/release_notes/4.3.0.txt +0 -40
  227. data/doc/release_notes/4.30.0.txt +0 -37
  228. data/doc/release_notes/4.31.0.txt +0 -57
  229. data/doc/release_notes/4.32.0.txt +0 -132
  230. data/doc/release_notes/4.33.0.txt +0 -88
  231. data/doc/release_notes/4.34.0.txt +0 -86
  232. data/doc/release_notes/4.35.0.txt +0 -130
  233. data/doc/release_notes/4.36.0.txt +0 -116
  234. data/doc/release_notes/4.37.0.txt +0 -50
  235. data/doc/release_notes/4.38.0.txt +0 -67
  236. data/doc/release_notes/4.39.0.txt +0 -127
  237. data/doc/release_notes/4.4.0.txt +0 -92
  238. data/doc/release_notes/4.40.0.txt +0 -179
  239. data/doc/release_notes/4.41.0.txt +0 -77
  240. data/doc/release_notes/4.42.0.txt +0 -221
  241. data/doc/release_notes/4.43.0.txt +0 -87
  242. data/doc/release_notes/4.44.0.txt +0 -125
  243. data/doc/release_notes/4.45.0.txt +0 -370
  244. data/doc/release_notes/4.46.0.txt +0 -404
  245. data/doc/release_notes/4.47.0.txt +0 -56
  246. data/doc/release_notes/4.48.0.txt +0 -293
  247. data/doc/release_notes/4.49.0.txt +0 -222
  248. data/doc/release_notes/4.5.0.txt +0 -34
  249. data/doc/release_notes/4.6.0.txt +0 -30
  250. data/doc/release_notes/4.7.0.txt +0 -103
  251. data/doc/release_notes/4.8.0.txt +0 -175
  252. data/doc/release_notes/4.9.0.txt +0 -190
  253. data/spec/adapter_spec.rb +0 -4
  254. data/spec/adapters/db2_spec.rb +0 -170
  255. data/spec/adapters/mssql_spec.rb +0 -804
  256. data/spec/adapters/mysql_spec.rb +0 -1065
  257. data/spec/adapters/oracle_spec.rb +0 -371
  258. data/spec/adapters/postgres_spec.rb +0 -4125
  259. data/spec/adapters/spec_helper.rb +0 -44
  260. data/spec/adapters/sqlanywhere_spec.rb +0 -97
  261. data/spec/adapters/sqlite_spec.rb +0 -652
  262. data/spec/bin_spec.rb +0 -278
  263. data/spec/core/connection_pool_spec.rb +0 -1250
  264. data/spec/core/database_spec.rb +0 -2865
  265. data/spec/core/dataset_spec.rb +0 -5515
  266. data/spec/core/deprecated_spec.rb +0 -70
  267. data/spec/core/expression_filters_spec.rb +0 -1455
  268. data/spec/core/mock_adapter_spec.rb +0 -722
  269. data/spec/core/object_graph_spec.rb +0 -336
  270. data/spec/core/placeholder_literalizer_spec.rb +0 -166
  271. data/spec/core/schema_generator_spec.rb +0 -214
  272. data/spec/core/schema_spec.rb +0 -1826
  273. data/spec/core/spec_helper.rb +0 -24
  274. data/spec/core/version_spec.rb +0 -14
  275. data/spec/core_extensions_spec.rb +0 -763
  276. data/spec/core_model_spec.rb +0 -2
  277. data/spec/core_spec.rb +0 -1
  278. data/spec/deprecation_helper.rb +0 -30
  279. data/spec/extensions/accessed_columns_spec.rb +0 -51
  280. data/spec/extensions/active_model_spec.rb +0 -99
  281. data/spec/extensions/after_initialize_spec.rb +0 -28
  282. data/spec/extensions/arbitrary_servers_spec.rb +0 -109
  283. data/spec/extensions/association_dependencies_spec.rb +0 -125
  284. data/spec/extensions/association_pks_spec.rb +0 -423
  285. data/spec/extensions/association_proxies_spec.rb +0 -100
  286. data/spec/extensions/auto_literal_strings_spec.rb +0 -205
  287. data/spec/extensions/auto_validations_spec.rb +0 -229
  288. data/spec/extensions/blacklist_security_spec.rb +0 -95
  289. data/spec/extensions/blank_spec.rb +0 -69
  290. data/spec/extensions/boolean_readers_spec.rb +0 -93
  291. data/spec/extensions/boolean_subsets_spec.rb +0 -47
  292. data/spec/extensions/caching_spec.rb +0 -273
  293. data/spec/extensions/caller_logging_spec.rb +0 -52
  294. data/spec/extensions/class_table_inheritance_spec.rb +0 -750
  295. data/spec/extensions/column_conflicts_spec.rb +0 -75
  296. data/spec/extensions/column_select_spec.rb +0 -129
  297. data/spec/extensions/columns_introspection_spec.rb +0 -90
  298. data/spec/extensions/columns_updated_spec.rb +0 -35
  299. data/spec/extensions/composition_spec.rb +0 -248
  300. data/spec/extensions/connection_expiration_spec.rb +0 -151
  301. data/spec/extensions/connection_validator_spec.rb +0 -144
  302. data/spec/extensions/constant_sql_override_spec.rb +0 -24
  303. data/spec/extensions/constraint_validations_plugin_spec.rb +0 -300
  304. data/spec/extensions/constraint_validations_spec.rb +0 -439
  305. data/spec/extensions/core_refinements_spec.rb +0 -528
  306. data/spec/extensions/csv_serializer_spec.rb +0 -183
  307. data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
  308. data/spec/extensions/dataset_associations_spec.rb +0 -365
  309. data/spec/extensions/dataset_source_alias_spec.rb +0 -51
  310. data/spec/extensions/date_arithmetic_spec.rb +0 -181
  311. data/spec/extensions/datetime_parse_to_time_spec.rb +0 -169
  312. data/spec/extensions/def_dataset_method_spec.rb +0 -100
  313. data/spec/extensions/defaults_setter_spec.rb +0 -150
  314. data/spec/extensions/delay_add_association_spec.rb +0 -73
  315. data/spec/extensions/dirty_spec.rb +0 -189
  316. data/spec/extensions/duplicate_columns_handler_spec.rb +0 -104
  317. data/spec/extensions/eager_each_spec.rb +0 -62
  318. data/spec/extensions/eager_graph_eager_spec.rb +0 -100
  319. data/spec/extensions/empty_array_consider_nulls_spec.rb +0 -24
  320. data/spec/extensions/error_splitter_spec.rb +0 -18
  321. data/spec/extensions/error_sql_spec.rb +0 -20
  322. data/spec/extensions/escaped_like_spec.rb +0 -40
  323. data/spec/extensions/eval_inspect_spec.rb +0 -81
  324. data/spec/extensions/finder_spec.rb +0 -260
  325. data/spec/extensions/force_encoding_spec.rb +0 -126
  326. data/spec/extensions/freeze_datasets_spec.rb +0 -31
  327. data/spec/extensions/graph_each_spec.rb +0 -113
  328. data/spec/extensions/hook_class_methods_spec.rb +0 -402
  329. data/spec/extensions/identifier_mangling_spec.rb +0 -201
  330. data/spec/extensions/implicit_subquery_spec.rb +0 -58
  331. data/spec/extensions/index_caching_spec.rb +0 -66
  332. data/spec/extensions/inflector_spec.rb +0 -183
  333. data/spec/extensions/input_transformer_spec.rb +0 -69
  334. data/spec/extensions/insert_returning_select_spec.rb +0 -72
  335. data/spec/extensions/instance_filters_spec.rb +0 -79
  336. data/spec/extensions/instance_hooks_spec.rb +0 -246
  337. data/spec/extensions/integer64_spec.rb +0 -22
  338. data/spec/extensions/inverted_subsets_spec.rb +0 -33
  339. data/spec/extensions/json_serializer_spec.rb +0 -336
  340. data/spec/extensions/lazy_attributes_spec.rb +0 -183
  341. data/spec/extensions/list_spec.rb +0 -291
  342. data/spec/extensions/looser_typecasting_spec.rb +0 -43
  343. data/spec/extensions/many_through_many_spec.rb +0 -2177
  344. data/spec/extensions/migration_spec.rb +0 -864
  345. data/spec/extensions/modification_detection_spec.rb +0 -93
  346. data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -92
  347. data/spec/extensions/named_timezones_spec.rb +0 -111
  348. data/spec/extensions/nested_attributes_spec.rb +0 -767
  349. data/spec/extensions/null_dataset_spec.rb +0 -85
  350. data/spec/extensions/optimistic_locking_spec.rb +0 -127
  351. data/spec/extensions/pagination_spec.rb +0 -116
  352. data/spec/extensions/pg_array_associations_spec.rb +0 -802
  353. data/spec/extensions/pg_array_ops_spec.rb +0 -144
  354. data/spec/extensions/pg_array_spec.rb +0 -398
  355. data/spec/extensions/pg_auto_constraint_validations_spec.rb +0 -172
  356. data/spec/extensions/pg_enum_spec.rb +0 -118
  357. data/spec/extensions/pg_extended_date_support_spec.rb +0 -126
  358. data/spec/extensions/pg_hstore_ops_spec.rb +0 -238
  359. data/spec/extensions/pg_hstore_spec.rb +0 -219
  360. data/spec/extensions/pg_inet_ops_spec.rb +0 -102
  361. data/spec/extensions/pg_inet_spec.rb +0 -72
  362. data/spec/extensions/pg_interval_spec.rb +0 -103
  363. data/spec/extensions/pg_json_ops_spec.rb +0 -289
  364. data/spec/extensions/pg_json_spec.rb +0 -262
  365. data/spec/extensions/pg_loose_count_spec.rb +0 -23
  366. data/spec/extensions/pg_range_ops_spec.rb +0 -60
  367. data/spec/extensions/pg_range_spec.rb +0 -519
  368. data/spec/extensions/pg_row_ops_spec.rb +0 -61
  369. data/spec/extensions/pg_row_plugin_spec.rb +0 -60
  370. data/spec/extensions/pg_row_spec.rb +0 -363
  371. data/spec/extensions/pg_static_cache_updater_spec.rb +0 -93
  372. data/spec/extensions/pg_timestamptz_spec.rb +0 -17
  373. data/spec/extensions/prepared_statements_safe_spec.rb +0 -66
  374. data/spec/extensions/prepared_statements_spec.rb +0 -177
  375. data/spec/extensions/pretty_table_spec.rb +0 -123
  376. data/spec/extensions/query_spec.rb +0 -94
  377. data/spec/extensions/rcte_tree_spec.rb +0 -381
  378. data/spec/extensions/round_timestamps_spec.rb +0 -39
  379. data/spec/extensions/s_spec.rb +0 -60
  380. data/spec/extensions/schema_caching_spec.rb +0 -64
  381. data/spec/extensions/schema_dumper_spec.rb +0 -870
  382. data/spec/extensions/select_remove_spec.rb +0 -38
  383. data/spec/extensions/sequel_4_dataset_methods_spec.rb +0 -121
  384. data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
  385. data/spec/extensions/serialization_spec.rb +0 -365
  386. data/spec/extensions/server_block_spec.rb +0 -97
  387. data/spec/extensions/server_logging_spec.rb +0 -45
  388. data/spec/extensions/sharding_spec.rb +0 -189
  389. data/spec/extensions/shared_caching_spec.rb +0 -151
  390. data/spec/extensions/single_table_inheritance_spec.rb +0 -347
  391. data/spec/extensions/singular_table_names_spec.rb +0 -22
  392. data/spec/extensions/skip_create_refresh_spec.rb +0 -18
  393. data/spec/extensions/spec_helper.rb +0 -63
  394. data/spec/extensions/split_array_nil_spec.rb +0 -24
  395. data/spec/extensions/split_values_spec.rb +0 -57
  396. data/spec/extensions/sql_comments_spec.rb +0 -33
  397. data/spec/extensions/sql_expr_spec.rb +0 -59
  398. data/spec/extensions/static_cache_spec.rb +0 -471
  399. data/spec/extensions/string_agg_spec.rb +0 -90
  400. data/spec/extensions/string_date_time_spec.rb +0 -95
  401. data/spec/extensions/string_stripper_spec.rb +0 -68
  402. data/spec/extensions/subclasses_spec.rb +0 -79
  403. data/spec/extensions/subset_conditions_spec.rb +0 -38
  404. data/spec/extensions/symbol_aref_refinement_spec.rb +0 -28
  405. data/spec/extensions/symbol_as_refinement_spec.rb +0 -21
  406. data/spec/extensions/synchronize_sql_spec.rb +0 -124
  407. data/spec/extensions/table_select_spec.rb +0 -83
  408. data/spec/extensions/tactical_eager_loading_spec.rb +0 -402
  409. data/spec/extensions/thread_local_timezones_spec.rb +0 -67
  410. data/spec/extensions/throw_failures_spec.rb +0 -74
  411. data/spec/extensions/timestamps_spec.rb +0 -209
  412. data/spec/extensions/to_dot_spec.rb +0 -153
  413. data/spec/extensions/touch_spec.rb +0 -226
  414. data/spec/extensions/tree_spec.rb +0 -334
  415. data/spec/extensions/typecast_on_load_spec.rb +0 -86
  416. data/spec/extensions/unlimited_update_spec.rb +0 -21
  417. data/spec/extensions/update_or_create_spec.rb +0 -83
  418. data/spec/extensions/update_primary_key_spec.rb +0 -105
  419. data/spec/extensions/update_refresh_spec.rb +0 -59
  420. data/spec/extensions/uuid_spec.rb +0 -101
  421. data/spec/extensions/validate_associated_spec.rb +0 -52
  422. data/spec/extensions/validation_class_methods_spec.rb +0 -1040
  423. data/spec/extensions/validation_contexts_spec.rb +0 -31
  424. data/spec/extensions/validation_helpers_spec.rb +0 -525
  425. data/spec/extensions/whitelist_security_spec.rb +0 -157
  426. data/spec/extensions/xml_serializer_spec.rb +0 -213
  427. data/spec/files/bad_down_migration/001_create_alt_basic.rb +0 -4
  428. data/spec/files/bad_down_migration/002_create_alt_advanced.rb +0 -4
  429. data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  430. data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  431. data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +0 -3
  432. data/spec/files/bad_up_migration/001_create_alt_basic.rb +0 -4
  433. data/spec/files/bad_up_migration/002_create_alt_advanced.rb +0 -3
  434. data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +0 -9
  435. data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +0 -9
  436. data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +0 -4
  437. data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +0 -9
  438. data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +0 -9
  439. data/spec/files/double_migration/001_create_sessions.rb +0 -9
  440. data/spec/files/double_migration/002_create_nodes.rb +0 -19
  441. data/spec/files/double_migration/003_3_create_users.rb +0 -4
  442. data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +0 -4
  443. data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +0 -4
  444. data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  445. data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +0 -9
  446. data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +0 -4
  447. data/spec/files/empty_migration/001_create_sessions.rb +0 -9
  448. data/spec/files/empty_migration/002_create_nodes.rb +0 -0
  449. data/spec/files/empty_migration/003_3_create_users.rb +0 -4
  450. data/spec/files/integer_migrations/001_create_sessions.rb +0 -9
  451. data/spec/files/integer_migrations/002_create_nodes.rb +0 -9
  452. data/spec/files/integer_migrations/003_3_create_users.rb +0 -4
  453. data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  454. data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +0 -9
  455. data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  456. data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +0 -9
  457. data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  458. data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +0 -4
  459. data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +0 -4
  460. data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  461. data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  462. data/spec/files/reversible_migrations/001_reversible.rb +0 -5
  463. data/spec/files/reversible_migrations/002_reversible.rb +0 -5
  464. data/spec/files/reversible_migrations/003_reversible.rb +0 -5
  465. data/spec/files/reversible_migrations/004_reversible.rb +0 -5
  466. data/spec/files/reversible_migrations/005_reversible.rb +0 -10
  467. data/spec/files/reversible_migrations/006_reversible.rb +0 -10
  468. data/spec/files/reversible_migrations/007_reversible.rb +0 -10
  469. data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +0 -9
  470. data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +0 -9
  471. data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +0 -4
  472. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +0 -4
  473. data/spec/files/transaction_specified_migrations/002_create_basic.rb +0 -4
  474. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +0 -3
  475. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +0 -3
  476. data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +0 -9
  477. data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +0 -9
  478. data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +0 -4
  479. data/spec/guards_helper.rb +0 -59
  480. data/spec/integration/associations_test.rb +0 -2597
  481. data/spec/integration/database_test.rb +0 -113
  482. data/spec/integration/dataset_test.rb +0 -1981
  483. data/spec/integration/eager_loader_test.rb +0 -687
  484. data/spec/integration/migrator_test.rb +0 -262
  485. data/spec/integration/model_test.rb +0 -203
  486. data/spec/integration/plugin_test.rb +0 -2396
  487. data/spec/integration/prepared_statement_test.rb +0 -405
  488. data/spec/integration/schema_test.rb +0 -889
  489. data/spec/integration/spec_helper.rb +0 -65
  490. data/spec/integration/timezone_test.rb +0 -86
  491. data/spec/integration/transaction_test.rb +0 -603
  492. data/spec/integration/type_test.rb +0 -127
  493. data/spec/model/association_reflection_spec.rb +0 -803
  494. data/spec/model/associations_spec.rb +0 -4738
  495. data/spec/model/base_spec.rb +0 -875
  496. data/spec/model/class_dataset_methods_spec.rb +0 -146
  497. data/spec/model/dataset_methods_spec.rb +0 -198
  498. data/spec/model/eager_loading_spec.rb +0 -2377
  499. data/spec/model/hooks_spec.rb +0 -370
  500. data/spec/model/inflector_spec.rb +0 -26
  501. data/spec/model/model_spec.rb +0 -956
  502. data/spec/model/plugins_spec.rb +0 -429
  503. data/spec/model/record_spec.rb +0 -2118
  504. data/spec/model/spec_helper.rb +0 -46
  505. data/spec/model/validations_spec.rb +0 -220
  506. data/spec/model_no_assoc_spec.rb +0 -1
  507. data/spec/model_spec.rb +0 -1
  508. data/spec/plugin_spec.rb +0 -1
  509. data/spec/sequel_coverage.rb +0 -15
  510. data/spec/sequel_warning.rb +0 -4
  511. data/spec/spec_config.rb +0 -12
@@ -1,2396 +0,0 @@
1
- require_relative "spec_helper"
2
-
3
- describe "Class Table Inheritance Plugin" do
4
- before(:all) do
5
- @db = DB
6
- @db.instance_variable_get(:@schemas).clear
7
- @db.drop_table?(:staff, :executives, :managers, :employees)
8
- @db.create_table(:employees) do
9
- primary_key :id
10
- String :name
11
- String :kind
12
- end
13
- @db.create_table(:managers) do
14
- foreign_key :id, :employees, :primary_key=>true
15
- Integer :num_staff
16
- end
17
- @db.create_table(:executives) do
18
- foreign_key :id, :managers, :primary_key=>true
19
- Integer :num_managers
20
- end
21
- @db.create_table(:staff) do
22
- foreign_key :id, :employees, :primary_key=>true
23
- foreign_key :manager_id, :managers
24
- end
25
- end
26
- before do
27
- [:staff, :executives, :managers, :employees].each{|t| @db[t].delete}
28
- class ::Employee < Sequel::Model(@db)
29
- plugin :class_table_inheritance, :key=>:kind, :table_map=>{:Staff=>:staff}
30
- end
31
- class ::Manager < Employee
32
- one_to_many :staff_members, :class=>:Staff
33
- one_to_one :first_staff_member, :clone=>:staff_members, :order=>:id
34
- end
35
- class ::Executive < Manager
36
- end
37
- class ::Ceo < Executive
38
- end
39
- class ::Staff < Employee
40
- many_to_one :manager
41
- end
42
- class ::Intern < Employee
43
- end
44
-
45
- @i1 = @db[:employees].insert(:name=>'E', :kind=>'Employee')
46
- @i2 = @db[:employees].insert(:name=>'S', :kind=>'Staff')
47
- @i3 = @db[:employees].insert(:name=>'M', :kind=>'Manager')
48
- @db[:managers].insert(:id=>@i3, :num_staff=>7)
49
- @i4 = @db[:employees].insert(:name=>'Ex', :kind=>'Executive')
50
- @db[:managers].insert(:id=>@i4, :num_staff=>5)
51
- @db[:executives].insert(:id=>@i4, :num_managers=>6)
52
- @i5 = @db[:employees].insert(:name=>'C', :kind=>'Ceo')
53
- @db[:managers].insert(:id=>@i5, :num_staff=>2)
54
- @db[:executives].insert(:id=>@i5, :num_managers=>1)
55
- @db[:staff].insert(:id=>@i2, :manager_id=>@i4)
56
- @i6 = @db[:employees].insert(:name=>'I', :kind=>'Intern')
57
- end
58
- after do
59
- [:Intern, :Ceo, :Executive, :Manager, :Staff, :Employee].each{|s| Object.send(:remove_const, s)}
60
- end
61
- after(:all) do
62
- @db.drop_table? :staff, :executives, :managers, :employees
63
- end
64
-
65
- it "should return rows as subclass instances" do
66
- Employee.order(:id).all.must_equal [
67
- Employee.load(:id=>@i1, :name=>'E', :kind=>'Employee'),
68
- Staff.load(:id=>@i2, :name=>'S', :kind=>'Staff'),
69
- Manager.load(:id=>@i3, :name=>'M', :kind=>'Manager'),
70
- Executive.load(:id=>@i4, :name=>'Ex', :kind=>'Executive'),
71
- Ceo.load(:id=>@i5, :name=>'C', :kind=>'Ceo'),
72
- Intern.load(:id=>@i6, :name=>'I', :kind=>'Intern'),
73
- ]
74
- end
75
-
76
- it "should lazily load columns in subclass tables" do
77
- Employee[@i2][:manager_id].must_be_nil
78
- Employee[@i2].manager_id.must_equal @i4
79
- Employee[@i3][:num_staff].must_be_nil
80
- Employee[@i3].num_staff.must_equal 7
81
- Employee[@i4][:num_staff].must_be_nil
82
- Employee[@i4].num_staff.must_equal 5
83
- Employee[@i4][:num_managers].must_be_nil
84
- Employee[@i4].num_managers.must_equal 6
85
- Employee[@i5][:num_managers].must_be_nil
86
- Employee[@i5].num_managers.must_equal 1
87
- end
88
-
89
- it "should eagerly load columns in subclass tables when retrieving multiple objects" do
90
- a = Employee.order(:id).all
91
- a[1][:manager_id].must_be_nil
92
- a[1].manager_id.must_equal @i4
93
- a[2][:num_staff].must_be_nil
94
- a[2].num_staff.must_equal 7
95
- a[3][:num_staff].must_equal 5 # eagerly loaded by previous call
96
- a[3].num_staff.must_equal 5
97
- a[3][:num_managers].must_be_nil
98
- a[3].num_managers.must_equal 6
99
- a[4][:num_managers].must_equal 1
100
- a[4].num_managers.must_equal 1
101
- end
102
-
103
- it "should include schema for columns for tables for ancestor classes" do
104
- Employee.db_schema.keys.sort_by{|x| x.to_s}.must_equal [:id, :kind, :name]
105
- Staff.db_schema.keys.sort_by{|x| x.to_s}.must_equal [:id, :kind, :manager_id, :name]
106
- Manager.db_schema.keys.sort_by{|x| x.to_s}.must_equal [:id, :kind, :name, :num_staff]
107
- Executive.db_schema.keys.sort_by{|x| x.to_s}.must_equal [:id, :kind, :name, :num_managers, :num_staff]
108
- Ceo.db_schema.keys.sort_by{|x| x.to_s}.must_equal [:id, :kind, :name, :num_managers, :num_staff]
109
- Intern.db_schema.keys.sort_by{|x| x.to_s}.must_equal [:id, :kind, :name]
110
- end
111
-
112
- it "should include columns for tables for ancestor classes" do
113
- Employee.columns.must_equal [:id, :name, :kind]
114
- Staff.columns.must_equal [:id, :name, :kind, :manager_id]
115
- Manager.columns.must_equal [:id, :name, :kind, :num_staff]
116
- Executive.columns.must_equal [:id, :name, :kind, :num_staff, :num_managers]
117
- Ceo.columns.must_equal [:id, :name, :kind, :num_staff, :num_managers]
118
- Intern.columns.must_equal [:id, :name, :kind]
119
- end
120
-
121
- it "should delete rows from all tables" do
122
- e = Ceo.first
123
- i = e.id
124
- e.staff_members_dataset.destroy
125
- e.destroy
126
- @db[:executives][:id=>i].must_be_nil
127
- @db[:managers][:id=>i].must_be_nil
128
- @db[:employees][:id=>i].must_be_nil
129
- end
130
-
131
- it "should handle associations only defined in subclasses" do
132
- Employee.filter(Sequel[:employees][:id]=>@i2).all.first.manager.id.must_equal @i4
133
- end
134
-
135
- it "should insert rows into all tables" do
136
- e = Ceo.create(:name=>'Ex2', :num_managers=>8, :num_staff=>9)
137
- i = e.id
138
- @db[:employees][:id=>i].must_equal(:id=>i, :name=>'Ex2', :kind=>'Ceo')
139
- @db[:managers][:id=>i].must_equal(:id=>i, :num_staff=>9)
140
- @db[:executives][:id=>i].must_equal(:id=>i, :num_managers=>8)
141
- end
142
-
143
- it "should update rows in all tables" do
144
- Executive[:id=>@i4].update(:name=>'Ex2', :num_managers=>8, :num_staff=>9)
145
- @db[:employees][:id=>@i4].must_equal(:id=>@i4, :name=>'Ex2', :kind=>'Executive')
146
- @db[:managers][:id=>@i4].must_equal(:id=>@i4, :num_staff=>9)
147
- @db[:executives][:id=>@i4].must_equal(:id=>@i4, :num_managers=>8)
148
- end
149
-
150
- it "should handle many_to_one relationships" do
151
- m = Staff.first.manager
152
- m.must_equal Manager[@i4]
153
- m.must_be_kind_of(Executive)
154
- Staff.first.update(:manager => Manager[@i3])
155
- Staff.first.manager.must_equal Manager[@i3]
156
- end
157
-
158
- it "should handle eagerly loading many_to_one relationships" do
159
- Staff.limit(1).eager(:manager).all.map{|x| x.manager}.must_equal [Manager[@i4]]
160
- end
161
-
162
- it "should handle eagerly graphing many_to_one relationships" do
163
- ss = Staff.eager_graph(:manager).all
164
- ss.must_equal [Staff[@i2]]
165
- ss.map{|x| x.manager}.must_equal [Manager[@i4]]
166
- end
167
-
168
- it "should handle one_to_many relationships" do
169
- Executive.first(:name=>'Ex').staff_members.must_equal [Staff[@i2]]
170
- i6 = @db[:employees].insert(:name=>'S2', :kind=>'Staff')
171
- @db[:staff].insert(:id=>i6, :manager_id=>@i4)
172
- Executive.first(:name=>'Ex').add_staff_member(i6)
173
- Executive.first(:name=>'Ex').staff_members{|ds| ds.order(:id)}.must_equal [Staff[@i2], Staff[i6]]
174
- end
175
-
176
- it "should handle one_to_many relationships" do
177
- Executive.first(:name=>'Ex').first_staff_member.must_equal Staff[@i2]
178
- i6 = @db[:employees].insert(:name=>'S2', :kind=>'Staff')
179
- @db[:staff].insert(:id=>i6, :manager_id=>@i4)
180
- Executive.first(:name=>'Ex').first_staff_member = Staff[i6]
181
- Executive.first(:name=>'Ex').staff_members.must_equal [Staff[i6]]
182
- end
183
-
184
- it "should handle eagerly loading one_to_many relationships" do
185
- Executive.where(:name=>'Ex').eager(:staff_members).first.staff_members.must_equal [Staff[@i2]]
186
- end
187
-
188
- it "should handle eagerly graphing one_to_many relationships" do
189
- es = Executive.where(Sequel[:employees][:name]=>'Ex').eager_graph(:staff_members).all
190
- es.must_equal [Executive[@i4]]
191
- es.map{|x| x.staff_members}.must_equal [[Staff[@i2]]]
192
- end
193
- end
194
-
195
- describe "Many Through Many Plugin" do
196
- before(:all) do
197
- @db = DB
198
- @db.instance_variable_get(:@schemas).clear
199
- @db.drop_table?(:albums_artists, :albums, :artists)
200
- @db.create_table(:albums) do
201
- primary_key :id
202
- String :name
203
- end
204
- @db.create_table(:artists) do
205
- primary_key :id
206
- String :name
207
- end
208
- @db.create_table(:albums_artists) do
209
- foreign_key :album_id, :albums
210
- foreign_key :artist_id, :artists
211
- end
212
- end
213
- before do
214
- [:albums_artists, :albums, :artists].each{|t| @db[t].delete}
215
- class ::Album < Sequel::Model(@db)
216
- many_to_many :artists
217
- end
218
- class ::Artist < Sequel::Model(@db)
219
- plugin :many_through_many
220
- end
221
-
222
- @artist1 = Artist.create(:name=>'1')
223
- @artist2 = Artist.create(:name=>'2')
224
- @artist3 = Artist.create(:name=>'3')
225
- @artist4 = Artist.create(:name=>'4')
226
- @album1 = Album.create(:name=>'A')
227
- @album1.add_artist(@artist1)
228
- @album1.add_artist(@artist2)
229
- @album2 = Album.create(:name=>'B')
230
- @album2.add_artist(@artist3)
231
- @album2.add_artist(@artist4)
232
- @album3 = Album.create(:name=>'C')
233
- @album3.add_artist(@artist2)
234
- @album3.add_artist(@artist3)
235
- @album4 = Album.create(:name=>'D')
236
- @album4.add_artist(@artist1)
237
- @album4.add_artist(@artist4)
238
- end
239
- after do
240
- [:Album, :Artist].each{|s| Object.send(:remove_const, s)}
241
- end
242
- after(:all) do
243
- @db.drop_table? :albums_artists, :albums, :artists
244
- end
245
- def around
246
- DB.transaction(:rollback=>:always){super}
247
- end
248
-
249
- def self_join(c)
250
- c.join(Sequel.as(c.table_name, :b), Array(c.primary_key).zip(Array(c.primary_key))).select_all(c.table_name)
251
- end
252
-
253
- it "should handle super simple case with 1 join table" do
254
- Artist.many_through_many :albums, [[:albums_artists, :artist_id, :album_id]]
255
- Artist[@artist1.id].albums.map{|x| x.name}.sort.must_equal %w'A D'
256
- Artist[@artist2.id].albums.map{|x| x.name}.sort.must_equal %w'A C'
257
- Artist[@artist3.id].albums.map{|x| x.name}.sort.must_equal %w'B C'
258
- Artist[@artist4.id].albums.map{|x| x.name}.sort.must_equal %w'B D'
259
-
260
- Artist[@artist1.id].albums.map{|x| x.name}.sort.must_equal %w'A D'
261
- Artist[@artist2.id].albums.map{|x| x.name}.sort.must_equal %w'A C'
262
- Artist[@artist3.id].albums.map{|x| x.name}.sort.must_equal %w'B C'
263
- Artist[@artist4.id].albums.map{|x| x.name}.sort.must_equal %w'B D'
264
-
265
- Artist.filter(:id=>@artist1.id).eager(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.must_equal %w'A D'
266
- Artist.filter(:id=>@artist2.id).eager(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.must_equal %w'A C'
267
- Artist.filter(:id=>@artist3.id).eager(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.must_equal %w'B C'
268
- Artist.filter(:id=>@artist4.id).eager(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.must_equal %w'B D'
269
-
270
- Artist.filter(Sequel[:artists][:id]=>@artist1.id).eager_graph(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.must_equal %w'A D'
271
- Artist.filter(Sequel[:artists][:id]=>@artist2.id).eager_graph(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.must_equal %w'A C'
272
- Artist.filter(Sequel[:artists][:id]=>@artist3.id).eager_graph(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.must_equal %w'B C'
273
- Artist.filter(Sequel[:artists][:id]=>@artist4.id).eager_graph(:albums).all.map{|x| x.albums.map{|a| a.name}}.flatten.sort.must_equal %w'B D'
274
-
275
- Artist.filter(:albums=>@album1).all.map{|a| a.name}.sort.must_equal %w'1 2'
276
- Artist.filter(:albums=>@album2).all.map{|a| a.name}.sort.must_equal %w'3 4'
277
- Artist.filter(:albums=>@album3).all.map{|a| a.name}.sort.must_equal %w'2 3'
278
- Artist.filter(:albums=>@album4).all.map{|a| a.name}.sort.must_equal %w'1 4'
279
-
280
- Artist.exclude(:albums=>@album1).all.map{|a| a.name}.sort.must_equal %w'3 4'
281
- Artist.exclude(:albums=>@album2).all.map{|a| a.name}.sort.must_equal %w'1 2'
282
- Artist.exclude(:albums=>@album3).all.map{|a| a.name}.sort.must_equal %w'1 4'
283
- Artist.exclude(:albums=>@album4).all.map{|a| a.name}.sort.must_equal %w'2 3'
284
-
285
- Artist.filter(:albums=>[@album1, @album3]).all.map{|a| a.name}.sort.must_equal %w'1 2 3'
286
- Artist.filter(:albums=>[@album2, @album4]).all.map{|a| a.name}.sort.must_equal %w'1 3 4'
287
-
288
- Artist.exclude(:albums=>[@album1, @album3]).all.map{|a| a.name}.sort.must_equal %w'4'
289
- Artist.exclude(:albums=>[@album2, @album4]).all.map{|a| a.name}.sort.must_equal %w'2'
290
-
291
- Artist.filter(:albums=>Album.filter(:id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.must_equal %w'1 2 3'
292
- Artist.exclude(:albums=>Album.filter(:id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.must_equal %w'4'
293
-
294
- c = self_join(Artist)
295
- c.filter(:albums=>@album1).all.map{|a| a.name}.sort.must_equal %w'1 2'
296
- c.filter(:albums=>@album2).all.map{|a| a.name}.sort.must_equal %w'3 4'
297
- c.filter(:albums=>@album3).all.map{|a| a.name}.sort.must_equal %w'2 3'
298
- c.filter(:albums=>@album4).all.map{|a| a.name}.sort.must_equal %w'1 4'
299
-
300
- c.exclude(:albums=>@album1).all.map{|a| a.name}.sort.must_equal %w'3 4'
301
- c.exclude(:albums=>@album2).all.map{|a| a.name}.sort.must_equal %w'1 2'
302
- c.exclude(:albums=>@album3).all.map{|a| a.name}.sort.must_equal %w'1 4'
303
- c.exclude(:albums=>@album4).all.map{|a| a.name}.sort.must_equal %w'2 3'
304
-
305
- c.filter(:albums=>[@album1, @album3]).all.map{|a| a.name}.sort.must_equal %w'1 2 3'
306
- c.filter(:albums=>[@album2, @album4]).all.map{|a| a.name}.sort.must_equal %w'1 3 4'
307
-
308
- c.exclude(:albums=>[@album1, @album3]).all.map{|a| a.name}.sort.must_equal %w'4'
309
- c.exclude(:albums=>[@album2, @album4]).all.map{|a| a.name}.sort.must_equal %w'2'
310
-
311
- c.filter(:albums=>self_join(Album).filter(Sequel[:albums][:id]=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.must_equal %w'1 2 3'
312
- c.exclude(:albums=>self_join(Album).filter(Sequel[:albums][:id]=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.must_equal %w'4'
313
- end
314
-
315
- it "should handle typical case with 3 join tables" do
316
- Artist.many_through_many :related_artists, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_artists, :album_id, :artist_id]], :class=>Artist, :distinct=>true, :delay_pks=>false
317
- Artist[@artist1.id].related_artists.map{|x| x.name}.sort.must_equal %w'1 2 4'
318
- Artist[@artist2.id].related_artists.map{|x| x.name}.sort.must_equal %w'1 2 3'
319
- Artist[@artist3.id].related_artists.map{|x| x.name}.sort.must_equal %w'2 3 4'
320
- Artist[@artist4.id].related_artists.map{|x| x.name}.sort.must_equal %w'1 3 4'
321
-
322
- Artist[@artist1.id].related_artists.map{|x| x.name}.sort.must_equal %w'1 2 4'
323
- Artist[@artist2.id].related_artists.map{|x| x.name}.sort.must_equal %w'1 2 3'
324
- Artist[@artist3.id].related_artists.map{|x| x.name}.sort.must_equal %w'2 3 4'
325
- Artist[@artist4.id].related_artists.map{|x| x.name}.sort.must_equal %w'1 3 4'
326
-
327
- Artist.filter(:id=>@artist1.id).eager(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.must_equal %w'1 2 4'
328
- Artist.filter(:id=>@artist2.id).eager(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.must_equal %w'1 2 3'
329
- Artist.filter(:id=>@artist3.id).eager(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.must_equal %w'2 3 4'
330
- Artist.filter(:id=>@artist4.id).eager(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.must_equal %w'1 3 4'
331
-
332
- Artist.filter(Sequel[:artists][:id]=>@artist1.id).eager_graph(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.must_equal %w'1 2 4'
333
- Artist.filter(Sequel[:artists][:id]=>@artist2.id).eager_graph(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.must_equal %w'1 2 3'
334
- Artist.filter(Sequel[:artists][:id]=>@artist3.id).eager_graph(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.must_equal %w'2 3 4'
335
- Artist.filter(Sequel[:artists][:id]=>@artist4.id).eager_graph(:related_artists).all.map{|x| x.related_artists.map{|a| a.name}}.flatten.sort.must_equal %w'1 3 4'
336
-
337
- Artist.filter(:related_artists=>@artist1).all.map{|a| a.name}.sort.must_equal %w'1 2 4'
338
- Artist.filter(:related_artists=>@artist2).all.map{|a| a.name}.sort.must_equal %w'1 2 3'
339
- Artist.filter(:related_artists=>@artist3).all.map{|a| a.name}.sort.must_equal %w'2 3 4'
340
- Artist.filter(:related_artists=>@artist4).all.map{|a| a.name}.sort.must_equal %w'1 3 4'
341
-
342
- Artist.exclude(:related_artists=>@artist1).all.map{|a| a.name}.sort.must_equal %w'3'
343
- Artist.exclude(:related_artists=>@artist2).all.map{|a| a.name}.sort.must_equal %w'4'
344
- Artist.exclude(:related_artists=>@artist3).all.map{|a| a.name}.sort.must_equal %w'1'
345
- Artist.exclude(:related_artists=>@artist4).all.map{|a| a.name}.sort.must_equal %w'2'
346
-
347
- Artist.filter(:related_artists=>[@artist1, @artist4]).all.map{|a| a.name}.sort.must_equal %w'1 2 3 4'
348
- Artist.exclude(:related_artists=>[@artist1, @artist4]).all.map{|a| a.name}.sort.must_equal %w''
349
-
350
- Artist.filter(:related_artists=>Artist.filter(:id=>@artist1.id)).all.map{|a| a.name}.sort.must_equal %w'1 2 4'
351
- Artist.exclude(:related_artists=>Artist.filter(:id=>@artist1.id)).all.map{|a| a.name}.sort.must_equal %w'3'
352
-
353
- c = self_join(Artist)
354
- c.filter(:related_artists=>@artist1).all.map{|a| a.name}.sort.must_equal %w'1 2 4'
355
- c.filter(:related_artists=>@artist2).all.map{|a| a.name}.sort.must_equal %w'1 2 3'
356
- c.filter(:related_artists=>@artist3).all.map{|a| a.name}.sort.must_equal %w'2 3 4'
357
- c.filter(:related_artists=>@artist4).all.map{|a| a.name}.sort.must_equal %w'1 3 4'
358
-
359
- c.exclude(:related_artists=>@artist1).all.map{|a| a.name}.sort.must_equal %w'3'
360
- c.exclude(:related_artists=>@artist2).all.map{|a| a.name}.sort.must_equal %w'4'
361
- c.exclude(:related_artists=>@artist3).all.map{|a| a.name}.sort.must_equal %w'1'
362
- c.exclude(:related_artists=>@artist4).all.map{|a| a.name}.sort.must_equal %w'2'
363
-
364
- c.filter(:related_artists=>[@artist1, @artist4]).all.map{|a| a.name}.sort.must_equal %w'1 2 3 4'
365
- c.exclude(:related_artists=>[@artist1, @artist4]).all.map{|a| a.name}.sort.must_equal %w''
366
-
367
- c.filter(:related_artists=>c.filter(Sequel[:artists][:id]=>@artist1.id)).all.map{|a| a.name}.sort.must_equal %w'1 2 4'
368
- c.exclude(:related_artists=>c.filter(Sequel[:artists][:id]=>@artist1.id)).all.map{|a| a.name}.sort.must_equal %w'3'
369
- end
370
-
371
- it "should handle extreme case with 5 join tables" do
372
- Artist.many_through_many :related_albums, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_artists, :album_id, :artist_id], [:artists, :id, :id], [:albums_artists, :artist_id, :album_id]], :class=>Album, :distinct=>true
373
- @db[:albums_artists].delete
374
- @album1.add_artist(@artist1)
375
- @album1.add_artist(@artist2)
376
- @album2.add_artist(@artist2)
377
- @album2.add_artist(@artist3)
378
- @album3.add_artist(@artist1)
379
- @album4.add_artist(@artist3)
380
- @album4.add_artist(@artist4)
381
-
382
- Artist[@artist1.id].related_albums.map{|x| x.name}.sort.must_equal %w'A B C'
383
- Artist[@artist2.id].related_albums.map{|x| x.name}.sort.must_equal %w'A B C D'
384
- Artist[@artist3.id].related_albums.map{|x| x.name}.sort.must_equal %w'A B D'
385
- Artist[@artist4.id].related_albums.map{|x| x.name}.sort.must_equal %w'B D'
386
-
387
- Artist[@artist1.id].related_albums.map{|x| x.name}.sort.must_equal %w'A B C'
388
- Artist[@artist2.id].related_albums.map{|x| x.name}.sort.must_equal %w'A B C D'
389
- Artist[@artist3.id].related_albums.map{|x| x.name}.sort.must_equal %w'A B D'
390
- Artist[@artist4.id].related_albums.map{|x| x.name}.sort.must_equal %w'B D'
391
-
392
- Artist.filter(:id=>@artist1.id).eager(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.must_equal %w'A B C'
393
- Artist.filter(:id=>@artist2.id).eager(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.must_equal %w'A B C D'
394
- Artist.filter(:id=>@artist3.id).eager(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.must_equal %w'A B D'
395
- Artist.filter(:id=>@artist4.id).eager(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.must_equal %w'B D'
396
-
397
- Artist.filter(Sequel[:artists][:id]=>@artist1.id).eager_graph(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.must_equal %w'A B C'
398
- Artist.filter(Sequel[:artists][:id]=>@artist2.id).eager_graph(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.must_equal %w'A B C D'
399
- Artist.filter(Sequel[:artists][:id]=>@artist3.id).eager_graph(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.must_equal %w'A B D'
400
- Artist.filter(Sequel[:artists][:id]=>@artist4.id).eager_graph(:related_albums).all.map{|x| x.related_albums.map{|a| a.name}}.flatten.sort.must_equal %w'B D'
401
-
402
- Artist.filter(:related_albums=>@album1).all.map{|a| a.name}.sort.must_equal %w'1 2 3'
403
- Artist.filter(:related_albums=>@album2).all.map{|a| a.name}.sort.must_equal %w'1 2 3 4'
404
- Artist.filter(:related_albums=>@album3).all.map{|a| a.name}.sort.must_equal %w'1 2'
405
- Artist.filter(:related_albums=>@album4).all.map{|a| a.name}.sort.must_equal %w'2 3 4'
406
-
407
- Artist.exclude(:related_albums=>@album1).all.map{|a| a.name}.sort.must_equal %w'4'
408
- Artist.exclude(:related_albums=>@album2).all.map{|a| a.name}.sort.must_equal %w''
409
- Artist.exclude(:related_albums=>@album3).all.map{|a| a.name}.sort.must_equal %w'3 4'
410
- Artist.exclude(:related_albums=>@album4).all.map{|a| a.name}.sort.must_equal %w'1'
411
-
412
- Artist.filter(:related_albums=>[@album1, @album3]).all.map{|a| a.name}.sort.must_equal %w'1 2 3'
413
- Artist.filter(:related_albums=>[@album3, @album4]).all.map{|a| a.name}.sort.must_equal %w'1 2 3 4'
414
-
415
- Artist.exclude(:related_albums=>[@album1, @album3]).all.map{|a| a.name}.sort.must_equal %w'4'
416
- Artist.exclude(:related_albums=>[@album2, @album4]).all.map{|a| a.name}.sort.must_equal %w''
417
-
418
- Artist.filter(:related_albums=>Album.filter(:id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.must_equal %w'1 2 3'
419
- Artist.exclude(:related_albums=>Album.filter(:id=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.must_equal %w'4'
420
-
421
- c = self_join(Artist)
422
- c.filter(:related_albums=>@album1).all.map{|a| a.name}.sort.must_equal %w'1 2 3'
423
- c.filter(:related_albums=>@album2).all.map{|a| a.name}.sort.must_equal %w'1 2 3 4'
424
- c.filter(:related_albums=>@album3).all.map{|a| a.name}.sort.must_equal %w'1 2'
425
- c.filter(:related_albums=>@album4).all.map{|a| a.name}.sort.must_equal %w'2 3 4'
426
-
427
- c.exclude(:related_albums=>@album1).all.map{|a| a.name}.sort.must_equal %w'4'
428
- c.exclude(:related_albums=>@album2).all.map{|a| a.name}.sort.must_equal %w''
429
- c.exclude(:related_albums=>@album3).all.map{|a| a.name}.sort.must_equal %w'3 4'
430
- c.exclude(:related_albums=>@album4).all.map{|a| a.name}.sort.must_equal %w'1'
431
-
432
- c.filter(:related_albums=>[@album1, @album3]).all.map{|a| a.name}.sort.must_equal %w'1 2 3'
433
- c.filter(:related_albums=>[@album3, @album4]).all.map{|a| a.name}.sort.must_equal %w'1 2 3 4'
434
-
435
- c.exclude(:related_albums=>[@album1, @album3]).all.map{|a| a.name}.sort.must_equal %w'4'
436
- c.exclude(:related_albums=>[@album2, @album4]).all.map{|a| a.name}.sort.must_equal %w''
437
-
438
- c.filter(:related_albums=>self_join(Album).filter(Sequel[:albums][:id]=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.must_equal %w'1 2 3'
439
- c.exclude(:related_albums=>self_join(Album).filter(Sequel[:albums][:id]=>[@album1.id, @album3.id])).all.map{|a| a.name}.sort.must_equal %w'4'
440
- end
441
- end
442
-
443
- describe "Lazy Attributes plugin" do
444
- before(:all) do
445
- @db = DB
446
- @db.create_table!(:items) do
447
- primary_key :id
448
- String :name
449
- Integer :num
450
- end
451
- @db[:items].delete
452
- class ::Item < Sequel::Model(@db)
453
- plugin :lazy_attributes, :num
454
- end
455
- Item.create(:name=>'J', :num=>1)
456
- end
457
- after(:all) do
458
- @db.drop_table?(:items)
459
- Object.send(:remove_const, :Item)
460
- end
461
-
462
- it "should not include lazy attribute columns by default" do
463
- Item.first.must_equal Item.load(:id=>1, :name=>'J')
464
- end
465
-
466
- it "should load lazy attribute on access" do
467
- Item.first.num.must_equal 1
468
- end
469
-
470
- it "should typecast lazy attribute in setter" do
471
- i = Item.new
472
- i.num = '1'
473
- i.num.must_equal 1
474
- end
475
-
476
- it "should load lazy attribute for all items returned when accessing any item if using identity map " do
477
- Item.create(:name=>'K', :num=>2)
478
- a = Item.order(:name).all
479
- a.must_equal [Item.load(:id=>1, :name=>'J'), Item.load(:id=>2, :name=>'K')]
480
- a.map{|x| x[:num]}.must_equal [nil, nil]
481
- a.first.num.must_equal 1
482
- a.map{|x| x[:num]}.must_equal [1, 2]
483
- a.last.num.must_equal 2
484
- end
485
- end
486
-
487
- describe "Tactical Eager Loading Plugin" do
488
- before(:all) do
489
- @db = DB
490
- @db.instance_variable_get(:@schemas).clear
491
- @db.drop_table?(:albums_artists)
492
- @db.create_table!(:artists) do
493
- primary_key :id
494
- String :name
495
- end
496
- @db.create_table!(:albums) do
497
- primary_key :id
498
- String :name
499
- foreign_key :artist_id, :artists
500
- end
501
- end
502
- before do
503
- @db[:albums].delete
504
- @db[:artists].delete
505
- class ::Album < Sequel::Model(@db)
506
- plugin :tactical_eager_loading
507
- many_to_one :artist
508
- end
509
- class ::Artist < Sequel::Model(@db)
510
- plugin :tactical_eager_loading
511
- one_to_many :albums, :order=>:name
512
- end
513
-
514
- @artist1 = Artist.create(:name=>'1')
515
- @artist2 = Artist.create(:name=>'2')
516
- @artist3 = Artist.create(:name=>'3')
517
- @artist4 = Artist.create(:name=>'4')
518
- @album1 = Album.create(:name=>'A', :artist=>@artist1)
519
- @album2 = Album.create(:name=>'B', :artist=>@artist1)
520
- @album3 = Album.create(:name=>'C', :artist=>@artist2)
521
- @album4 = Album.create(:name=>'D', :artist=>@artist3)
522
- end
523
- after do
524
- [:Album, :Artist].each{|s| Object.send(:remove_const, s)}
525
- end
526
- after(:all) do
527
- @db.drop_table? :albums, :artists
528
- end
529
-
530
- it "should eagerly load associations for all items when accessing any item" do
531
- a = Artist.order(:name).all
532
- a.map{|x| x.associations}.must_equal [{}, {}, {}, {}]
533
- a.first.albums.must_equal [@album1, @album2]
534
- a.map{|x| x.associations}.must_equal [{:albums=>[@album1, @album2]}, {:albums=>[@album3]}, {:albums=>[@album4]}, {:albums=>[]}]
535
-
536
- a = Album.order(:name).all
537
- a.map{|x| x.associations}.must_equal [{}, {}, {}, {}]
538
- a.first.artist.must_equal @artist1
539
- a.map{|x| x.associations}.must_equal [{:artist=>@artist1}, {:artist=>@artist1}, {:artist=>@artist2}, {:artist=>@artist3}]
540
- end
541
- end
542
-
543
- describe "Touch plugin" do
544
- before(:all) do
545
- @db = DB
546
- @db.drop_table? :albums_artists, :albums, :artists
547
- @db.create_table(:artists) do
548
- primary_key :id
549
- String :name
550
- DateTime :updated_at
551
- end
552
- @db.create_table(:albums) do
553
- primary_key :id
554
- String :name
555
- foreign_key :artist_id, :artists
556
- DateTime :updated_at
557
- end
558
- @db.create_join_table({:album_id=>:albums, :artist_id=>:artists}, :no_index=>true)
559
- end
560
- before do
561
- @db[:albums].delete
562
- @db[:artists].delete
563
- class ::Album < Sequel::Model(@db)
564
- end
565
- class ::Artist < Sequel::Model(@db)
566
- end
567
-
568
- @artist = Artist.create(:name=>'1')
569
- @album = Album.create(:name=>'A', :artist_id=>@artist.id)
570
- end
571
- after do
572
- [:Album, :Artist].each{|s| Object.send(:remove_const, s)}
573
- end
574
- after(:all) do
575
- @db.drop_table? :albums_artists, :albums, :artists
576
- end
577
- def around
578
- DB.transaction(:rollback=>:always){super}
579
- end
580
-
581
- it "should update the timestamp column when touching the record" do
582
- Album.plugin :touch
583
- @album.updated_at.must_be_nil
584
- @album.touch
585
- @album.updated_at.to_i.must_be_close_to Time.now.to_i, 2
586
- end
587
-
588
- cspecify "should update the timestamp column for many_to_one associated records when the record is updated or destroyed", [:jdbc, :sqlite] do
589
- Album.many_to_one :artist
590
- Album.plugin :touch, :associations=>:artist
591
- @artist.updated_at.must_be_nil
592
- @album.update(:name=>'B')
593
- ua = @artist.reload.updated_at
594
- if ua.is_a?(Time)
595
- ua.to_i.must_be_close_to Time.now.to_i, 60
596
- else
597
- (DateTime.now - ua).must_be_close_to 0, 60.0/86400
598
- end
599
- @artist.update(:updated_at=>nil)
600
- @album.destroy
601
- if ua.is_a?(Time)
602
- ua.to_i.must_be_close_to Time.now.to_i, 60
603
- else
604
- (DateTime.now - ua).must_be_close_to 0, 60.0/86400
605
- end
606
- end
607
-
608
- cspecify "should update the timestamp column for one_to_many associated records when the record is updated", [:jdbc, :sqlite] do
609
- Artist.one_to_many :albums
610
- Artist.plugin :touch, :associations=>:albums
611
- @album.updated_at.must_be_nil
612
- @artist.update(:name=>'B')
613
- ua = @album.reload.updated_at
614
- if ua.is_a?(Time)
615
- ua.to_i.must_be_close_to Time.now.to_i, 60
616
- else
617
- (DateTime.now - ua).must_be_close_to 0, 60.0/86400
618
- end
619
- end
620
-
621
- cspecify "should update the timestamp column for many_to_many associated records when the record is updated", [:jdbc, :sqlite] do
622
- Artist.many_to_many :albums
623
- Artist.plugin :touch, :associations=>:albums
624
- @artist.add_album(@album)
625
- @album.updated_at.must_be_nil
626
- @artist.update(:name=>'B')
627
- ua = @album.reload.updated_at
628
- if ua.is_a?(Time)
629
- ua.to_i.must_be_close_to Time.now.to_i, 60
630
- else
631
- (DateTime.now - ua).must_be_close_to 0, 60.0/86400
632
- end
633
- end
634
- end
635
-
636
- describe "Serialization plugin" do
637
- before do
638
- @db = DB
639
- @db.create_table!(:items) do
640
- primary_key :id
641
- String :stuff
642
- end
643
- class ::Item < Sequel::Model(@db)
644
- plugin :serialization, :marshal, :stuff
645
- end
646
- end
647
- after do
648
- @db.drop_table?(:items)
649
- Object.send(:remove_const, :Item)
650
- end
651
-
652
- it "should serialize and deserialize items as needed" do
653
- i = Item.create(:stuff=>{:a=>1})
654
- i.stuff.must_equal(:a=>1)
655
- i.stuff = [1, 2, 3]
656
- i.save
657
- Item.first.stuff.must_equal [1, 2, 3]
658
- i.update(:stuff=>Item.new)
659
- Item.first.stuff.must_equal Item.new
660
- end
661
- end
662
-
663
- describe "OptimisticLocking plugin" do
664
- before(:all) do
665
- @db = DB
666
- @db.create_table!(:people) do
667
- primary_key :id
668
- String :name
669
- Integer :lock_version, :default=>0, :null=>false
670
- end
671
- class ::Person < Sequel::Model(@db)
672
- plugin :optimistic_locking
673
- end
674
- end
675
- before do
676
- @db[:people].delete
677
- @p = Person.create(:name=>'John')
678
- end
679
- after(:all) do
680
- @db.drop_table?(:people)
681
- Object.send(:remove_const, :Person)
682
- end
683
-
684
- it "should raise an error when updating a stale record" do
685
- p1 = Person[@p.id]
686
- p2 = Person[@p.id]
687
- p1.update(:name=>'Jim')
688
- proc{p2.update(:name=>'Bob')}.must_raise(Sequel::Plugins::OptimisticLocking::Error)
689
- end
690
-
691
- it "should raise an error when destroying a stale record" do
692
- p1 = Person[@p.id]
693
- p2 = Person[@p.id]
694
- p1.update(:name=>'Jim')
695
- proc{p2.destroy}.must_raise(Sequel::Plugins::OptimisticLocking::Error)
696
- end
697
-
698
- it "should not raise an error when updating the same record twice" do
699
- p1 = Person[@p.id]
700
- p1.update(:name=>'Jim')
701
- p1.update(:name=>'Bob')
702
- end
703
- end
704
-
705
- describe "Composition plugin" do
706
- before do
707
- @db = DB
708
- @db.create_table!(:events) do
709
- primary_key :id
710
- Integer :year
711
- Integer :month
712
- Integer :day
713
- end
714
- class ::Event < Sequel::Model(@db)
715
- plugin :composition
716
- composition :date, :composer=>proc{Date.new(year, month, day) if year && month && day}, :decomposer=>(proc do
717
- if date
718
- self.year = date.year
719
- self.month = date.month
720
- self.day = date.day
721
- else
722
- self.year, self.month, self.day = nil
723
- end
724
- end)
725
- composition :date, :mapping=>[:year, :month, :day]
726
- end
727
- @e1 = Event.create(:year=>2010, :month=>2, :day=>15)
728
- @e2 = Event.create(:year=>nil)
729
- end
730
- after do
731
- @db.drop_table?(:events)
732
- Object.send(:remove_const, :Event)
733
- end
734
-
735
- it "should return a composed object if the underlying columns have a value" do
736
- @e1.date.must_equal Date.civil(2010, 2, 15)
737
- @e2.date.must_be_nil
738
- end
739
-
740
- it "should decompose the object when saving the record" do
741
- @e1.date = Date.civil(2009, 1, 2)
742
- @e1.save
743
- @e1.year.must_equal 2009
744
- @e1.month.must_equal 1
745
- @e1.day.must_equal 2
746
- end
747
-
748
- it "should save all columns when saving changes" do
749
- @e2.date = Date.civil(2009, 10, 2)
750
- @e2.save_changes
751
- @e2.reload
752
- @e2.year.must_equal 2009
753
- @e2.month.must_equal 10
754
- @e2.day.must_equal 2
755
- end
756
- end
757
-
758
- describe "RcteTree Plugin" do
759
- RcteTreePluginSpecs = shared_description do
760
- it "should load all standard (not-CTE) methods correctly" do
761
- @a.children.must_equal [@aa, @ab]
762
- @b.children.must_equal [@ba, @bb]
763
- @aa.children.must_equal [@aaa, @aab]
764
- @ab.children.must_equal [@aba, @abb]
765
- @ba.children.must_equal []
766
- @bb.children.must_equal []
767
- @aaa.children.must_equal [@aaaa, @aaab]
768
- @aab.children.must_equal []
769
- @aba.children.must_equal []
770
- @abb.children.must_equal []
771
- @aaaa.children.must_equal [@aaaaa]
772
- @aaab.children.must_equal []
773
- @aaaaa.children.must_equal []
774
-
775
- @a.parent.must_be_nil
776
- @b.parent.must_be_nil
777
- @aa.parent.must_equal @a
778
- @ab.parent.must_equal @a
779
- @ba.parent.must_equal @b
780
- @bb.parent.must_equal @b
781
- @aaa.parent.must_equal @aa
782
- @aab.parent.must_equal @aa
783
- @aba.parent.must_equal @ab
784
- @abb.parent.must_equal @ab
785
- @aaaa.parent.must_equal @aaa
786
- @aaab.parent.must_equal @aaa
787
- @aaaaa.parent.must_equal @aaaa
788
- end
789
-
790
- it "should load all ancestors and descendants lazily for a given instance" do
791
- @a.descendants.must_equal [@aa, @aaa, @aaaa, @aaaaa, @aaab, @aab, @ab, @aba, @abb]
792
- @b.descendants.must_equal [@ba, @bb]
793
- @aa.descendants.must_equal [@aaa, @aaaa, @aaaaa, @aaab, @aab]
794
- @ab.descendants.must_equal [@aba, @abb]
795
- @ba.descendants.must_equal []
796
- @bb.descendants.must_equal []
797
- @aaa.descendants.must_equal [@aaaa, @aaaaa, @aaab]
798
- @aab.descendants.must_equal []
799
- @aba.descendants.must_equal []
800
- @abb.descendants.must_equal []
801
- @aaaa.descendants.must_equal [@aaaaa]
802
- @aaab.descendants.must_equal []
803
- @aaaaa.descendants.must_equal []
804
-
805
- @a.ancestors.must_equal []
806
- @b.ancestors.must_equal []
807
- @aa.ancestors.must_equal [@a]
808
- @ab.ancestors.must_equal [@a]
809
- @ba.ancestors.must_equal [@b]
810
- @bb.ancestors.must_equal [@b]
811
- @aaa.ancestors.must_equal [@a, @aa]
812
- @aab.ancestors.must_equal [@a, @aa]
813
- @aba.ancestors.must_equal [@a, @ab]
814
- @abb.ancestors.must_equal [@a, @ab]
815
- @aaaa.ancestors.must_equal [@a, @aa, @aaa]
816
- @aaab.ancestors.must_equal [@a, @aa, @aaa]
817
- @aaaaa.ancestors.must_equal [@a, @aa, @aaa, @aaaa]
818
- end
819
-
820
- it "should eagerly load all ancestors and descendants for a dataset" do
821
- nodes = @Node.filter(@Node.primary_key=>[@a.pk, @b.pk, @aaa.pk]).order(:name).eager(:ancestors, :descendants).all
822
- nodes.must_equal [@a, @aaa, @b]
823
- nodes[0].descendants.must_equal [@aa, @aaa, @aaaa, @aaaaa, @aaab, @aab, @ab, @aba, @abb]
824
- nodes[1].descendants.must_equal [@aaaa, @aaaaa, @aaab]
825
- nodes[2].descendants.must_equal [@ba, @bb]
826
- nodes[0].ancestors.must_equal []
827
- nodes[1].ancestors.must_equal [@a, @aa]
828
- nodes[2].ancestors.must_equal []
829
- end
830
-
831
- it "should eagerly load descendants to a given level" do
832
- nodes = @Node.filter(@Node.primary_key=>[@a.pk, @b.pk, @aaa.pk]).order(:name).eager(:descendants=>1).all
833
- nodes.must_equal [@a, @aaa, @b]
834
- nodes[0].descendants.must_equal [@aa, @ab]
835
- nodes[1].descendants.must_equal [@aaaa, @aaab]
836
- nodes[2].descendants.must_equal [@ba, @bb]
837
-
838
- nodes = @Node.filter(@Node.primary_key=>[@a.pk, @b.pk, @aaa.pk]).order(:name).eager(:descendants=>2).all
839
- nodes.must_equal [@a, @aaa, @b]
840
- nodes[0].descendants.must_equal [@aa, @aaa, @aab, @ab, @aba, @abb]
841
- nodes[1].descendants.must_equal [@aaaa, @aaaaa, @aaab]
842
- nodes[2].descendants.must_equal [@ba, @bb]
843
- end
844
-
845
- it "should populate all :children associations when eagerly loading descendants for a dataset" do
846
- nodes = @Node.filter(@Node.primary_key=>[@a.pk, @b.pk, @aaa.pk]).order(:name).eager(:descendants).all
847
- nodes[0].associations[:children].must_equal [@aa, @ab]
848
- nodes[1].associations[:children].must_equal [@aaaa, @aaab]
849
- nodes[2].associations[:children].must_equal [@ba, @bb]
850
- nodes[0].associations[:children].map{|c1| c1.associations[:children]}.must_equal [[@aaa, @aab], [@aba, @abb]]
851
- nodes[1].associations[:children].map{|c1| c1.associations[:children]}.must_equal [[@aaaaa], []]
852
- nodes[2].associations[:children].map{|c1| c1.associations[:children]}.must_equal [[], []]
853
- nodes[0].associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.associations[:children]}}.must_equal [[[@aaaa, @aaab], []], [[], []]]
854
- nodes[1].associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.associations[:children]}}.must_equal [[[]], []]
855
- nodes[0].associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.associations[:children].map{|c3| c3.associations[:children]}}}.must_equal [[[[@aaaaa], []], []], [[], []]]
856
- nodes[0].associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.associations[:children].map{|c3| c3.associations[:children].map{|c4| c4.associations[:children]}}}}.must_equal [[[[[]], []], []], [[], []]]
857
- end
858
-
859
- it "should not populate :children associations for final level when loading descendants to a given level" do
860
- nodes = @Node.filter(@Node.primary_key=>[@a.pk, @b.pk, @aaa.pk]).order(:name).eager(:descendants=>1).all
861
- nodes[0].associations[:children].must_equal [@aa, @ab]
862
- nodes[0].associations[:children].map{|c1| c1.associations[:children]}.must_equal [nil, nil]
863
- nodes[1].associations[:children].must_equal [@aaaa, @aaab]
864
- nodes[1].associations[:children].map{|c1| c1.associations[:children]}.must_equal [nil, nil]
865
- nodes[2].associations[:children].must_equal [@ba, @bb]
866
- nodes[2].associations[:children].map{|c1| c1.associations[:children]}.must_equal [nil, nil]
867
-
868
- nodes[0].associations[:children].map{|c1| c1.children}.must_equal [[@aaa, @aab], [@aba, @abb]]
869
- nodes[1].associations[:children].map{|c1| c1.children}.must_equal [[@aaaaa], []]
870
- nodes[2].associations[:children].map{|c1| c1.children}.must_equal [[], []]
871
-
872
- nodes = @Node.filter(@Node.primary_key=>[@a.pk, @b.pk, @aaa.pk]).order(:name).eager(:descendants=>2).all
873
- nodes[0].associations[:children].must_equal [@aa, @ab]
874
- nodes[0].associations[:children].map{|c1| c1.associations[:children]}.must_equal [[@aaa, @aab], [@aba, @abb]]
875
- nodes[0].associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.associations[:children]}}.must_equal [[[@aaaa, @aaab], nil], [nil, nil]]
876
- nodes[0].associations[:children].map{|c1| c1.associations[:children].map{|c2| (cc2 = c2.associations[:children]) ? cc2.map{|c3| c3.associations[:children]} : nil}}.must_equal [[[[@aaaaa], []], nil], [nil, nil]]
877
- nodes[0].associations[:children].map{|c1| c1.associations[:children].map{|c2| (cc2 = c2.associations[:children]) ? cc2.map{|c3| (cc3 = c3.associations[:children]) ? cc3.map{|c4| c4.associations[:children]} : nil} : nil}}.must_equal [[[[nil], []], nil], [nil, nil]]
878
-
879
- nodes[1].associations[:children].must_equal [@aaaa, @aaab]
880
- nodes[1].associations[:children].map{|c1| c1.associations[:children]}.must_equal [[@aaaaa], []]
881
- nodes[1].associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.associations[:children]}}.must_equal [[nil], []]
882
-
883
- nodes[2].associations[:children].must_equal [@ba, @bb]
884
- nodes[2].associations[:children].map{|c1| c1.associations[:children]}.must_equal [[], []]
885
-
886
- nodes[0].associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.children}}.must_equal [[[@aaaa, @aaab], []], [[], []]]
887
- nodes[0].associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.children.map{|c3| c3.children}}}.must_equal [[[[@aaaaa], []], []], [[], []]]
888
- nodes[0].associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.children.map{|c3| c3.children.map{|c4| c4.children}}}}.must_equal [[[[[]], []], []], [[], []]]
889
- nodes[1].associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.children}}.must_equal [[[]], []]
890
- end
891
-
892
- it "should populate all :children associations when lazily loading descendants" do
893
- @a.descendants
894
- @a.associations[:children].must_equal [@aa, @ab]
895
- @a.associations[:children].map{|c1| c1.associations[:children]}.must_equal [[@aaa, @aab], [@aba, @abb]]
896
- @a.associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.associations[:children]}}.must_equal [[[@aaaa, @aaab], []], [[], []]]
897
- @a.associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.associations[:children].map{|c3| c3.associations[:children]}}}.must_equal [[[[@aaaaa], []], []], [[], []]]
898
- @a.associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.associations[:children].map{|c3| c3.associations[:children].map{|c4| c4.associations[:children]}}}}.must_equal [[[[[]], []], []], [[], []]]
899
-
900
- @b.descendants
901
- @b.associations[:children].must_equal [@ba, @bb]
902
- @b.associations[:children].map{|c1| c1.associations[:children]}.must_equal [[], []]
903
-
904
- @aaa.descendants
905
- @aaa.associations[:children].map{|c1| c1.associations[:children]}.must_equal [[@aaaaa], []]
906
- @aaa.associations[:children].map{|c1| c1.associations[:children].map{|c2| c2.associations[:children]}}.must_equal [[[]], []]
907
- end
908
-
909
- it "should populate all :parent associations when eagerly loading ancestors for a dataset" do
910
- nodes = @Node.filter(@Node.primary_key=>[@a.pk, @ba.pk, @aaa.pk, @aaaaa.pk]).order(:name).eager(:ancestors).all
911
- nodes[0].associations.fetch(:parent, 1).must_be_nil
912
- nodes[1].associations[:parent].must_equal @aa
913
- nodes[1].associations[:parent].associations[:parent].must_equal @a
914
- nodes[1].associations[:parent].associations[:parent].associations.fetch(:parent, 1).must_be_nil
915
- nodes[2].associations[:parent].must_equal @aaaa
916
- nodes[2].associations[:parent].associations[:parent].must_equal @aaa
917
- nodes[2].associations[:parent].associations[:parent].associations[:parent].must_equal @aa
918
- nodes[2].associations[:parent].associations[:parent].associations[:parent].associations[:parent].must_equal @a
919
- nodes[2].associations[:parent].associations[:parent].associations[:parent].associations[:parent].associations.fetch(:parent, 1).must_be_nil
920
- nodes[3].associations[:parent].must_equal @b
921
- nodes[3].associations[:parent].associations.fetch(:parent, 1).must_be_nil
922
- end
923
-
924
- it "should populate all :parent associations when lazily loading ancestors" do
925
- @a.reload
926
- @a.ancestors
927
- @a.associations[:parent].must_be_nil
928
-
929
- @ba.reload
930
- @ba.ancestors
931
- @ba.associations[:parent].must_equal @b
932
- @ba.associations[:parent].associations.fetch(:parent, 1).must_be_nil
933
-
934
- @ba.reload
935
- @aaaaa.ancestors
936
- @aaaaa.associations[:parent].must_equal @aaaa
937
- @aaaaa.associations[:parent].associations[:parent].must_equal @aaa
938
- @aaaaa.associations[:parent].associations[:parent].associations[:parent].must_equal @aa
939
- @aaaaa.associations[:parent].associations[:parent].associations[:parent].associations[:parent].must_equal @a
940
- @aaaaa.associations[:parent].associations[:parent].associations[:parent].associations[:parent].associations.fetch(:parent, 1).must_be_nil
941
- end
942
- end
943
-
944
- before do
945
- @nodes.each{|n| n.associations.clear}
946
- end
947
-
948
- describe "with single key" do
949
- before(:all) do
950
- @db = DB
951
- @db.create_table!(:nodes) do
952
- primary_key :id
953
- Integer :parent_id
954
- String :name
955
- end
956
- @Node = Class.new(Sequel::Model(@db[:nodes]))
957
- @Node.plugin :rcte_tree, :order=>:name
958
- @nodes = []
959
- @nodes << @a = @Node.create(:name=>'a')
960
- @nodes << @b = @Node.create(:name=>'b')
961
- @nodes << @aa = @Node.create(:name=>'aa', :parent=>@a)
962
- @nodes << @ab = @Node.create(:name=>'ab', :parent=>@a)
963
- @nodes << @ba = @Node.create(:name=>'ba', :parent=>@b)
964
- @nodes << @bb = @Node.create(:name=>'bb', :parent=>@b)
965
- @nodes << @aaa = @Node.create(:name=>'aaa', :parent=>@aa)
966
- @nodes << @aab = @Node.create(:name=>'aab', :parent=>@aa)
967
- @nodes << @aba = @Node.create(:name=>'aba', :parent=>@ab)
968
- @nodes << @abb = @Node.create(:name=>'abb', :parent=>@ab)
969
- @nodes << @aaaa = @Node.create(:name=>'aaaa', :parent=>@aaa)
970
- @nodes << @aaab = @Node.create(:name=>'aaab', :parent=>@aaa)
971
- @nodes << @aaaaa = @Node.create(:name=>'aaaaa', :parent=>@aaaa)
972
- end
973
- after(:all) do
974
- @db.drop_table? :nodes
975
- end
976
-
977
- include RcteTreePluginSpecs
978
-
979
- it "should work correctly if not all columns are selected" do
980
- c = Class.new(Sequel::Model(@db[:nodes]))
981
- c.plugin :rcte_tree, :order=>:name
982
- c.plugin :lazy_attributes, :name
983
- c[:name=>'aaaa'].descendants.must_equal [c.load(:parent_id=>11, :id=>13)]
984
- c[:name=>'aa'].ancestors.must_equal [c.load(:parent_id=>nil, :id=>1)]
985
- nodes = c.filter(:id=>[@a.id, @b.id, @aaa.id]).order(:name).eager(:ancestors, :descendants).all
986
- nodes.must_equal [{:parent_id=>nil, :id=>1}, {:parent_id=>3, :id=>7}, {:parent_id=>nil, :id=>2}].map{|x| c.load(x)}
987
- nodes[2].descendants.must_equal [{:parent_id=>2, :id=>5}, {:parent_id=>2, :id=>6}].map{|x| c.load(x)}
988
- nodes[1].ancestors.must_equal [{:parent_id=>nil, :id=>1}, {:parent_id=>1, :id=>3}].map{|x| c.load(x)}
989
- end
990
- end
991
-
992
- describe "with composite keys" do
993
- before(:all) do
994
- @db = DB
995
- @db.create_table!(:nodes) do
996
- Integer :id
997
- Integer :id2
998
- Integer :parent_id
999
- Integer :parent_id2
1000
- String :name
1001
- primary_key [:id, :id2]
1002
- end
1003
- @Node = Class.new(Sequel::Model(@db[:nodes]))
1004
- @Node.plugin :rcte_tree, :order=>:name, :key=>[:parent_id, :parent_id2]
1005
- @Node.unrestrict_primary_key
1006
- @nodes = []
1007
- @nodes << @a = @Node.create(:id=>1, :id2=>1, :name=>'a')
1008
- @nodes << @b = @Node.create(:id=>1, :id2=>2, :name=>'b')
1009
- @nodes << @aa = @Node.create(:id=>2, :id2=>1, :name=>'aa', :parent=>@a)
1010
- @nodes << @ab = @Node.create(:id=>2, :id2=>2, :name=>'ab', :parent=>@a)
1011
- @nodes << @ba = @Node.create(:id=>3, :id2=>1, :name=>'ba', :parent=>@b)
1012
- @nodes << @bb = @Node.create(:id=>3, :id2=>2, :name=>'bb', :parent=>@b)
1013
- @nodes << @aaa = @Node.create(:id=>3, :id2=>3, :name=>'aaa', :parent=>@aa)
1014
- @nodes << @aab = @Node.create(:id=>1, :id2=>3, :name=>'aab', :parent=>@aa)
1015
- @nodes << @aba = @Node.create(:id=>2, :id2=>3, :name=>'aba', :parent=>@ab)
1016
- @nodes << @abb = @Node.create(:id=>4, :id2=>1, :name=>'abb', :parent=>@ab)
1017
- @nodes << @aaaa = @Node.create(:id=>1, :id2=>4, :name=>'aaaa', :parent=>@aaa)
1018
- @nodes << @aaab = @Node.create(:id=>2, :id2=>4, :name=>'aaab', :parent=>@aaa)
1019
- @nodes << @aaaaa = @Node.create(:id=>3, :id2=>4, :name=>'aaaaa', :parent=>@aaaa)
1020
- end
1021
- after(:all) do
1022
- @db.drop_table? :nodes
1023
- end
1024
-
1025
- include RcteTreePluginSpecs
1026
- end
1027
- end if DB.dataset.supports_cte? and !Sequel.guarded?(:db2)
1028
-
1029
- describe "Instance Filters plugin" do
1030
- before(:all) do
1031
- @db = DB
1032
- @db.create_table!(:items) do
1033
- primary_key :id
1034
- String :name
1035
- Integer :cost
1036
- Integer :number
1037
- end
1038
- class ::Item < Sequel::Model(@db)
1039
- plugin :instance_filters
1040
- end
1041
- end
1042
- before do
1043
- @db[:items].delete
1044
- @i = Item.create(:name=>'J', :number=>1, :cost=>2)
1045
- @i.instance_filter(:number=>1)
1046
- @i.set(:name=>'K')
1047
- end
1048
- after(:all) do
1049
- @db.drop_table?(:items)
1050
- Object.send(:remove_const, :Item)
1051
- end
1052
-
1053
- it "should not raise an error if saving only updates one row" do
1054
- @i.save
1055
- @i.refresh.name.must_equal 'K'
1056
- end
1057
-
1058
- it "should raise error if saving doesn't update a row" do
1059
- @i.this.update(:number=>2)
1060
- proc{@i.save}.must_raise(Sequel::NoExistingObject)
1061
- end
1062
-
1063
- it "should apply all instance filters" do
1064
- @i.instance_filter{cost <= 2}
1065
- @i.this.update(:number=>2)
1066
- proc{@i.save}.must_raise(Sequel::NoExistingObject)
1067
- @i.this.update(:number=>1, :cost=>3)
1068
- proc{@i.save}.must_raise(Sequel::NoExistingObject)
1069
- @i.this.update(:cost=>2)
1070
- @i.save
1071
- @i.refresh.name.must_equal 'K'
1072
- end
1073
-
1074
- it "should clear instance filters after successful save" do
1075
- @i.save
1076
- @i.this.update(:number=>2)
1077
- @i.update(:name=>'L')
1078
- @i.refresh.name.must_equal 'L'
1079
- end
1080
-
1081
- it "should not raise an error if deleting only deletes one row" do
1082
- @i.destroy
1083
- proc{@i.refresh}.must_raise(Sequel::Error, 'Record not found')
1084
- end
1085
-
1086
- it "should raise error if destroying doesn't delete a row" do
1087
- @i.this.update(:number=>2)
1088
- proc{@i.destroy}.must_raise(Sequel::NoExistingObject)
1089
- end
1090
- end
1091
-
1092
- describe "UpdatePrimaryKey plugin" do
1093
- before(:all) do
1094
- @db = DB
1095
- @db.create_table!(:t) do
1096
- Integer :a, :primary_key=>true
1097
- Integer :b
1098
- end
1099
- @ds = @db[:t]
1100
- @c = Class.new(Sequel::Model(@ds))
1101
- @c.set_primary_key(:a)
1102
- @c.unrestrict_primary_key
1103
- @c.plugin :update_primary_key
1104
- end
1105
- before do
1106
- @ds.delete
1107
- @ds.insert(:a=>1, :b=>3)
1108
- end
1109
- after(:all) do
1110
- @db.drop_table?(:t)
1111
- end
1112
-
1113
- it "should handle regular updates" do
1114
- @c.first.update(:b=>4)
1115
- @db[:t].all.must_equal [{:a=>1, :b=>4}]
1116
- @c.first.set(:b=>5).save
1117
- @db[:t].all.must_equal [{:a=>1, :b=>5}]
1118
- @c.first.set(:b=>6).save(:columns=>:b)
1119
- @db[:t].all.must_equal [{:a=>1, :b=>6}]
1120
- end
1121
-
1122
- it "should handle updating the primary key field with another field" do
1123
- @c.first.update(:a=>2, :b=>4)
1124
- @db[:t].all.must_equal [{:a=>2, :b=>4}]
1125
- end
1126
-
1127
- it "should handle updating just the primary key field when saving changes" do
1128
- @c.first.update(:a=>2)
1129
- @db[:t].all.must_equal [{:a=>2, :b=>3}]
1130
- @c.first.set(:a=>3).save(:columns=>:a)
1131
- @db[:t].all.must_equal [{:a=>3, :b=>3}]
1132
- end
1133
-
1134
- it "should handle saving after modifying the primary key field with another field" do
1135
- @c.first.set(:a=>2, :b=>4).save
1136
- @db[:t].all.must_equal [{:a=>2, :b=>4}]
1137
- end
1138
-
1139
- it "should handle saving after modifying just the primary key field" do
1140
- @c.first.set(:a=>2).save
1141
- @db[:t].all.must_equal [{:a=>2, :b=>3}]
1142
- end
1143
-
1144
- it "should handle saving after updating the primary key" do
1145
- @c.first.update(:a=>2).update(:b=>4).set(:b=>5).save
1146
- @db[:t].all.must_equal [{:a=>2, :b=>5}]
1147
- end
1148
- end
1149
-
1150
- describe "AssociationPks plugin" do
1151
- before(:all) do
1152
- @db = DB
1153
- @db.drop_table?(:albums_tags, :albums_vocalists, :vocalists_instruments, :vocalists_hits, :hits, :instruments, :vocalists, :tags, :albums, :artists)
1154
- @db.create_table(:artists) do
1155
- primary_key :id
1156
- String :name
1157
- end
1158
- @db.create_table(:albums) do
1159
- primary_key :id
1160
- String :name
1161
- foreign_key :artist_id, :artists
1162
- end
1163
- @db.create_table(:tags) do
1164
- primary_key :id
1165
- String :name
1166
- end
1167
- @db.create_table(:albums_tags) do
1168
- foreign_key :album_id, :albums
1169
- foreign_key :tag_id, :tags
1170
- end
1171
- @db.create_table(:vocalists) do
1172
- String :first
1173
- String :last
1174
- primary_key [:first, :last]
1175
- foreign_key :album_id, :albums
1176
- end
1177
- @db.create_table(:albums_vocalists) do
1178
- foreign_key :album_id, :albums
1179
- String :first
1180
- String :last
1181
- foreign_key [:first, :last], :vocalists
1182
- end
1183
- @db.create_table(:instruments) do
1184
- primary_key :id
1185
- String :first
1186
- String :last
1187
- foreign_key [:first, :last], :vocalists
1188
- end
1189
- @db.create_table(:vocalists_instruments) do
1190
- String :first
1191
- String :last
1192
- foreign_key [:first, :last], :vocalists
1193
- foreign_key :instrument_id, :instruments
1194
- end
1195
- @db.create_table(:hits) do
1196
- Integer :year
1197
- Integer :week
1198
- primary_key [:year, :week]
1199
- String :first
1200
- String :last
1201
- foreign_key [:first, :last], :vocalists
1202
- end
1203
- @db.create_table(:vocalists_hits) do
1204
- String :first
1205
- String :last
1206
- foreign_key [:first, :last], :vocalists
1207
- Integer :year
1208
- Integer :week
1209
- foreign_key [:year, :week], :hits
1210
- end
1211
- class ::Artist < Sequel::Model
1212
- plugin :association_pks
1213
- one_to_many :albums, :order=>:id, :delay_pks=>false
1214
- end
1215
- class ::Album < Sequel::Model
1216
- plugin :association_pks
1217
- many_to_many :tags, :order=>:id, :delay_pks=>false
1218
- many_to_many :uat_tags, :order=>Sequel[:tags][:id], :delay_pks=>false, :class=>:Tag, :right_key=>:tag_id, :association_pks_use_associated_table=>true
1219
- end
1220
- class ::Tag < Sequel::Model
1221
- end
1222
- class ::Vocalist < Sequel::Model
1223
- set_primary_key [:first, :last]
1224
- plugin :association_pks
1225
- end
1226
- class ::Instrument < Sequel::Model
1227
- plugin :association_pks
1228
- end
1229
- class ::Hit < Sequel::Model
1230
- set_primary_key [:year, :week]
1231
- end
1232
- end
1233
- before do
1234
- [:albums_tags, :albums_vocalists, :vocalists_instruments, :vocalists_hits, :hits, :instruments, :vocalists, :tags, :albums, :artists].each{|t| @db[t].delete}
1235
- @ar1 =@db[:artists].insert(:name=>'YJM')
1236
- @ar2 =@db[:artists].insert(:name=>'AS')
1237
- @al1 =@db[:albums].insert(:name=>'RF', :artist_id=>@ar1)
1238
- @al2 =@db[:albums].insert(:name=>'MO', :artist_id=>@ar1)
1239
- @al3 =@db[:albums].insert(:name=>'T', :artist_id=>@ar1)
1240
- @t1 = @db[:tags].insert(:name=>'A')
1241
- @t2 = @db[:tags].insert(:name=>'B')
1242
- @t3 = @db[:tags].insert(:name=>'C')
1243
- {@al1=>[@t1, @t2, @t3], @al2=>[@t2]}.each do |aid, tids|
1244
- tids.each{|tid| @db[:albums_tags].insert([aid, tid])}
1245
- end
1246
- @v1 = ['F1', 'L1']
1247
- @v2 = ['F2', 'L2']
1248
- @v3 = ['F3', 'L3']
1249
- @db[:vocalists].insert(@v1 + [@al1])
1250
- @db[:vocalists].insert(@v2 + [@al1])
1251
- @db[:vocalists].insert(@v3 + [@al1])
1252
- @i1 = @db[:instruments].insert([:first, :last], @v1)
1253
- @i2 = @db[:instruments].insert([:first, :last], @v1)
1254
- @i3 = @db[:instruments].insert([:first, :last], @v1)
1255
- @h1 = [1997, 1]
1256
- @h2 = [1997, 2]
1257
- @h3 = [1997, 3]
1258
- @db[:hits].insert(@h1 + @v1)
1259
- @db[:hits].insert(@h2 + @v1)
1260
- @db[:hits].insert(@h3 + @v1)
1261
- {@al1=>[@v1, @v2, @v3], @al2=>[@v2]}.each do |aid, vids|
1262
- vids.each{|vid| @db[:albums_vocalists].insert([aid] + vid)}
1263
- end
1264
- {@v1=>[@i1, @i2, @i3], @v2=>[@i2]}.each do |vid, iids|
1265
- iids.each{|iid| @db[:vocalists_instruments].insert(vid + [iid])}
1266
- end
1267
- {@v1=>[@h1, @h2, @h3], @v2=>[@h2]}.each do |vid, hids|
1268
- hids.each{|hid| @db[:vocalists_hits].insert(vid + hid)}
1269
- end
1270
- end
1271
- after(:all) do
1272
- @db.drop_table? :albums_tags, :albums_vocalists, :vocalists_instruments, :vocalists_hits, :hits, :instruments, :vocalists, :tags, :albums, :artists
1273
- [:Artist, :Album, :Tag, :Vocalist, :Instrument, :Hit].each{|s| Object.send(:remove_const, s)}
1274
- end
1275
-
1276
- it "should return correct associated pks for one_to_many associations" do
1277
- Artist.order(:id).all.map{|a| a.album_pks}.must_equal [[@al1, @al2, @al3], []]
1278
- end
1279
-
1280
- it "should return correct associated pks for many_to_many associations" do
1281
- Album.order(:id).all.map{|a| a.tag_pks.sort}.must_equal [[@t1, @t2, @t3], [@t2], []]
1282
- end
1283
-
1284
- it "should return correct associated pks for many_to_many associations using :association_pks_use_associated_table" do
1285
- Album.order(:id).all.map{|a| a.uat_tag_pks.sort}.must_equal [[@t1, @t2, @t3], [@t2], []]
1286
- end
1287
-
1288
- it "should return correct associated right-side cpks for one_to_many associations" do
1289
- Album.one_to_many :vocalists, :order=>:first
1290
- Album.order(:id).all.map{|a| a.vocalist_pks.sort}.must_equal [[@v1, @v2, @v3], [], []]
1291
- end
1292
-
1293
- it "should return correct associated right-side cpks for many_to_many associations" do
1294
- Album.many_to_many :vocalists, :join_table=>:albums_vocalists, :right_key=>[:first, :last], :order=>:first
1295
- Album.order(:id).all.map{|a| a.vocalist_pks.sort}.must_equal [[@v1, @v2, @v3], [@v2], []]
1296
- end
1297
-
1298
- it "should return correct associated right-side cpks for many_to_many associations when using :association_pks_use_associated_table" do
1299
- Album.many_to_many :vocalists, :join_table=>:albums_vocalists, :right_key=>[:first, :last], :order=>Sequel[:vocalists][:first], :association_pks_use_associated_table=>true
1300
- Album.order(:id).all.map{|a| a.vocalist_pks.sort}.must_equal [[@v1, @v2, @v3], [@v2], []]
1301
- end
1302
-
1303
- it "should return correct associated pks for left-side cpks for one_to_many associations" do
1304
- Vocalist.one_to_many :instruments, :key=>[:first, :last], :order=>:id
1305
- Vocalist.order(:first, :last).all.map{|a| a.instrument_pks.sort}.must_equal [[@i1, @i2, @i3], [], []]
1306
- end
1307
-
1308
- it "should return correct associated pks for left-side cpks for many_to_many associations" do
1309
- Vocalist.many_to_many :instruments, :join_table=>:vocalists_instruments, :left_key=>[:first, :last], :order=>:id
1310
- Vocalist.order(:first, :last).all.map{|a| a.instrument_pks.sort}.must_equal [[@i1, @i2, @i3], [@i2], []]
1311
- end
1312
-
1313
- it "should return correct associated pks for left-side cpks for many_to_many associations when using :association_pks_use_associated_table" do
1314
- Vocalist.many_to_many :instruments, :join_table=>:vocalists_instruments, :left_key=>[:first, :last], :order=>:id, :association_pks_use_associated_table=>true
1315
- Vocalist.order(:first, :last).all.map{|a| a.instrument_pks.sort}.must_equal [[@i1, @i2, @i3], [@i2], []]
1316
- end
1317
-
1318
- it "should return correct associated right-side cpks for left-side cpks for one_to_many associations" do
1319
- Vocalist.one_to_many :hits, :key=>[:first, :last], :order=>:week
1320
- Vocalist.order(:first, :last).all.map{|a| a.hit_pks.sort}.must_equal [[@h1, @h2, @h3], [], []]
1321
- end
1322
-
1323
- it "should return correct associated right-side cpks for left-side cpks for many_to_many associations" do
1324
- Vocalist.many_to_many :hits, :join_table=>:vocalists_hits, :left_key=>[:first, :last], :right_key=>[:year, :week], :order=>:week
1325
- Vocalist.order(:first, :last).all.map{|a| a.hit_pks.sort}.must_equal [[@h1, @h2, @h3], [@h2], []]
1326
- end
1327
-
1328
- it "should return correct associated right-side cpks for left-side cpks for many_to_many associations when using :association_pks_use_associated_table" do
1329
- Vocalist.many_to_many :hits, :join_table=>:vocalists_hits, :left_key=>[:first, :last], :right_key=>[:year, :week], :order=>Sequel[:vocalists_hits][:week], :association_pks_use_associated_table=>true
1330
- Vocalist.order(:first, :last).all.map{|a| a.hit_pks.sort}.must_equal [[@h1, @h2, @h3], [@h2], []]
1331
- end
1332
-
1333
- it "should default to delaying association_pks setter method changes until saving" do
1334
- album_class = Class.new(Album)
1335
- album_class.many_to_many :tags, :clone=>:tags, :delay_pks=>true, :join_table=>:albums_tags, :left_key=>:album_id
1336
- album = album_class.with_pk!(@al1)
1337
- album.tag_pks.sort.must_equal [@t1, @t2, @t3]
1338
- album.tag_pks = [@t1, @t2]
1339
- album.tag_pks.must_equal [@t1, @t2]
1340
- album.save_changes
1341
- album_class.with_pk!(album.pk).tag_pks.sort.must_equal [@t1, @t2]
1342
-
1343
- album.tag_pks = []
1344
- album.tag_pks.must_equal []
1345
- album.save_changes
1346
- album_class.with_pk!(album.pk).tag_pks.sort.must_equal []
1347
- end
1348
-
1349
- it "should set associated pks correctly for a one_to_many association" do
1350
- Artist.use_transactions = true
1351
- Album.order(:id).select_map(:artist_id).must_equal [@ar1, @ar1, @ar1]
1352
-
1353
- Artist[@ar2].album_pks = [@al1, @al3]
1354
- Artist[@ar1].album_pks.must_equal [@al2]
1355
- Album.order(:id).select_map(:artist_id).must_equal [@ar2, @ar1, @ar2]
1356
-
1357
- Artist[@ar1].album_pks = [@al1]
1358
- Artist[@ar2].album_pks.must_equal [@al3]
1359
- Album.order(:id).select_map(:artist_id).must_equal [@ar1, nil, @ar2]
1360
-
1361
- Artist[@ar1].album_pks = [@al1, @al2]
1362
- Artist[@ar2].album_pks.must_equal [@al3]
1363
- Album.order(:id).select_map(:artist_id).must_equal [@ar1, @ar1, @ar2]
1364
-
1365
- Artist[@ar1].album_pks = []
1366
- Album.order(:id).select_map(:artist_id).must_equal [nil, nil, @ar2]
1367
- end
1368
-
1369
- it "should set associated pks correctly for a many_to_many association" do
1370
- Artist.use_transactions = true
1371
- @db[:albums_tags].filter(:album_id=>@al1).select_order_map(:tag_id).must_equal [@t1, @t2, @t3]
1372
- Album[@al1].tag_pks = [@t1, @t3]
1373
- @db[:albums_tags].filter(:album_id=>@al1).select_order_map(:tag_id).must_equal [@t1, @t3]
1374
- Album[@al1].tag_pks = []
1375
- @db[:albums_tags].filter(:album_id=>@al1).select_order_map(:tag_id).must_equal []
1376
-
1377
- @db[:albums_tags].filter(:album_id=>@al2).select_order_map(:tag_id).must_equal [@t2]
1378
- Album[@al2].tag_pks = [@t1, @t2]
1379
- @db[:albums_tags].filter(:album_id=>@al2).select_order_map(:tag_id).must_equal [@t1, @t2]
1380
- Album[@al2].tag_pks = []
1381
- @db[:albums_tags].filter(:album_id=>@al1).select_order_map(:tag_id).must_equal []
1382
-
1383
- @db[:albums_tags].filter(:album_id=>@al3).select_order_map(:tag_id).must_equal []
1384
- Album[@al3].tag_pks = [@t1, @t3]
1385
- @db[:albums_tags].filter(:album_id=>@al3).select_order_map(:tag_id).must_equal [@t1, @t3]
1386
- Album[@al3].tag_pks = []
1387
- @db[:albums_tags].filter(:album_id=>@al1).select_order_map(:tag_id).must_equal []
1388
- end
1389
-
1390
- it "should set associated right-side cpks correctly for a one_to_many association" do
1391
- Album.use_transactions = true
1392
- Album.one_to_many :vocalists, :order=>:first, :delay_pks=>false
1393
- Album.order(:id).all.map{|a| a.vocalist_pks.sort}.must_equal [[@v1, @v2, @v3], [], []]
1394
-
1395
- Album[@al2].vocalist_pks = [@v1, @v3]
1396
- Album[@al1].vocalist_pks.must_equal [@v2]
1397
- Vocalist.order(:first, :last).select_map(:album_id).must_equal [@al2, @al1, @al2]
1398
-
1399
- Album[@al1].vocalist_pks = [@v1]
1400
- Album[@al2].vocalist_pks.must_equal [@v3]
1401
- Vocalist.order(:first, :last).select_map(:album_id).must_equal [@al1, nil, @al2]
1402
-
1403
- Album[@al1].vocalist_pks = [@v1, @v2]
1404
- Album[@al2].vocalist_pks.must_equal [@v3]
1405
- Vocalist.order(:first, :last).select_map(:album_id).must_equal [@al1, @al1, @al2]
1406
-
1407
- Album[@al1].vocalist_pks = []
1408
- Vocalist.order(:first, :last).select_map(:album_id).must_equal [nil, nil, @al2]
1409
- end
1410
-
1411
- it "should set associated right-side cpks correctly for a many_to_many association" do
1412
- Album.use_transactions = true
1413
- Album.many_to_many :vocalists, :join_table=>:albums_vocalists, :right_key=>[:first, :last], :order=>:first, :delay_pks=>false
1414
-
1415
- @db[:albums_vocalists].filter(:album_id=>@al1).select_order_map([:first, :last]).must_equal [@v1, @v2, @v3]
1416
- Album[@al1].vocalist_pks = [@v1, @v3]
1417
- @db[:albums_vocalists].filter(:album_id=>@al1).select_order_map([:first, :last]).must_equal [@v1, @v3]
1418
- Album[@al1].vocalist_pks = []
1419
- @db[:albums_vocalists].filter(:album_id=>@al1).select_order_map([:first, :last]).must_equal []
1420
-
1421
- @db[:albums_vocalists].filter(:album_id=>@al2).select_order_map([:first, :last]).must_equal [@v2]
1422
- Album[@al2].vocalist_pks = [@v1, @v2]
1423
- @db[:albums_vocalists].filter(:album_id=>@al2).select_order_map([:first, :last]).must_equal [@v1, @v2]
1424
- Album[@al2].vocalist_pks = []
1425
- @db[:albums_vocalists].filter(:album_id=>@al1).select_order_map([:first, :last]).must_equal []
1426
-
1427
- @db[:albums_vocalists].filter(:album_id=>@al3).select_order_map([:first, :last]).must_equal []
1428
- Album[@al3].vocalist_pks = [@v1, @v3]
1429
- @db[:albums_vocalists].filter(:album_id=>@al3).select_order_map([:first, :last]).must_equal [@v1, @v3]
1430
- Album[@al3].vocalist_pks = []
1431
- @db[:albums_vocalists].filter(:album_id=>@al1).select_order_map([:first, :last]).must_equal []
1432
- end
1433
-
1434
- it "should set associated pks correctly with left-side cpks for a one_to_many association" do
1435
- Vocalist.use_transactions = true
1436
- Vocalist.one_to_many :instruments, :key=>[:first, :last], :order=>:id, :delay_pks=>false
1437
- Vocalist.order(:first, :last).all.map{|a| a.instrument_pks.sort}.must_equal [[@i1, @i2, @i3], [], []]
1438
-
1439
- Vocalist[@v2].instrument_pks = [@i1, @i3]
1440
- Vocalist[@v1].instrument_pks.must_equal [@i2]
1441
- Instrument.order(:id).select_map([:first, :last]).must_equal [@v2, @v1, @v2]
1442
-
1443
- Vocalist[@v1].instrument_pks = [@i1]
1444
- Vocalist[@v2].instrument_pks.must_equal [@i3]
1445
- Instrument.order(:id).select_map([:first, :last]).must_equal [@v1, [nil, nil], @v2]
1446
-
1447
- Vocalist[@v1].instrument_pks = [@i1, @i2]
1448
- Vocalist[@v2].instrument_pks.must_equal [@i3]
1449
- Instrument.order(:id).select_map([:first, :last]).must_equal [@v1, @v1, @v2]
1450
-
1451
- Vocalist[@v1].instrument_pks = []
1452
- Instrument.order(:id).select_map([:first, :last]).must_equal [[nil, nil], [nil, nil], @v2]
1453
- end
1454
-
1455
- it "should set associated pks correctly with left-side cpks for a many_to_many association" do
1456
- Vocalist.use_transactions = true
1457
- Vocalist.many_to_many :instruments, :join_table=>:vocalists_instruments, :left_key=>[:first, :last], :order=>:id, :delay_pks=>false
1458
-
1459
- @db[:vocalists_instruments].filter([:first, :last]=>[@v1]).select_order_map(:instrument_id).must_equal [@i1, @i2, @i3]
1460
- Vocalist[@v1].instrument_pks = [@i1, @i3]
1461
- @db[:vocalists_instruments].filter([:first, :last]=>[@v1]).select_order_map(:instrument_id).must_equal [@i1, @i3]
1462
- Vocalist[@v1].instrument_pks = []
1463
- @db[:vocalists_instruments].filter([:first, :last]=>[@v1]).select_order_map(:instrument_id).must_equal []
1464
-
1465
- @db[:vocalists_instruments].filter([:first, :last]=>[@v2]).select_order_map(:instrument_id).must_equal [@i2]
1466
- Vocalist[@v2].instrument_pks = [@i1, @i2]
1467
- @db[:vocalists_instruments].filter([:first, :last]=>[@v2]).select_order_map(:instrument_id).must_equal [@i1, @i2]
1468
- Vocalist[@v2].instrument_pks = []
1469
- @db[:vocalists_instruments].filter([:first, :last]=>[@v1]).select_order_map(:instrument_id).must_equal []
1470
-
1471
- @db[:vocalists_instruments].filter([:first, :last]=>[@v3]).select_order_map(:instrument_id).must_equal []
1472
- Vocalist[@v3].instrument_pks = [@i1, @i3]
1473
- @db[:vocalists_instruments].filter([:first, :last]=>[@v3]).select_order_map(:instrument_id).must_equal [@i1, @i3]
1474
- Vocalist[@v3].instrument_pks = []
1475
- @db[:vocalists_instruments].filter([:first, :last]=>[@v1]).select_order_map(:instrument_id).must_equal []
1476
- end
1477
-
1478
- it "should set associated right-side cpks correctly with left-side cpks for a one_to_many association" do
1479
- Vocalist.use_transactions = true
1480
- Vocalist.one_to_many :hits, :key=>[:first, :last], :order=>:week, :delay_pks=>false
1481
- Vocalist.order(:first, :last).all.map{|a| a.hit_pks.sort}.must_equal [[@h1, @h2, @h3], [], []]
1482
-
1483
- Vocalist[@v2].hit_pks = [@h1, @h3]
1484
- Vocalist[@v1].hit_pks.must_equal [@h2]
1485
- Hit.order(:year, :week).select_map([:first, :last]).must_equal [@v2, @v1, @v2]
1486
-
1487
- Vocalist[@v1].hit_pks = [@h1]
1488
- Vocalist[@v2].hit_pks.must_equal [@h3]
1489
- Hit.order(:year, :week).select_map([:first, :last]).must_equal [@v1, [nil, nil], @v2]
1490
-
1491
- Vocalist[@v1].hit_pks = [@h1, @h2]
1492
- Vocalist[@v2].hit_pks.must_equal [@h3]
1493
- Hit.order(:year, :week).select_map([:first, :last]).must_equal [@v1, @v1, @v2]
1494
-
1495
- Vocalist[@v1].hit_pks = []
1496
- Hit.order(:year, :week).select_map([:first, :last]).must_equal [[nil, nil], [nil, nil], @v2]
1497
- end
1498
-
1499
- it "should set associated right-side cpks correctly with left-side cpks for a many_to_many association" do
1500
- Vocalist.use_transactions = true
1501
- Vocalist.many_to_many :hits, :join_table=>:vocalists_hits, :left_key=>[:first, :last], :right_key=>[:year, :week], :order=>:week, :delay_pks=>false
1502
-
1503
- @db[:vocalists_hits].filter([:first, :last]=>[@v1]).select_order_map([:year, :week]).must_equal [@h1, @h2, @h3]
1504
- Vocalist[@v1].hit_pks = [@h1, @h3]
1505
- @db[:vocalists_hits].filter([:first, :last]=>[@v1]).select_order_map([:year, :week]).must_equal [@h1, @h3]
1506
- Vocalist[@v1].hit_pks = []
1507
- @db[:vocalists_hits].filter([:first, :last]=>[@v1]).select_order_map([:year, :week]).must_equal []
1508
-
1509
- @db[:vocalists_hits].filter([:first, :last]=>[@v2]).select_order_map([:year, :week]).must_equal [@h2]
1510
- Vocalist[@v2].hit_pks = [@h1, @h2]
1511
- @db[:vocalists_hits].filter([:first, :last]=>[@v2]).select_order_map([:year, :week]).must_equal [@h1, @h2]
1512
- Vocalist[@v2].hit_pks = []
1513
- @db[:vocalists_hits].filter([:first, :last]=>[@v1]).select_order_map([:year, :week]).must_equal []
1514
-
1515
- @db[:vocalists_hits].filter([:first, :last]=>[@v3]).select_order_map([:year, :week]).must_equal []
1516
- Vocalist[@v3].hit_pks = [@h1, @h3]
1517
- @db[:vocalists_hits].filter([:first, :last]=>[@v3]).select_order_map([:year, :week]).must_equal [@h1, @h3]
1518
- Vocalist[@v3].hit_pks = []
1519
- @db[:vocalists_hits].filter([:first, :last]=>[@v1]).select_order_map([:year, :week]).must_equal []
1520
- end
1521
- end
1522
-
1523
- describe "List plugin without a scope" do
1524
- before(:all) do
1525
- @db = DB
1526
- @db.create_table!(:sites) do
1527
- primary_key :id
1528
- String :name
1529
- Integer :position
1530
- end
1531
-
1532
- @c = Class.new(Sequel::Model(@db[:sites]))
1533
- @c.plugin :list
1534
- end
1535
- before do
1536
- @c.dataset.delete
1537
- @c.create :name => "abc"
1538
- @c.create :name => "def"
1539
- @c.create :name => "hig"
1540
- end
1541
- after(:all) do
1542
- @db.drop_table?(:sites)
1543
- end
1544
-
1545
- it "should return rows in order of position" do
1546
- @c.map(:position).must_equal [1,2,3]
1547
- @c.map(:name).must_equal %w[ abc def hig ]
1548
- end
1549
-
1550
- it "should define prev and next" do
1551
- i = @c[:name => "abc"]
1552
- i.prev.must_be_nil
1553
- i = @c[:name => "def"]
1554
- i.prev.must_equal @c[:name => "abc"]
1555
- i.next.must_equal @c[:name => "hig"]
1556
- i = @c[:name => "hig"]
1557
- i.next.must_be_nil
1558
- end
1559
-
1560
- it "should define move_to" do
1561
- @c[:name => "def"].move_to(1)
1562
- @c.map(:name).must_equal %w[ def abc hig ]
1563
-
1564
- @c[:name => "abc"].move_to(3)
1565
- @c.map(:name).must_equal %w[ def hig abc ]
1566
-
1567
- @c[:name => "abc"].move_to(-1)
1568
- @c.map(:name).must_equal %w[ abc def hig ]
1569
- @c[:name => "abc"].move_to(10)
1570
- @c.map(:name).must_equal %w[ def hig abc ]
1571
- end
1572
-
1573
- it "should define move_to_top and move_to_bottom" do
1574
- @c[:name => "def"].move_to_top
1575
- @c.map(:name).must_equal %w[ def abc hig ]
1576
-
1577
- @c[:name => "def"].move_to_bottom
1578
- @c.map(:name).must_equal %w[ abc hig def ]
1579
- end
1580
-
1581
- it "should define move_up and move_down" do
1582
- @c[:name => "def"].move_up
1583
- @c.map(:name).must_equal %w[ def abc hig ]
1584
-
1585
- @c[:name => "abc"].move_down
1586
- @c.map(:name).must_equal %w[ def hig abc ]
1587
-
1588
- @c[:name => "abc"].move_up(2)
1589
- @c.map(:name).must_equal %w[ abc def hig ]
1590
-
1591
- @c[:name => "abc"].move_down(2)
1592
- @c.map(:name).must_equal %w[ def hig abc ]
1593
-
1594
- @c[:name => "abc"].move_up(10)
1595
- @c.map(:name).must_equal %w[ abc def hig ]
1596
- @c[:name => "abc"].move_down(10)
1597
- @c.map(:name).must_equal %w[ def hig abc ]
1598
- end
1599
-
1600
- it "should update positions on destroy" do
1601
- @c[:name => "def"].destroy
1602
- @c.select_map([:position, :name]).must_equal [[1, 'abc'], [2, 'hig']]
1603
- end
1604
- end
1605
-
1606
- describe "List plugin with a scope" do
1607
- before(:all) do
1608
- @db = DB
1609
- @db.create_table!(:pages) do
1610
- primary_key :id
1611
- String :name
1612
- Integer :pos
1613
- Integer :parent_id
1614
- end
1615
-
1616
- @c = Class.new(Sequel::Model(@db[:pages]))
1617
- @c.plugin :list, :field => :pos, :scope => :parent_id
1618
- end
1619
- before do
1620
- @c.dataset.delete
1621
- p1 = @c.create :name => "Hm", :parent_id => 0
1622
- p2 = @c.create :name => "Ps", :parent_id => p1.id
1623
- @c.create :name => "P1", :parent_id => p2.id
1624
- @c.create :name => "P2", :parent_id => p2.id
1625
- @c.create :name => "P3", :parent_id => p2.id
1626
- @c.create :name => "Au", :parent_id => p1.id
1627
- end
1628
- after(:all) do
1629
- @db.drop_table?(:pages)
1630
- end
1631
-
1632
- it "should return rows in order of position" do
1633
- @c.map(:name).must_equal %w[ Hm Ps Au P1 P2 P3 ]
1634
- end
1635
-
1636
- it "should define prev and next" do
1637
- @c[:name => "Ps"].next.name.must_equal 'Au'
1638
- @c[:name => "Au"].prev.name.must_equal 'Ps'
1639
- @c[:name => "P1"].next.name.must_equal 'P2'
1640
- @c[:name => "P2"].prev.name.must_equal 'P1'
1641
-
1642
- @c[:name => "P1"].next(2).name.must_equal 'P3'
1643
- @c[:name => "P2"].next(-1).name.must_equal 'P1'
1644
- @c[:name => "P3"].prev(2).name.must_equal 'P1'
1645
- @c[:name => "P2"].prev(-1).name.must_equal 'P3'
1646
-
1647
- @c[:name => "Ps"].prev.must_be_nil
1648
- @c[:name => "Au"].next.must_be_nil
1649
- @c[:name => "P1"].prev.must_be_nil
1650
- @c[:name => "P3"].next.must_be_nil
1651
- end
1652
-
1653
- it "should define move_to" do
1654
- @c[:name => "P2"].move_to(1)
1655
- @c.map(:name).must_equal %w[ Hm Ps Au P2 P1 P3 ]
1656
-
1657
- @c[:name => "P2"].move_to(3)
1658
- @c.map(:name).must_equal %w[ Hm Ps Au P1 P3 P2 ]
1659
-
1660
- @c[:name => "P2"].move_to(-1)
1661
- @c.map(:name).must_equal %w[ Hm Ps Au P2 P1 P3 ]
1662
- @c[:name => "P2"].move_to(10)
1663
- @c.map(:name).must_equal %w[ Hm Ps Au P1 P3 P2 ]
1664
- end
1665
-
1666
- it "should define move_to_top and move_to_bottom" do
1667
- @c[:name => "Au"].move_to_top
1668
- @c.map(:name).must_equal %w[ Hm Au Ps P1 P2 P3 ]
1669
-
1670
- @c[:name => "Au"].move_to_bottom
1671
- @c.map(:name).must_equal %w[ Hm Ps Au P1 P2 P3 ]
1672
- end
1673
-
1674
- it "should define move_up and move_down" do
1675
- @c[:name => "P2"].move_up
1676
- @c.map(:name).must_equal %w[ Hm Ps Au P2 P1 P3 ]
1677
-
1678
- @c[:name => "P1"].move_down
1679
- @c.map(:name).must_equal %w[ Hm Ps Au P2 P3 P1 ]
1680
-
1681
- @c[:name => "P1"].move_up(10)
1682
- @c.map(:name).must_equal %w[ Hm Ps Au P1 P2 P3 ]
1683
- @c[:name => "P1"].move_down(10)
1684
- @c.map(:name).must_equal %w[ Hm Ps Au P2 P3 P1 ]
1685
- end
1686
-
1687
- it "should update positions on destroy" do
1688
- @c[:name => "P2"].destroy
1689
- @c.select_order_map([:pos, :name]).must_equal [[1, "Hm"], [1, "P1"], [1, "Ps"], [2, "Au"], [2, "P3"]]
1690
- end
1691
- end
1692
-
1693
- describe "Sequel::Plugins::Tree" do
1694
- TreePluginSpecs = shared_description do
1695
- it "should instantiate" do
1696
- @Node.all.size.must_equal 12
1697
- end
1698
-
1699
- it "should find all descendants of a node" do
1700
- @Node.find(:name => 'two').descendants.map{|m| m.name}.must_equal %w'two.one two.two two.three two.two.one'
1701
- end
1702
-
1703
- it "should find all ancestors of a node" do
1704
- @Node.find(:name => "two.two.one").ancestors.map{|m| m.name}.must_equal %w'two.two two'
1705
- end
1706
-
1707
- it "should find all siblings of a node, excepting self" do
1708
- @Node.find(:name=>"two.one").siblings.map{|m| m.name}.must_equal %w'two.two two.three'
1709
- end
1710
-
1711
- it "should find all siblings of a node, including self" do
1712
- @Node.find(:name=>"two.one").self_and_siblings.map{|m| m.name}.must_equal %w'two.one two.two two.three'
1713
- end
1714
-
1715
- it "should find siblings for root nodes" do
1716
- @Node.find(:name=>'three').self_and_siblings.map{|m| m.name}.must_equal %w'one two three four five'
1717
- end
1718
-
1719
- it "should find correct root for a node" do
1720
- @Node.find(:name=>"two.two.one").root.name.must_equal 'two'
1721
- @Node.find(:name=>"three").root.name.must_equal 'three'
1722
- @Node.find(:name=>"five.one").root.name.must_equal 'five'
1723
- end
1724
-
1725
- it "iterate top-level nodes in order" do
1726
- @Node.roots_dataset.count.must_equal 5
1727
- @Node.roots.map(&:name).must_equal %w'one two three four five'
1728
- @Node.where(:name=>%w'one two.one').roots_dataset.count.must_equal 1
1729
- @Node.where(:name=>%w'one two.one').roots.map(&:name).must_equal %w'one'
1730
- end
1731
-
1732
- it "should have children" do
1733
- @Node.find(:name=>'one').children.map{|m| m.name}.must_equal %w'one.one one.two'
1734
- end
1735
- end
1736
-
1737
- describe "with simple key" do
1738
- before(:all) do
1739
- @db = DB
1740
- @db.create_table!(:nodes) do
1741
- Integer :id, :primary_key=>true
1742
- String :name
1743
- Integer :parent_id
1744
- Integer :position
1745
- end
1746
-
1747
- @nodes = [{:id => 1, :name => 'one', :parent_id => nil, :position => 1},
1748
- {:id => 2, :name => 'two', :parent_id => nil, :position => 2},
1749
- {:id => 3, :name => 'three', :parent_id => nil, :position => 3},
1750
- {:id => 4, :name => "two.one", :parent_id => 2, :position => 1},
1751
- {:id => 5, :name => "two.two", :parent_id => 2, :position => 2},
1752
- {:id => 6, :name => "two.two.one", :parent_id => 5, :position => 1},
1753
- {:id => 7, :name => "one.two", :parent_id => 1, :position => 2},
1754
- {:id => 8, :name => "one.one", :parent_id => 1, :position => 1},
1755
- {:id => 9, :name => "five", :parent_id => nil, :position => 5},
1756
- {:id => 10, :name => "four", :parent_id => nil, :position => 4},
1757
- {:id => 11, :name => "five.one", :parent_id => 9, :position => 1},
1758
- {:id => 12, :name => "two.three", :parent_id => 2, :position => 3}]
1759
- @nodes.each{|node| @db[:nodes].insert(node)}
1760
-
1761
- @Node = Class.new(Sequel::Model(:nodes))
1762
- @Node.plugin :tree, :order=>:position
1763
- end
1764
- after(:all) do
1765
- @db.drop_table?(:nodes)
1766
- end
1767
-
1768
- include TreePluginSpecs
1769
- end
1770
-
1771
- describe "with composite key" do
1772
- before(:all) do
1773
- @db = DB
1774
- @db.create_table!(:nodes) do
1775
- Integer :id
1776
- Integer :id2
1777
- String :name
1778
- Integer :parent_id
1779
- Integer :parent_id2
1780
- Integer :position
1781
- primary_key [:id, :id2]
1782
- end
1783
-
1784
- @nodes = [{:id => 1, :id2=> 1, :name => 'one', :parent_id => nil, :parent_id2 => nil, :position => 1},
1785
- {:id => 2, :id2=> 1, :name => 'two', :parent_id => nil, :parent_id2 => nil, :position => 2},
1786
- {:id => 1, :id2=> 2, :name => 'three', :parent_id => nil, :parent_id2 => nil, :position => 3},
1787
- {:id => 2, :id2=> 2, :name => "two.one", :parent_id => 2, :parent_id2 => 1, :position => 1},
1788
- {:id => 3, :id2=> 1, :name => "two.two", :parent_id => 2, :parent_id2 => 1, :position => 2},
1789
- {:id => 3, :id2=> 2, :name => "two.two.one", :parent_id => 3, :parent_id2 => 1, :position => 1},
1790
- {:id => 3, :id2=> 3, :name => "one.two", :parent_id => 1, :parent_id2 => 1, :position => 2},
1791
- {:id => 1, :id2=> 3, :name => "one.one", :parent_id => 1, :parent_id2 => 1, :position => 1},
1792
- {:id => 2, :id2=> 3, :name => "five", :parent_id => nil, :parent_id2 => nil, :position => 5},
1793
- {:id => 4, :id2=> 1, :name => "four", :parent_id => nil, :parent_id2 => nil, :position => 4},
1794
- {:id => 1, :id2=> 4, :name => "five.one", :parent_id => 2, :parent_id2 => 3, :position => 1},
1795
- {:id => 2, :id2=> 4, :name => "two.three", :parent_id => 2, :parent_id2 => 1, :position => 3}]
1796
- @nodes.each{|node| @db[:nodes].insert(node)}
1797
-
1798
- @Node = Class.new(Sequel::Model(:nodes))
1799
- @Node.plugin :tree, :order=>:position, :key=>[:parent_id, :parent_id2]
1800
- end
1801
- after(:all) do
1802
- @db.drop_table?(:nodes)
1803
- end
1804
-
1805
- include TreePluginSpecs
1806
- end
1807
- end
1808
-
1809
- describe "Sequel::Plugins::UpdateRefresh" do
1810
- before(:all) do
1811
- @db = DB
1812
- @db.create_table!(:tests) do
1813
- primary_key :id
1814
- String :name
1815
- Integer :i
1816
- end
1817
- @c = Class.new(Sequel::Model(@db[:tests]))
1818
- @c.plugin :update_refresh
1819
- end
1820
- before do
1821
- @c.dataset.delete
1822
- @foo = @c.create(:name=>'foo', :i=>10)
1823
- end
1824
- after(:all) do
1825
- @db.drop_table?(:tests)
1826
- end
1827
-
1828
- it "should refresh when updating" do
1829
- @foo.this.update(:i=>20)
1830
- @foo.update(:name=>'bar')
1831
- @foo.name.must_equal 'bar'
1832
- @foo.i.must_equal 20
1833
- end
1834
- end
1835
-
1836
- describe "Sequel::Plugins::PreparedStatements" do
1837
- before(:all) do
1838
- @db = DB
1839
- @db.create_table!(:ps_test) do
1840
- primary_key :id
1841
- String :name
1842
- Integer :i
1843
- end
1844
- @c = Class.new(Sequel::Model(@db[:ps_test]))
1845
- end
1846
- before do
1847
- @c.dataset.delete
1848
- @foo = @c.create(:name=>'foo', :i=>10)
1849
- @bar = @c.create(:name=>'bar', :i=>20)
1850
- end
1851
- after(:all) do
1852
- @db.drop_table?(:ps_test)
1853
- end
1854
-
1855
- it "should work with looking up using Model.[]" do
1856
- @c[@foo.id].must_equal @foo
1857
- @c[@bar.id].must_equal @bar
1858
- @c[0].must_be_nil
1859
- @c[nil].must_be_nil
1860
- end
1861
-
1862
- it "should work with looking up using Dataset#with_pk" do
1863
- @c.dataset.with_pk(@foo.id).must_equal @foo
1864
- @c.dataset.with_pk(@bar.id).must_equal @bar
1865
- @c.dataset.with_pk(0).must_be_nil
1866
- @c.dataset.with_pk(nil).must_be_nil
1867
-
1868
- @c.dataset.filter(:i=>0).with_pk(@foo.id).must_be_nil
1869
- @c.dataset.filter(:i=>10).with_pk(@foo.id).must_equal @foo
1870
- @c.dataset.filter(:i=>20).with_pk(@bar.id).must_equal @bar
1871
- @c.dataset.filter(:i=>10).with_pk(nil).must_be_nil
1872
- @c.dataset.filter(:name=>'foo').with_pk(@foo.id).must_equal @foo
1873
- @c.dataset.filter(:name=>'bar').with_pk(@bar.id).must_equal @bar
1874
- @c.dataset.filter(:name=>'baz').with_pk(@bar.id).must_be_nil
1875
- @c.dataset.filter(:name=>'bar').with_pk(nil).must_be_nil
1876
- end
1877
-
1878
- it "should work with Model#destroy" do
1879
- @foo.destroy
1880
- @bar.destroy
1881
- @c[@foo.id].must_be_nil
1882
- @c[@bar.id].must_be_nil
1883
- end
1884
-
1885
- it "should work with Model#update" do
1886
- @foo.update(:name=>'foo2', :i=>30)
1887
- @c[@foo.id].must_equal @c.load(:id=>@foo.id, :name=>'foo2', :i=>30)
1888
- @foo.update(:name=>'foo3')
1889
- @c[@foo.id].must_equal @c.load(:id=>@foo.id, :name=>'foo3', :i=>30)
1890
- @foo.update(:i=>40)
1891
- @c[@foo.id].must_equal @c.load(:id=>@foo.id, :name=>'foo3', :i=>40)
1892
- @foo.update(:i=>nil)
1893
- @c[@foo.id].must_equal @c.load(:id=>@foo.id, :name=>'foo3', :i=>nil)
1894
- end
1895
-
1896
- it "should work with Model#create" do
1897
- o = @c.create(:name=>'foo2', :i=>30)
1898
- @c[o.id].must_equal @c.load(:id=>o.id, :name=>'foo2', :i=>30)
1899
- o = @c.create(:name=>'foo2')
1900
- @c[o.id].must_equal @c.load(:id=>o.id, :name=>'foo2', :i=>nil)
1901
- o = @c.create(:i=>30)
1902
- @c[o.id].must_equal @c.load(:id=>o.id, :name=>nil, :i=>30)
1903
- o = @c.create(:name=>nil, :i=>40)
1904
- @c[o.id].must_equal @c.load(:id=>o.id, :name=>nil, :i=>40)
1905
- end
1906
- end
1907
-
1908
- describe "Sequel::Plugins::PreparedStatements with schema changes" do
1909
- before do
1910
- @db = DB
1911
- @db.create_table!(:ps_test) do
1912
- primary_key :id
1913
- String :name
1914
- end
1915
- @c = Class.new(Sequel::Model(@db[:ps_test]))
1916
- @c.many_to_one :ps_test, :key=>:id, :class=>@c
1917
- @c.one_to_many :ps_tests, :key=>:id, :class=>@c
1918
- @c.many_to_many :mps_tests, :left_key=>:id, :right_key=>:id, :class=>@c, :join_table=>Sequel[:ps_test].as(:x)
1919
- @c.plugin :prepared_statements
1920
- end
1921
- after do
1922
- @db.drop_table?(:ps_test)
1923
- end
1924
-
1925
- it "should handle added columns" do
1926
- foo = @c.create(:name=>'foo')
1927
- @c[foo.id].name.must_equal 'foo'
1928
- foo.ps_test.name.must_equal 'foo'
1929
- foo.ps_tests.map{|x| x.name}.must_equal %w'foo'
1930
- foo.mps_tests.map{|x| x.name}.must_equal %w'foo'
1931
- foo.update(:name=>'foo2')
1932
- @c[foo.id].name.must_equal 'foo2'
1933
- foo.delete
1934
- foo.exists?.must_equal false
1935
-
1936
- @db.alter_table(:ps_test){add_column :i, Integer}
1937
-
1938
- foo = @c.create(:name=>'foo')
1939
- @c[foo.id].name.must_equal 'foo'
1940
- foo.ps_test.name.must_equal 'foo'
1941
- foo.ps_tests.map{|x| x.name}.must_equal %w'foo'
1942
- foo.mps_tests.map{|x| x.name}.must_equal %w'foo'
1943
- foo.update(:name=>'foo2')
1944
- @c[foo.id].name.must_equal 'foo2'
1945
- foo.delete
1946
- foo.exists?.must_equal false
1947
- end
1948
- end
1949
-
1950
- describe "Caching plugins" do
1951
- before(:all) do
1952
- @db = DB
1953
- @db.drop_table?(:albums, :artists)
1954
- @db.create_table(:artists) do
1955
- primary_key :id
1956
- end
1957
- @db.create_table(:albums) do
1958
- primary_key :id
1959
- foreign_key :artist_id, :artists
1960
- end
1961
- @db[:artists].insert
1962
- @db[:albums].insert(:artist_id=>1)
1963
- end
1964
- before do
1965
- @Album = Class.new(Sequel::Model(@db[:albums]))
1966
- end
1967
- after(:all) do
1968
- @db.drop_table?(:albums, :artists)
1969
- end
1970
-
1971
- CachingPluginSpecs = shared_description do
1972
- it "should work with looking up using Model.[]" do
1973
- @Artist[1].must_be_same_as(@Artist[1])
1974
- @Artist[:id=>1].must_equal @Artist[1]
1975
- @Artist[0].must_be_nil
1976
- @Artist[nil].must_be_nil
1977
- end
1978
-
1979
- it "should work with lookup up many_to_one associated objects" do
1980
- a = @Artist[1]
1981
- @Album.first.artist.must_be_same_as(a)
1982
- end
1983
- end
1984
-
1985
- describe "caching plugin" do
1986
- before do
1987
- @cache_class = Class.new(Hash) do
1988
- def set(k, v, ttl) self[k] = v end
1989
- alias get []
1990
- end
1991
- @cache = @cache_class.new
1992
-
1993
- @Artist = Class.new(Sequel::Model(@db[:artists]))
1994
- @Artist.plugin :caching, @cache
1995
- @Album.many_to_one :artist, :class=>@Artist
1996
- end
1997
-
1998
- include CachingPluginSpecs
1999
- end
2000
-
2001
- describe "static_cache plugin" do
2002
- before do
2003
- @Artist = Class.new(Sequel::Model(@db[:artists]))
2004
- @Artist.plugin :static_cache
2005
- @Album.many_to_one :artist, :class=>@Artist
2006
- end
2007
-
2008
- include CachingPluginSpecs
2009
-
2010
- it "should have first retrieve correct values" do
2011
- @Artist.first.must_equal @Artist.load(:id=>1)
2012
- @Artist.first(1).must_equal [@Artist.load(:id=>1)]
2013
- @Artist.first(:id=>1).must_equal @Artist.load(:id=>1)
2014
- @Artist.first{id =~ 1}.must_equal @Artist.load(:id=>1)
2015
- end
2016
- end
2017
- end
2018
-
2019
- describe "Sequel::Plugins::ConstraintValidations" do
2020
- before(:all) do
2021
- @db = DB
2022
- @db.extension(:constraint_validations) unless @db.frozen?
2023
- @db.drop_table?(:sequel_constraint_validations)
2024
- @db.create_constraint_validations_table
2025
- @ds = @db[:cv_test]
2026
- @regexp = regexp = @db.dataset.supports_regexp?
2027
- @validation_opts = {}
2028
- opts_proc = proc{@validation_opts}
2029
- @validate_block = proc do |opts|
2030
- opts = opts_proc.call
2031
- presence :pre, opts.merge(:name=>:p)
2032
- exact_length 5, :exactlen, opts.merge(:name=>:el)
2033
- min_length 5, :minlen, opts.merge(:name=>:minl)
2034
- max_length 5, :maxlen, opts.merge(:name=>:maxl)
2035
- length_range 3..5, :lenrange, opts.merge(:name=>:lr)
2036
- if regexp
2037
- format(/^foo\d+/, :form, opts.merge(:name=>:f))
2038
- end
2039
- like 'foo%', :lik, opts.merge(:name=>:l)
2040
- ilike 'foo%', :ilik, opts.merge(:name=>:il)
2041
- includes %w'abc def', :inc, opts.merge(:name=>:i)
2042
- unique :uniq, opts.merge(:name=>:u)
2043
- max_length 6, :minlen, opts.merge(:name=>:maxl2)
2044
- operator :<, 'm', :exactlen, opts.merge(:name=>:lt)
2045
- operator :>=, 5, :num, opts.merge(:name=>:gte)
2046
- presence [:m1, :m2, :m3], opts.merge(:name=>:pm)
2047
- end
2048
- @valid_row = {:pre=>'a', :exactlen=>'12345', :minlen=>'12345', :maxlen=>'12345', :lenrange=>'1234', :lik=>'fooabc', :ilik=>'FooABC', :inc=>'abc', :uniq=>'u', :num=>5, :m1=>'a', :m2=>1, :m3=>'a'}
2049
- @violations = [
2050
- [:pre, [nil, '', ' ']],
2051
- [:exactlen, [nil, '', '1234', '123456', 'n1234']],
2052
- [:minlen, [nil, '', '1234']],
2053
- [:maxlen, [nil, '123456']],
2054
- [:lenrange, [nil, '', '12', '123456']],
2055
- [:lik, [nil, '', 'fo', 'fotabc', 'FOOABC']],
2056
- [:ilik, [nil, '', 'fo', 'fotabc']],
2057
- [:inc, [nil, '', 'ab', 'abcd']],
2058
- [:num, [nil, 3, 4]],
2059
- ]
2060
-
2061
- if @regexp
2062
- @valid_row[:form] = 'foo1'
2063
- @violations << [:form, [nil, '', 'foo', 'fooa']]
2064
- end
2065
- end
2066
- after(:all) do
2067
- @db.drop_constraint_validations_table
2068
- end
2069
-
2070
- ConstraintValidationsSpecs = shared_description do
2071
- cspecify "should set up constraints that work even outside the model", [proc{|db| !db.mariadb? || db.server_version <= 100200}, :mysql] do
2072
- @ds.insert(@valid_row)
2073
-
2074
- # Test for unique constraint
2075
- proc{@ds.insert(@valid_row)}.must_raise(Sequel::DatabaseError)
2076
-
2077
- @ds.delete
2078
- @violations.each do |col, vals|
2079
- try = @valid_row.dup
2080
- vals += ['1234567'] if col == :minlen
2081
- vals.each do |val|
2082
- next if val.nil? && @validation_opts[:allow_nil]
2083
- next if val == '' && @validation_opts[:allow_nil] && @db.database_type == :oracle
2084
- try[col] = val
2085
- proc{@ds.insert(try)}.must_raise(Sequel::DatabaseError)
2086
- end
2087
- end
2088
-
2089
- try = @valid_row.dup
2090
- if @validation_opts[:allow_nil]
2091
- [:m1, :m2, :m3].each do |c|
2092
- @ds.insert(try.merge(c=>nil))
2093
- @ds.delete
2094
- end
2095
- @ds.insert(try.merge(:m1=>nil, :m2=>nil))
2096
- @ds.delete
2097
- @ds.insert(try.merge(:m1=>nil, :m3=>nil))
2098
- @ds.delete
2099
- @ds.insert(try.merge(:m2=>nil, :m3=>nil))
2100
- @ds.delete
2101
- @ds.insert(try.merge(:m1=>nil, :m2=>nil, :m3=>nil))
2102
- @ds.delete
2103
- else
2104
- [:m1, :m2, :m3].each do |c|
2105
- proc{@ds.insert(try.merge(c=>nil))}.must_raise(Sequel::DatabaseError)
2106
- end
2107
- proc{@ds.insert(try.merge(:m1=>nil, :m2=>nil))}.must_raise(Sequel::DatabaseError)
2108
- proc{@ds.insert(try.merge(:m1=>nil, :m3=>nil))}.must_raise(Sequel::DatabaseError)
2109
- proc{@ds.insert(try.merge(:m2=>nil, :m3=>nil))}.must_raise(Sequel::DatabaseError)
2110
- proc{@ds.insert(try.merge(:m1=>nil, :m2=>nil, :m3=>nil))}.must_raise(Sequel::DatabaseError)
2111
- end
2112
-
2113
- unless @db.database_type == :oracle
2114
- [:m1, :m3].each do |c|
2115
- proc{@ds.insert(try.merge(c=>''))}.must_raise(Sequel::DatabaseError)
2116
- end
2117
- proc{@ds.insert(try.merge(:m1=>'', :m3=>''))}.must_raise(Sequel::DatabaseError)
2118
- proc{@ds.insert(try.merge(:m1=>'', :m2=>nil))}.must_raise(Sequel::DatabaseError)
2119
- proc{@ds.insert(try.merge(:m1=>nil, :m3=>''))}.must_raise(Sequel::DatabaseError)
2120
- proc{@ds.insert(try.merge(:m2=>nil, :m3=>''))}.must_raise(Sequel::DatabaseError)
2121
- proc{@ds.insert(try.merge(:m1=>'', :m2=>nil, :m3=>''))}.must_raise(Sequel::DatabaseError)
2122
- end
2123
-
2124
- # Test for dropping of constraint
2125
- @db.alter_table(:cv_test){validate{drop :maxl2}}
2126
- @ds.insert(@valid_row.merge(:minlen=>'1234567'))
2127
- end
2128
-
2129
- it "should set up automatic validations inside the model" do
2130
- skip if @db.frozen?
2131
- c = Class.new(Sequel::Model(@ds))
2132
- c.plugin :constraint_validations
2133
- c.dataset.delete
2134
- c.create(@valid_row)
2135
-
2136
- # Test for unique validation
2137
- c.new(@valid_row).wont_be :valid?
2138
-
2139
- c.dataset.delete
2140
- @violations.each do |col, vals|
2141
- try = @valid_row.dup
2142
- vals.each do |val|
2143
- next if val.nil? && @validation_opts[:allow_nil]
2144
- try[col] = val
2145
- c.new(try).wont_be :valid?
2146
- end
2147
- end
2148
-
2149
- try = @valid_row.dup
2150
- if @validation_opts[:allow_nil]
2151
- [:m1, :m2, :m3].each do |col|
2152
- c.new(try.merge(col=>nil)).must_be :valid?
2153
- end
2154
- c.new(try.merge(:m1=>nil, :m2=>nil)).must_be :valid?
2155
- c.new(try.merge(:m1=>nil, :m3=>nil)).must_be :valid?
2156
- c.new(try.merge(:m2=>nil, :m3=>nil)).must_be :valid?
2157
- c.new(try.merge(:m1=>nil, :m2=>nil, :m3=>nil)).must_be :valid?
2158
- else
2159
- [:m1, :m2, :m3].each do |col|
2160
- c.new(try.merge(col=>nil)).wont_be :valid?
2161
- end
2162
- c.new(try.merge(:m1=>nil, :m2=>nil)).wont_be :valid?
2163
- c.new(try.merge(:m1=>nil, :m3=>nil)).wont_be :valid?
2164
- c.new(try.merge(:m2=>nil, :m3=>nil)).wont_be :valid?
2165
- c.new(try.merge(:m1=>nil, :m2=>nil, :m3=>nil)).wont_be :valid?
2166
- end
2167
- c.new(try.merge(:m1=>'', :m2=>nil)).wont_be :valid?
2168
- c.new(try.merge(:m1=>nil, :m3=>'')).wont_be :valid?
2169
- c.new(try.merge(:m2=>nil, :m3=>'')).wont_be :valid?
2170
- c.new(try.merge(:m1=>'', :m2=>nil, :m3=>'')).wont_be :valid?
2171
- [:m1, :m3].each do |col|
2172
- c.new(try.merge(col=>'')).wont_be :valid?
2173
- end
2174
- c.new(try.merge(:m1=>'', :m3=>'')).wont_be :valid?
2175
-
2176
- c.db.constraint_validations = nil
2177
- end
2178
- end
2179
-
2180
- describe "via create_table" do
2181
- before(:all) do
2182
- @table_block = proc do
2183
- regexp = @regexp
2184
- validate_block = @validate_block
2185
- @db.create_table!(:cv_test) do
2186
- primary_key :id
2187
- String :pre
2188
- String :exactlen
2189
- String :minlen
2190
- String :maxlen
2191
- String :lenrange
2192
- if regexp
2193
- String :form
2194
- end
2195
- String :lik
2196
- String :ilik
2197
- String :inc
2198
- String :uniq, :null=>false
2199
- Integer :num
2200
- String :m1
2201
- Integer :m2
2202
- String :m3
2203
- validate(&validate_block)
2204
- end
2205
- end
2206
- end
2207
- after(:all) do
2208
- @db.drop_table?(:cv_test)
2209
- @db.drop_constraint_validations_for(:table=>:cv_test)
2210
- end
2211
-
2212
- describe "with :allow_nil=>true" do
2213
- before(:all) do
2214
- @validation_opts = {:allow_nil=>true}
2215
- @table_block.call
2216
- end
2217
- include ConstraintValidationsSpecs
2218
- end
2219
- describe "with :allow_nil=>false" do
2220
- before(:all) do
2221
- @table_block.call
2222
- end
2223
- include ConstraintValidationsSpecs
2224
- end
2225
- end
2226
-
2227
- describe "via alter_table" do
2228
- before(:all) do
2229
- @table_block = proc do
2230
- regexp = @regexp
2231
- validate_block = @validate_block
2232
- @db.create_table!(:cv_test) do
2233
- primary_key :id
2234
- String :lik
2235
- String :ilik
2236
- String :inc
2237
- String :uniq, :null=>false
2238
- end
2239
- @db.alter_table(:cv_test) do
2240
- add_column :pre, String
2241
- add_column :exactlen, String
2242
- add_column :minlen, String
2243
- add_column :maxlen, String
2244
- add_column :lenrange, String
2245
- if regexp
2246
- add_column :form, String
2247
- end
2248
- add_column :num, Integer
2249
- add_column :m1, String
2250
- add_column :m2, Integer
2251
- add_column :m3, String
2252
- validate(&validate_block)
2253
- end
2254
- end
2255
- end
2256
- after(:all) do
2257
- @db.drop_table?(:cv_test)
2258
- @db.drop_constraint_validations_for(:table=>:cv_test)
2259
- end
2260
-
2261
- describe "with :allow_nil=>true" do
2262
- before(:all) do
2263
- @validation_opts = {:allow_nil=>true}
2264
- @table_block.call
2265
- end
2266
- include ConstraintValidationsSpecs
2267
- end
2268
- describe "with :allow_nil=>false" do
2269
- before(:all) do
2270
- @table_block.call
2271
- end
2272
- include ConstraintValidationsSpecs
2273
- end
2274
- end
2275
- end
2276
-
2277
- describe "date_arithmetic extension" do
2278
- asd = begin
2279
- require 'active_support/duration'
2280
- require 'active_support/inflector'
2281
- require 'active_support/core_ext/string/inflections'
2282
- true
2283
- rescue LoadError
2284
- false
2285
- end
2286
-
2287
- before(:all) do
2288
- @db = DB
2289
- @db.extension(:date_arithmetic) unless @db.frozen?
2290
- skip if @db.database_type == :sqlite && @db.frozen?
2291
- if @db.database_type == :sqlite
2292
- @db.use_timestamp_timezones = false
2293
- end
2294
- @date = Date.civil(2010, 7, 12)
2295
- @dt = Time.local(2010, 7, 12)
2296
- if asd
2297
- @d0 = ActiveSupport::Duration.new(0, [[:days, 0]])
2298
- @d1 = ActiveSupport::Duration.new(1, [[:days, 1]])
2299
- @d2 = ActiveSupport::Duration.new(1, [[:years, 1], [:months, 1], [:days, 1], [:minutes, 61], [:seconds, 1]])
2300
- end
2301
- @h0 = {:days=>0}
2302
- @h1 = {:days=>1, :years=>nil, :hours=>0}
2303
- @h2 = {:years=>1, :months=>1, :days=>1, :hours=>1, :minutes=>1, :seconds=>1}
2304
- @a1 = Time.local(2010, 7, 13)
2305
- @a2 = Time.local(2011, 8, 13, 1, 1, 1)
2306
- @s1 = Time.local(2010, 7, 11)
2307
- @s2 = Time.local(2009, 6, 10, 22, 58, 59)
2308
- @check = lambda do |meth, in_date, in_interval, should|
2309
- output = @db.get(Sequel.send(meth, in_date, in_interval))
2310
- output = Time.parse(output.to_s) unless output.is_a?(Time) || output.is_a?(DateTime)
2311
- output.year.must_equal should.year
2312
- output.month.must_equal should.month
2313
- output.day.must_equal should.day
2314
- output.hour.must_equal should.hour
2315
- output.min.must_equal should.min
2316
- output.sec.must_equal should.sec
2317
- end
2318
- end
2319
- after(:all) do
2320
- if @db.database_type == :sqlite
2321
- @db.use_timestamp_timezones = true
2322
- end
2323
- end
2324
-
2325
- if asd
2326
- it "be able to use Sequel.date_add to add ActiveSupport::Duration objects to dates and datetimes" do
2327
- @check.call(:date_add, @date, @d0, @dt)
2328
- @check.call(:date_add, @date, @d1, @a1)
2329
- @check.call(:date_add, @date, @d2, @a2)
2330
-
2331
- @check.call(:date_add, @dt, @d0, @dt)
2332
- @check.call(:date_add, @dt, @d1, @a1)
2333
- @check.call(:date_add, @dt, @d2, @a2)
2334
- end
2335
-
2336
- it "be able to use Sequel.date_sub to subtract ActiveSupport::Duration objects from dates and datetimes" do
2337
- @check.call(:date_sub, @date, @d0, @dt)
2338
- @check.call(:date_sub, @date, @d1, @s1)
2339
- @check.call(:date_sub, @date, @d2, @s2)
2340
-
2341
- @check.call(:date_sub, @dt, @d0, @dt)
2342
- @check.call(:date_sub, @dt, @d1, @s1)
2343
- @check.call(:date_sub, @dt, @d2, @s2)
2344
- end
2345
- end
2346
-
2347
- it "be able to use Sequel.date_add to add interval hashes to dates and datetimes" do
2348
- @check.call(:date_add, @date, @h0, @dt)
2349
- @check.call(:date_add, @date, @h1, @a1)
2350
- @check.call(:date_add, @date, @h2, @a2)
2351
-
2352
- @check.call(:date_add, @dt, @h0, @dt)
2353
- @check.call(:date_add, @dt, @h1, @a1)
2354
- @check.call(:date_add, @dt, @h2, @a2)
2355
- end
2356
-
2357
- it "be able to use Sequel.date_sub to subtract interval hashes from dates and datetimes" do
2358
- @check.call(:date_sub, @date, @h0, @dt)
2359
- @check.call(:date_sub, @date, @h1, @s1)
2360
- @check.call(:date_sub, @date, @h2, @s2)
2361
-
2362
- @check.call(:date_sub, @dt, @h0, @dt)
2363
- @check.call(:date_sub, @dt, @h1, @s1)
2364
- @check.call(:date_sub, @dt, @h2, @s2)
2365
- end
2366
- end
2367
-
2368
- describe "string_agg extension" do
2369
- before(:all) do
2370
- @db = DB
2371
- @db.extension(:string_agg) unless @db.frozen?
2372
- @db.create_table!(:string_agg_test) do
2373
- Integer :id
2374
- String :s
2375
- Integer :o
2376
- end
2377
- @db[:string_agg_test].import([:id, :s, :o], [[1, 'a', 3], [1, 'a', 3], [1, 'b', 5], [1, 'c', 4], [2, 'aa', 2], [2, 'bb', 1]])
2378
- @ds = @db[:string_agg_test].select_group(:id).order(:id)
2379
- end
2380
- after(:all) do
2381
- @db.drop_table?(:string_agg_test)
2382
- end
2383
-
2384
- cspecify "should have string_agg return aggregated concatenation", :mssql, :sqlite, :derby do
2385
- h = @ds.select_append(Sequel.string_agg(:s).as(:v)).to_hash(:id, :v)
2386
- h[1].must_match(/\A[abc],[abc],[abc],[abc]\z/)
2387
- h[2].must_match(/\A(aa|bb),(aa|bb)\z/)
2388
-
2389
- @ds.select_append(Sequel.string_agg(:s).order(:o).as(:v)).map([:id, :v]).must_equal [[1, 'a,a,c,b'], [2, 'bb,aa']]
2390
- @ds.select_append(Sequel.string_agg(:s, '-').order(:o).as(:v)).map([:id, :v]).must_equal [[1, 'a-a-c-b'], [2, 'bb-aa']]
2391
- end
2392
-
2393
- cspecify "should have string_agg return aggregated concatenation for distinct values", :mssql, :sqlite, :oracle, :db2, :derby do
2394
- @ds.select_group(:id).select_append(Sequel.string_agg(:s).order(:s).distinct.as(:v)).map([:id, :v]).must_equal [[1, 'a,b,c'], [2, 'aa,bb']]
2395
- end
2396
- end