sequel 5.8.0 → 5.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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