sequel 5.8.0 → 5.38.0

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