sequel 5.29.0 → 5.30.0

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