sequel 5.28.0 → 5.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (380) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +64 -1922
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/doc/advanced_associations.rdoc +4 -4
  6. data/doc/association_basics.rdoc +3 -3
  7. data/doc/code_order.rdoc +12 -2
  8. data/doc/model_dataset_method_design.rdoc +1 -1
  9. data/doc/postgresql.rdoc +71 -0
  10. data/doc/release_notes/5.29.0.txt +22 -0
  11. data/doc/release_notes/5.30.0.txt +20 -0
  12. data/doc/release_notes/5.31.0.txt +148 -0
  13. data/doc/release_notes/5.32.0.txt +46 -0
  14. data/doc/release_notes/5.33.0.txt +24 -0
  15. data/doc/testing.rdoc +1 -1
  16. data/lib/sequel/adapters/postgres.rb +5 -1
  17. data/lib/sequel/adapters/shared/access.rb +6 -6
  18. data/lib/sequel/adapters/shared/mssql.rb +5 -5
  19. data/lib/sequel/adapters/shared/mysql.rb +10 -10
  20. data/lib/sequel/adapters/shared/oracle.rb +16 -16
  21. data/lib/sequel/adapters/shared/postgres.rb +169 -14
  22. data/lib/sequel/adapters/shared/sqlanywhere.rb +9 -9
  23. data/lib/sequel/adapters/shared/sqlite.rb +32 -5
  24. data/lib/sequel/adapters/tinytds.rb +1 -1
  25. data/lib/sequel/connection_pool/sharded_threaded.rb +2 -2
  26. data/lib/sequel/connection_pool/threaded.rb +1 -1
  27. data/lib/sequel/core.rb +318 -314
  28. data/lib/sequel/database/query.rb +1 -1
  29. data/lib/sequel/database/schema_generator.rb +1 -1
  30. data/lib/sequel/database/transactions.rb +8 -12
  31. data/lib/sequel/dataset/misc.rb +2 -2
  32. data/lib/sequel/extensions/connection_expiration.rb +2 -2
  33. data/lib/sequel/extensions/connection_validator.rb +2 -2
  34. data/lib/sequel/extensions/fiber_concurrency.rb +24 -0
  35. data/lib/sequel/extensions/index_caching.rb +9 -7
  36. data/lib/sequel/extensions/integer64.rb +2 -0
  37. data/lib/sequel/extensions/migration.rb +1 -1
  38. data/lib/sequel/extensions/pg_enum.rb +5 -2
  39. data/lib/sequel/extensions/pg_hstore.rb +6 -0
  40. data/lib/sequel/extensions/pg_inet.rb +13 -5
  41. data/lib/sequel/extensions/pg_interval.rb +2 -0
  42. data/lib/sequel/extensions/pg_range.rb +2 -0
  43. data/lib/sequel/extensions/pg_timestamptz.rb +2 -0
  44. data/lib/sequel/extensions/run_transaction_hooks.rb +72 -0
  45. data/lib/sequel/extensions/schema_dumper.rb +10 -4
  46. data/lib/sequel/extensions/server_block.rb +3 -3
  47. data/lib/sequel/model/associations.rb +18 -5
  48. data/lib/sequel/model/base.rb +60 -53
  49. data/lib/sequel/model/plugins.rb +1 -0
  50. data/lib/sequel/plugins/association_lazy_eager_option.rb +66 -0
  51. data/lib/sequel/plugins/association_multi_add_remove.rb +2 -0
  52. data/lib/sequel/plugins/association_proxies.rb +2 -0
  53. data/lib/sequel/plugins/boolean_subsets.rb +4 -1
  54. data/lib/sequel/plugins/class_table_inheritance.rb +26 -26
  55. data/lib/sequel/plugins/dirty.rb +13 -13
  56. data/lib/sequel/plugins/empty_failure_backtraces.rb +38 -0
  57. data/lib/sequel/plugins/forbid_lazy_load.rb +214 -0
  58. data/lib/sequel/plugins/json_serializer.rb +18 -11
  59. data/lib/sequel/plugins/single_table_inheritance.rb +15 -15
  60. data/lib/sequel/plugins/skip_saving_columns.rb +108 -0
  61. data/lib/sequel/plugins/subclasses.rb +2 -0
  62. data/lib/sequel/plugins/throw_failures.rb +1 -1
  63. data/lib/sequel/timezones.rb +6 -4
  64. data/lib/sequel/version.rb +1 -1
  65. metadata +18 -367
  66. data/Rakefile +0 -151
  67. data/doc/release_notes/4.0.0.txt +0 -262
  68. data/doc/release_notes/4.1.0.txt +0 -85
  69. data/doc/release_notes/4.10.0.txt +0 -226
  70. data/doc/release_notes/4.11.0.txt +0 -147
  71. data/doc/release_notes/4.12.0.txt +0 -105
  72. data/doc/release_notes/4.13.0.txt +0 -169
  73. data/doc/release_notes/4.14.0.txt +0 -68
  74. data/doc/release_notes/4.15.0.txt +0 -56
  75. data/doc/release_notes/4.16.0.txt +0 -36
  76. data/doc/release_notes/4.17.0.txt +0 -38
  77. data/doc/release_notes/4.18.0.txt +0 -36
  78. data/doc/release_notes/4.19.0.txt +0 -45
  79. data/doc/release_notes/4.2.0.txt +0 -129
  80. data/doc/release_notes/4.20.0.txt +0 -79
  81. data/doc/release_notes/4.21.0.txt +0 -94
  82. data/doc/release_notes/4.22.0.txt +0 -72
  83. data/doc/release_notes/4.23.0.txt +0 -65
  84. data/doc/release_notes/4.24.0.txt +0 -99
  85. data/doc/release_notes/4.25.0.txt +0 -181
  86. data/doc/release_notes/4.26.0.txt +0 -44
  87. data/doc/release_notes/4.27.0.txt +0 -78
  88. data/doc/release_notes/4.28.0.txt +0 -57
  89. data/doc/release_notes/4.29.0.txt +0 -41
  90. data/doc/release_notes/4.3.0.txt +0 -40
  91. data/doc/release_notes/4.30.0.txt +0 -37
  92. data/doc/release_notes/4.31.0.txt +0 -57
  93. data/doc/release_notes/4.32.0.txt +0 -132
  94. data/doc/release_notes/4.33.0.txt +0 -88
  95. data/doc/release_notes/4.34.0.txt +0 -86
  96. data/doc/release_notes/4.35.0.txt +0 -130
  97. data/doc/release_notes/4.36.0.txt +0 -116
  98. data/doc/release_notes/4.37.0.txt +0 -50
  99. data/doc/release_notes/4.38.0.txt +0 -67
  100. data/doc/release_notes/4.39.0.txt +0 -127
  101. data/doc/release_notes/4.4.0.txt +0 -92
  102. data/doc/release_notes/4.40.0.txt +0 -179
  103. data/doc/release_notes/4.41.0.txt +0 -77
  104. data/doc/release_notes/4.42.0.txt +0 -221
  105. data/doc/release_notes/4.43.0.txt +0 -87
  106. data/doc/release_notes/4.44.0.txt +0 -125
  107. data/doc/release_notes/4.45.0.txt +0 -370
  108. data/doc/release_notes/4.46.0.txt +0 -404
  109. data/doc/release_notes/4.47.0.txt +0 -56
  110. data/doc/release_notes/4.48.0.txt +0 -293
  111. data/doc/release_notes/4.49.0.txt +0 -222
  112. data/doc/release_notes/4.5.0.txt +0 -34
  113. data/doc/release_notes/4.6.0.txt +0 -30
  114. data/doc/release_notes/4.7.0.txt +0 -103
  115. data/doc/release_notes/4.8.0.txt +0 -175
  116. data/doc/release_notes/4.9.0.txt +0 -190
  117. data/spec/adapter_spec.rb +0 -4
  118. data/spec/adapters/db2_spec.rb +0 -170
  119. data/spec/adapters/mssql_spec.rb +0 -828
  120. data/spec/adapters/mysql_spec.rb +0 -1060
  121. data/spec/adapters/oracle_spec.rb +0 -371
  122. data/spec/adapters/postgres_spec.rb +0 -4476
  123. data/spec/adapters/spec_helper.rb +0 -44
  124. data/spec/adapters/sqlanywhere_spec.rb +0 -97
  125. data/spec/adapters/sqlite_spec.rb +0 -652
  126. data/spec/bin_spec.rb +0 -278
  127. data/spec/core/connection_pool_spec.rb +0 -1250
  128. data/spec/core/database_spec.rb +0 -2915
  129. data/spec/core/dataset_spec.rb +0 -5547
  130. data/spec/core/deprecated_spec.rb +0 -70
  131. data/spec/core/expression_filters_spec.rb +0 -1498
  132. data/spec/core/mock_adapter_spec.rb +0 -722
  133. data/spec/core/object_graph_spec.rb +0 -336
  134. data/spec/core/placeholder_literalizer_spec.rb +0 -166
  135. data/spec/core/schema_generator_spec.rb +0 -214
  136. data/spec/core/schema_spec.rb +0 -1844
  137. data/spec/core/spec_helper.rb +0 -24
  138. data/spec/core/version_spec.rb +0 -14
  139. data/spec/core_extensions_spec.rb +0 -763
  140. data/spec/core_model_spec.rb +0 -2
  141. data/spec/core_spec.rb +0 -1
  142. data/spec/deprecation_helper.rb +0 -30
  143. data/spec/extensions/accessed_columns_spec.rb +0 -51
  144. data/spec/extensions/active_model_spec.rb +0 -99
  145. data/spec/extensions/after_initialize_spec.rb +0 -28
  146. data/spec/extensions/any_not_empty_spec.rb +0 -23
  147. data/spec/extensions/arbitrary_servers_spec.rb +0 -109
  148. data/spec/extensions/association_dependencies_spec.rb +0 -125
  149. data/spec/extensions/association_multi_add_remove_spec.rb +0 -1041
  150. data/spec/extensions/association_pks_spec.rb +0 -423
  151. data/spec/extensions/association_proxies_spec.rb +0 -100
  152. data/spec/extensions/auto_literal_strings_spec.rb +0 -205
  153. data/spec/extensions/auto_validations_spec.rb +0 -229
  154. data/spec/extensions/blacklist_security_spec.rb +0 -95
  155. data/spec/extensions/blank_spec.rb +0 -69
  156. data/spec/extensions/boolean_readers_spec.rb +0 -93
  157. data/spec/extensions/boolean_subsets_spec.rb +0 -47
  158. data/spec/extensions/caching_spec.rb +0 -273
  159. data/spec/extensions/caller_logging_spec.rb +0 -52
  160. data/spec/extensions/class_table_inheritance_spec.rb +0 -750
  161. data/spec/extensions/column_conflicts_spec.rb +0 -75
  162. data/spec/extensions/column_select_spec.rb +0 -129
  163. data/spec/extensions/columns_introspection_spec.rb +0 -90
  164. data/spec/extensions/columns_updated_spec.rb +0 -35
  165. data/spec/extensions/composition_spec.rb +0 -248
  166. data/spec/extensions/connection_expiration_spec.rb +0 -151
  167. data/spec/extensions/connection_validator_spec.rb +0 -144
  168. data/spec/extensions/constant_sql_override_spec.rb +0 -24
  169. data/spec/extensions/constraint_validations_plugin_spec.rb +0 -300
  170. data/spec/extensions/constraint_validations_spec.rb +0 -439
  171. data/spec/extensions/core_refinements_spec.rb +0 -528
  172. data/spec/extensions/csv_serializer_spec.rb +0 -183
  173. data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
  174. data/spec/extensions/dataset_associations_spec.rb +0 -365
  175. data/spec/extensions/dataset_source_alias_spec.rb +0 -51
  176. data/spec/extensions/date_arithmetic_spec.rb +0 -181
  177. data/spec/extensions/datetime_parse_to_time_spec.rb +0 -169
  178. data/spec/extensions/def_dataset_method_spec.rb +0 -100
  179. data/spec/extensions/defaults_setter_spec.rb +0 -150
  180. data/spec/extensions/delay_add_association_spec.rb +0 -73
  181. data/spec/extensions/dirty_spec.rb +0 -222
  182. data/spec/extensions/duplicate_columns_handler_spec.rb +0 -104
  183. data/spec/extensions/eager_each_spec.rb +0 -62
  184. data/spec/extensions/eager_graph_eager_spec.rb +0 -100
  185. data/spec/extensions/empty_array_consider_nulls_spec.rb +0 -24
  186. data/spec/extensions/error_splitter_spec.rb +0 -18
  187. data/spec/extensions/error_sql_spec.rb +0 -20
  188. data/spec/extensions/escaped_like_spec.rb +0 -40
  189. data/spec/extensions/eval_inspect_spec.rb +0 -81
  190. data/spec/extensions/exclude_or_null_spec.rb +0 -15
  191. data/spec/extensions/finder_spec.rb +0 -260
  192. data/spec/extensions/force_encoding_spec.rb +0 -126
  193. data/spec/extensions/freeze_datasets_spec.rb +0 -31
  194. data/spec/extensions/graph_each_spec.rb +0 -113
  195. data/spec/extensions/hook_class_methods_spec.rb +0 -402
  196. data/spec/extensions/identifier_mangling_spec.rb +0 -201
  197. data/spec/extensions/implicit_subquery_spec.rb +0 -58
  198. data/spec/extensions/index_caching_spec.rb +0 -66
  199. data/spec/extensions/inflector_spec.rb +0 -183
  200. data/spec/extensions/input_transformer_spec.rb +0 -69
  201. data/spec/extensions/insert_conflict_spec.rb +0 -103
  202. data/spec/extensions/insert_returning_select_spec.rb +0 -72
  203. data/spec/extensions/instance_filters_spec.rb +0 -79
  204. data/spec/extensions/instance_hooks_spec.rb +0 -246
  205. data/spec/extensions/integer64_spec.rb +0 -22
  206. data/spec/extensions/inverted_subsets_spec.rb +0 -33
  207. data/spec/extensions/json_serializer_spec.rb +0 -336
  208. data/spec/extensions/lazy_attributes_spec.rb +0 -183
  209. data/spec/extensions/list_spec.rb +0 -291
  210. data/spec/extensions/looser_typecasting_spec.rb +0 -43
  211. data/spec/extensions/many_through_many_spec.rb +0 -2177
  212. data/spec/extensions/migration_spec.rb +0 -864
  213. data/spec/extensions/modification_detection_spec.rb +0 -93
  214. data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -92
  215. data/spec/extensions/named_timezones_spec.rb +0 -218
  216. data/spec/extensions/nested_attributes_spec.rb +0 -815
  217. data/spec/extensions/null_dataset_spec.rb +0 -85
  218. data/spec/extensions/optimistic_locking_spec.rb +0 -127
  219. data/spec/extensions/pagination_spec.rb +0 -116
  220. data/spec/extensions/pg_array_associations_spec.rb +0 -802
  221. data/spec/extensions/pg_array_ops_spec.rb +0 -144
  222. data/spec/extensions/pg_array_spec.rb +0 -398
  223. data/spec/extensions/pg_auto_constraint_validations_spec.rb +0 -209
  224. data/spec/extensions/pg_enum_spec.rb +0 -118
  225. data/spec/extensions/pg_extended_date_support_spec.rb +0 -126
  226. data/spec/extensions/pg_hstore_ops_spec.rb +0 -238
  227. data/spec/extensions/pg_hstore_spec.rb +0 -219
  228. data/spec/extensions/pg_inet_ops_spec.rb +0 -102
  229. data/spec/extensions/pg_inet_spec.rb +0 -72
  230. data/spec/extensions/pg_interval_spec.rb +0 -103
  231. data/spec/extensions/pg_json_ops_spec.rb +0 -356
  232. data/spec/extensions/pg_json_spec.rb +0 -451
  233. data/spec/extensions/pg_loose_count_spec.rb +0 -23
  234. data/spec/extensions/pg_range_ops_spec.rb +0 -60
  235. data/spec/extensions/pg_range_spec.rb +0 -600
  236. data/spec/extensions/pg_row_ops_spec.rb +0 -61
  237. data/spec/extensions/pg_row_plugin_spec.rb +0 -60
  238. data/spec/extensions/pg_row_spec.rb +0 -363
  239. data/spec/extensions/pg_static_cache_updater_spec.rb +0 -93
  240. data/spec/extensions/pg_timestamptz_spec.rb +0 -17
  241. data/spec/extensions/prepared_statements_safe_spec.rb +0 -66
  242. data/spec/extensions/prepared_statements_spec.rb +0 -177
  243. data/spec/extensions/pretty_table_spec.rb +0 -123
  244. data/spec/extensions/query_spec.rb +0 -94
  245. data/spec/extensions/rcte_tree_spec.rb +0 -387
  246. data/spec/extensions/round_timestamps_spec.rb +0 -39
  247. data/spec/extensions/s_spec.rb +0 -60
  248. data/spec/extensions/schema_caching_spec.rb +0 -64
  249. data/spec/extensions/schema_dumper_spec.rb +0 -870
  250. data/spec/extensions/select_remove_spec.rb +0 -38
  251. data/spec/extensions/sequel_4_dataset_methods_spec.rb +0 -121
  252. data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
  253. data/spec/extensions/serialization_spec.rb +0 -365
  254. data/spec/extensions/server_block_spec.rb +0 -135
  255. data/spec/extensions/server_logging_spec.rb +0 -45
  256. data/spec/extensions/sharding_spec.rb +0 -197
  257. data/spec/extensions/shared_caching_spec.rb +0 -151
  258. data/spec/extensions/single_table_inheritance_spec.rb +0 -347
  259. data/spec/extensions/singular_table_names_spec.rb +0 -22
  260. data/spec/extensions/skip_create_refresh_spec.rb +0 -18
  261. data/spec/extensions/spec_helper.rb +0 -70
  262. data/spec/extensions/split_array_nil_spec.rb +0 -24
  263. data/spec/extensions/split_values_spec.rb +0 -57
  264. data/spec/extensions/sql_comments_spec.rb +0 -33
  265. data/spec/extensions/sql_expr_spec.rb +0 -59
  266. data/spec/extensions/static_cache_cache_spec.rb +0 -35
  267. data/spec/extensions/static_cache_spec.rb +0 -471
  268. data/spec/extensions/string_agg_spec.rb +0 -90
  269. data/spec/extensions/string_date_time_spec.rb +0 -95
  270. data/spec/extensions/string_stripper_spec.rb +0 -68
  271. data/spec/extensions/subclasses_spec.rb +0 -79
  272. data/spec/extensions/subset_conditions_spec.rb +0 -38
  273. data/spec/extensions/symbol_aref_refinement_spec.rb +0 -28
  274. data/spec/extensions/symbol_as_refinement_spec.rb +0 -21
  275. data/spec/extensions/synchronize_sql_spec.rb +0 -124
  276. data/spec/extensions/table_select_spec.rb +0 -83
  277. data/spec/extensions/tactical_eager_loading_spec.rb +0 -402
  278. data/spec/extensions/thread_local_timezones_spec.rb +0 -67
  279. data/spec/extensions/throw_failures_spec.rb +0 -74
  280. data/spec/extensions/timestamps_spec.rb +0 -209
  281. data/spec/extensions/to_dot_spec.rb +0 -153
  282. data/spec/extensions/touch_spec.rb +0 -226
  283. data/spec/extensions/tree_spec.rb +0 -334
  284. data/spec/extensions/typecast_on_load_spec.rb +0 -86
  285. data/spec/extensions/unlimited_update_spec.rb +0 -21
  286. data/spec/extensions/update_or_create_spec.rb +0 -83
  287. data/spec/extensions/update_primary_key_spec.rb +0 -105
  288. data/spec/extensions/update_refresh_spec.rb +0 -59
  289. data/spec/extensions/uuid_spec.rb +0 -101
  290. data/spec/extensions/validate_associated_spec.rb +0 -52
  291. data/spec/extensions/validation_class_methods_spec.rb +0 -1040
  292. data/spec/extensions/validation_contexts_spec.rb +0 -31
  293. data/spec/extensions/validation_helpers_spec.rb +0 -525
  294. data/spec/extensions/whitelist_security_spec.rb +0 -157
  295. data/spec/extensions/xml_serializer_spec.rb +0 -213
  296. data/spec/files/bad_down_migration/001_create_alt_basic.rb +0 -4
  297. data/spec/files/bad_down_migration/002_create_alt_advanced.rb +0 -4
  298. data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  299. data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  300. data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +0 -3
  301. data/spec/files/bad_up_migration/001_create_alt_basic.rb +0 -4
  302. data/spec/files/bad_up_migration/002_create_alt_advanced.rb +0 -3
  303. data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +0 -9
  304. data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +0 -9
  305. data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +0 -4
  306. data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +0 -9
  307. data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +0 -9
  308. data/spec/files/double_migration/001_create_sessions.rb +0 -9
  309. data/spec/files/double_migration/002_create_nodes.rb +0 -19
  310. data/spec/files/double_migration/003_3_create_users.rb +0 -4
  311. data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +0 -4
  312. data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +0 -4
  313. data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  314. data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +0 -9
  315. data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +0 -4
  316. data/spec/files/empty_migration/001_create_sessions.rb +0 -9
  317. data/spec/files/empty_migration/002_create_nodes.rb +0 -0
  318. data/spec/files/empty_migration/003_3_create_users.rb +0 -4
  319. data/spec/files/integer_migrations/001_create_sessions.rb +0 -9
  320. data/spec/files/integer_migrations/002_create_nodes.rb +0 -9
  321. data/spec/files/integer_migrations/003_3_create_users.rb +0 -4
  322. data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  323. data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +0 -9
  324. data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  325. data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +0 -9
  326. data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  327. data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +0 -4
  328. data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +0 -4
  329. data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  330. data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  331. data/spec/files/reversible_migrations/001_reversible.rb +0 -5
  332. data/spec/files/reversible_migrations/002_reversible.rb +0 -5
  333. data/spec/files/reversible_migrations/003_reversible.rb +0 -5
  334. data/spec/files/reversible_migrations/004_reversible.rb +0 -5
  335. data/spec/files/reversible_migrations/005_reversible.rb +0 -10
  336. data/spec/files/reversible_migrations/006_reversible.rb +0 -10
  337. data/spec/files/reversible_migrations/007_reversible.rb +0 -10
  338. data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +0 -9
  339. data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +0 -9
  340. data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +0 -4
  341. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +0 -4
  342. data/spec/files/transaction_specified_migrations/002_create_basic.rb +0 -4
  343. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +0 -3
  344. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +0 -3
  345. data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +0 -9
  346. data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +0 -9
  347. data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +0 -4
  348. data/spec/guards_helper.rb +0 -59
  349. data/spec/integration/associations_test.rb +0 -2597
  350. data/spec/integration/database_test.rb +0 -113
  351. data/spec/integration/dataset_test.rb +0 -2037
  352. data/spec/integration/eager_loader_test.rb +0 -687
  353. data/spec/integration/migrator_test.rb +0 -262
  354. data/spec/integration/model_test.rb +0 -203
  355. data/spec/integration/plugin_test.rb +0 -2423
  356. data/spec/integration/prepared_statement_test.rb +0 -405
  357. data/spec/integration/schema_test.rb +0 -903
  358. data/spec/integration/spec_helper.rb +0 -71
  359. data/spec/integration/timezone_test.rb +0 -86
  360. data/spec/integration/transaction_test.rb +0 -603
  361. data/spec/integration/type_test.rb +0 -127
  362. data/spec/model/association_reflection_spec.rb +0 -803
  363. data/spec/model/associations_spec.rb +0 -4738
  364. data/spec/model/base_spec.rb +0 -875
  365. data/spec/model/class_dataset_methods_spec.rb +0 -146
  366. data/spec/model/dataset_methods_spec.rb +0 -198
  367. data/spec/model/eager_loading_spec.rb +0 -2377
  368. data/spec/model/hooks_spec.rb +0 -370
  369. data/spec/model/inflector_spec.rb +0 -26
  370. data/spec/model/model_spec.rb +0 -956
  371. data/spec/model/plugins_spec.rb +0 -429
  372. data/spec/model/record_spec.rb +0 -2118
  373. data/spec/model/spec_helper.rb +0 -46
  374. data/spec/model/validations_spec.rb +0 -220
  375. data/spec/model_no_assoc_spec.rb +0 -1
  376. data/spec/model_spec.rb +0 -1
  377. data/spec/plugin_spec.rb +0 -1
  378. data/spec/sequel_coverage.rb +0 -15
  379. data/spec/sequel_warning.rb +0 -4
  380. data/spec/spec_config.rb +0 -12
@@ -1,429 +0,0 @@
1
- require_relative "spec_helper"
2
-
3
- describe Sequel::Model, ".plugin" do
4
- before do
5
- module Sequel::Plugins
6
- module Timestamped
7
- module InstanceMethods
8
- def get_stamp(*args); @values[:stamp] end
9
- def abc; 123; end
10
- end
11
-
12
- module ClassMethods
13
- def def; 234; end
14
- end
15
-
16
- module DatasetMethods
17
- def ghi; 345; end
18
- end
19
- end
20
- end
21
- @c = Class.new(Sequel::Model(:items))
22
- @t = Sequel::Plugins::Timestamped
23
- end
24
- after do
25
- Sequel::Plugins.send(:remove_const, :Timestamped)
26
- end
27
-
28
- it "should raise LoadError if the plugin is not found" do
29
- proc{@c.plugin :something_or_other}.must_raise(LoadError)
30
- end
31
-
32
- it "should store the plugin in .plugins" do
33
- @c.plugins.wont_include(@t)
34
- @c.plugin @t
35
- @c.plugins.must_include(@t)
36
- end
37
-
38
- it "should be inherited in subclasses" do
39
- @c.plugins.wont_include(@t)
40
- c1 = Class.new(@c)
41
- @c.plugin @t
42
- c2 = Class.new(@c)
43
- @c.plugins.must_include(@t)
44
- c1.plugins.wont_include(@t)
45
- c2.plugins.must_include(@t)
46
- end
47
-
48
- it "should accept a symbol and load the module from the Sequel::Plugins namespace" do
49
- @c.plugin :timestamped
50
- @c.plugins.must_include(@t)
51
- end
52
-
53
- it "should accept a module" do
54
- m = Module.new
55
- @c.plugin m
56
- @c.plugins.must_include(m)
57
- end
58
-
59
- it "should not attempt to load a plugin twice" do
60
- @c.plugins.wont_include(@t)
61
- @c.plugin @t
62
- @c.plugins.reject{|m| m != @t}.length.must_equal 1
63
- @c.plugin @t
64
- @c.plugins.reject{|m| m != @t}.length.must_equal 1
65
- end
66
-
67
- it "should call apply and configure if the plugin responds to it, with the args and block used" do
68
- m = Module.new do
69
- def self.args; @args; end
70
- def self.block; @block; end
71
- def self.block_call; @block.call; end
72
- def self.args2; @args2; end
73
- def self.block2; @block2; end
74
- def self.block2_call; @block2.call; end
75
- def self.apply(model, *args, &block)
76
- @args = args
77
- @block = block
78
- model.send(:define_method, :blah){43}
79
- end
80
- def self.configure(model, *args, &block)
81
- @args2 = args
82
- @block2 = block
83
- model.send(:define_method, :blag){44}
84
- end
85
- end
86
- b = lambda{42}
87
- @c.plugin(m, 123, 1=>2, &b)
88
-
89
- m.args.must_equal [123, {1=>2}]
90
- m.block.must_equal b
91
- m.block_call.must_equal 42
92
- @c.new.blah.must_equal 43
93
-
94
- m.args2.must_equal [123, {1=>2}]
95
- m.block2.must_equal b
96
- m.block2_call.must_equal 42
97
- @c.new.blag.must_equal 44
98
- end
99
-
100
- it "should call configure even if the plugin has already been loaded" do
101
- m = Module.new do
102
- @args = []
103
- def self.args; @args; end
104
- def self.configure(model, *args, &block)
105
- @args << [block, *args]
106
- end
107
- end
108
-
109
- b = lambda{42}
110
- @c.plugin(m, 123, 1=>2, &b)
111
- m.args.must_equal [[b, 123, {1=>2}]]
112
-
113
- b2 = lambda{44}
114
- @c.plugin(m, 234, 2=>3, &b2)
115
- m.args.must_equal [[b, 123, {1=>2}], [b2, 234, {2=>3}]]
116
- end
117
-
118
- it "should call things in the following order: apply, ClassMethods, InstanceMethods, DatasetMethods, configure" do
119
- m = Module.new do
120
- @args = []
121
- def self.args; @args; end
122
- def self.apply(model, *args, &block)
123
- @args << :apply
124
- end
125
- def self.configure(model, *args, &block)
126
- @args << :configure
127
- end
128
- self::InstanceMethods = Module.new do
129
- def self.included(model)
130
- model.plugins.last.args << :im
131
- end
132
- end
133
- self::ClassMethods = Module.new do
134
- def self.extended(model)
135
- model.plugins.last.args << :cm
136
- end
137
- end
138
- self::DatasetMethods = Module.new do
139
- def self.extended(dataset)
140
- dataset.model.plugins.last.args << :dm
141
- end
142
- end
143
- end
144
-
145
- b = lambda{44}
146
- @c.plugin(m, 123, 1=>2, &b)
147
- m.args.must_equal [:apply, :cm, :im, :dm, :configure]
148
- @c.plugin(m, 234, 2=>3, &b)
149
- m.args.must_equal [:apply, :cm, :im, :dm, :configure, :configure]
150
- end
151
-
152
- it "should include an InstanceMethods module in the class if the plugin includes it" do
153
- @c.plugin @t
154
- m = @c.new
155
- m.must_respond_to(:get_stamp)
156
- m.must_respond_to(:abc)
157
- m.abc.must_equal 123
158
- t = Time.now
159
- m[:stamp] = t
160
- m.get_stamp.must_equal t
161
- end
162
-
163
- it "should extend the class with a ClassMethods module if the plugin includes it" do
164
- @c.plugin @t
165
- @c.def.must_equal 234
166
- end
167
-
168
- it "should extend the class's dataset with a DatasetMethods module if the plugin includes it" do
169
- @c.plugin @t
170
- @c.dataset.ghi.must_equal 345
171
- end
172
-
173
- it "should save the DatasetMethods module and apply it later if the class doesn't have a dataset" do
174
- c = Class.new(Sequel::Model)
175
- c.plugin @t
176
- c.dataset = DB[:i]
177
- c.dataset.ghi.must_equal 345
178
- end
179
-
180
- it "should save the DatasetMethods module and apply it later if the class has a dataset" do
181
- @c.plugin @t
182
- @c.dataset = DB[:i]
183
- @c.dataset.ghi.must_equal 345
184
- end
185
-
186
- it "should not define class methods for private instance methods in DatasetMethod" do
187
- m = Module.new do
188
- self::DatasetMethods = Module.new do
189
- def b; 2; end
190
- private
191
- def a; 1; end
192
- end
193
- end
194
- @c.plugin m
195
- @c.dataset.b.must_equal 2
196
- lambda{@c.dataset.a}.must_raise(NoMethodError)
197
- @c.dataset.send(:a).must_equal 1
198
- lambda{@c.a}.must_raise(NoMethodError)
199
- lambda{@c.send(:a)}.must_raise(NoMethodError)
200
- end
201
-
202
- it "should not raise an error if the DatasetMethod module has no public instance methods" do
203
- m = Module.new do
204
- self::DatasetMethods = Module.new do
205
- private
206
- def a; 1; end
207
- end
208
- end
209
- @c.plugin m
210
- end
211
-
212
- it "should not raise an error if plugin submodule names exist higher up in the namespace hierarchy" do
213
- class ::ClassMethods; end
214
- @c.plugin(m = Module.new)
215
- Object.send(:remove_const, :ClassMethods)
216
- @c.plugins.must_include(m)
217
-
218
- class ::InstanceMethods; end
219
- @c.plugin(m = Module.new)
220
- Object.send(:remove_const, :InstanceMethods)
221
- @c.plugins.must_include(m)
222
-
223
- class ::DatasetMethods; end
224
- @c.plugin(m = Module.new)
225
- Object.send(:remove_const, :DatasetMethods)
226
- @c.plugins.must_include(m)
227
- end
228
- end
229
-
230
- describe Sequel::Plugins do
231
- before do
232
- @c = Class.new(Sequel::Model(:items))
233
- end
234
-
235
- it "should have def_dataset_methods define methods that call methods on the dataset" do
236
- m = Module.new do
237
- module self::ClassMethods
238
- Sequel::Plugins.def_dataset_methods(self, :one)
239
- end
240
- module self::DatasetMethods
241
- def one
242
- 1
243
- end
244
- end
245
- end
246
- @c.plugin m
247
- @c.one.must_equal 1
248
- end
249
-
250
- it "should have def_dataset_methods accept an array with multiple methods" do
251
- m = Module.new do
252
- module self::ClassMethods
253
- Sequel::Plugins.def_dataset_methods(self, [:one, :two])
254
- end
255
- module self::DatasetMethods
256
- def one
257
- 1
258
- end
259
- def two
260
- 2
261
- end
262
- end
263
- end
264
- @c.plugin m
265
- @c.one.must_equal 1
266
- @c.two.must_equal 2
267
- end
268
-
269
- it "should have inherited_instance_variables add instance variables to copy into the subclass" do
270
- m = Module.new do
271
- def self.apply(model)
272
- model.instance_variable_set(:@one, 1)
273
- end
274
- module self::ClassMethods
275
- attr_reader :one
276
- Sequel::Plugins.inherited_instance_variables(self, :@one=>nil)
277
- end
278
- end
279
- @c.plugin m
280
- Class.new(@c).one.must_equal 1
281
- end
282
-
283
- it "should have after_set_dataset add a method to call after set_dataset" do
284
- m = Module.new do
285
- module self::ClassMethods
286
- Sequel::Plugins.after_set_dataset(self, :one)
287
- def foo; dataset.send(:cache_get, :foo) end
288
- private
289
- def one; dataset.send(:cache_set, :foo, 1) end
290
- end
291
- end
292
- @c.plugin m
293
- @c.foo.must_be_nil
294
- @c.set_dataset :blah
295
- @c.foo.must_equal 1
296
- end
297
- end
298
-
299
- describe "Sequel::Model.plugin" do
300
- before do
301
- @c = Class.new(Sequel::Model)
302
- end
303
- after do
304
- Sequel::Plugins.send(:remove_const, :SomethingOrOther)
305
- end
306
-
307
- it "should try loading plugins from sequel/plugins/:plugin" do
308
- a = []
309
- m = Module.new
310
- @c.define_singleton_method(:require) do |b|
311
- a << b
312
- Sequel::Plugins.const_set(:SomethingOrOther, m)
313
- end
314
- @c.plugin :something_or_other
315
- @c.plugins.must_include m
316
- a.must_equal ['sequel/plugins/something_or_other']
317
- end
318
- end
319
-
320
- describe "Sequel::Plugins.def_sequel_method" do
321
- before do
322
- @m = Class.new
323
- @scope = @m.new
324
- end
325
-
326
- it "should define methods using block" do
327
- m0 = Sequel::Plugins.def_sequel_method(@m, "x", 0){1}
328
- m0.must_be_kind_of Symbol
329
- m0.must_match /\A_sequel_x_\d+\z/
330
- @scope.send(m0).must_equal 1
331
-
332
- m1 = Sequel::Plugins.def_sequel_method(@m, "x", 1){|x| [x, 2]}
333
- m1.must_be_kind_of Symbol
334
- m1.must_match /\A_sequel_x_\d+\z/
335
- @scope.send(m1, 3).must_equal [3, 2]
336
- end
337
-
338
- it "should define public methods" do
339
- proc{@scope.public_send(Sequel::Plugins.def_sequel_method(@m, "x", 0){1})}.must_raise NoMethodError
340
- end
341
-
342
- it "should accept symbols as method name and return the same symbol" do
343
- m0 = Sequel::Plugins.def_sequel_method(@m, :_roda_foo, 0){1}
344
- m0.must_equal :_roda_foo
345
- @scope.send(m0).must_equal 1
346
- end
347
-
348
- it "should handle optional arguments and splats for expected_arity 0" do
349
- m2 = Sequel::Plugins.def_sequel_method(@m, "x", 0){|*x| [x, 3]}
350
- @scope.send(m2).must_equal [[], 3]
351
-
352
- m3 = Sequel::Plugins.def_sequel_method(@m, "x", 0){|x=5| [x, 4]}
353
- @scope.send(m3).must_equal [5, 4]
354
-
355
- m4 = Sequel::Plugins.def_sequel_method(@m, "x", 0){|x=6, *y| [x, y, 5]}
356
- @scope.send(m4).must_equal [6, [], 5]
357
- end
358
-
359
- it "should should optional arguments and splats for expected_arity 1" do
360
- m2 = Sequel::Plugins.def_sequel_method(@m, "x", 1){|y, *x| [y, x, 3]}
361
- @scope.send(m2, :a).must_equal [:a, [], 3]
362
-
363
- m3 = Sequel::Plugins.def_sequel_method(@m, "x", 1){|y, x=5| [y, x, 4]}
364
- @scope.send(m3, :b).must_equal [:b, 5, 4]
365
-
366
- m4 = Sequel::Plugins.def_sequel_method(@m, "x", 1){|y, x=6, *z| [y, x, z, 5]}
367
- @scope.send(m4, :c).must_equal [:c, 6, [], 5]
368
- end
369
-
370
- deprecated "should handle differences in arity" do
371
- m0 = Sequel::Plugins.def_sequel_method(@m, "x", 0){|x| [x, 1]}
372
- @scope.send(m0).must_equal [nil, 1]
373
-
374
- m1 = Sequel::Plugins.def_sequel_method(@m, "x", 1){2}
375
- @scope.send(m1, 3).must_equal 2
376
-
377
- m1 = Sequel::Plugins.def_sequel_method(@m, "x", 1){|x, y| [x, y]}
378
- @scope.send(m1, 4).must_equal [4, nil]
379
- end
380
-
381
- it "should raise for unexpected expected_arity" do
382
- proc{Sequel::Plugins.def_sequel_method(@m, "x", 2){|x|}}.must_raise Sequel::Error
383
- end
384
-
385
- it "should fail if a lambda with invalid arity is passed" do
386
- m0 = Sequel::Plugins.def_sequel_method(@m, "x", 0, &lambda{|x| [x, 1]})
387
- proc{@scope.send(m0)}.must_raise ArgumentError
388
-
389
- m1 = Sequel::Plugins.def_sequel_method(@m, "x", 1, &lambda{2})
390
- proc{@scope.send(m1, 1)}.must_raise ArgumentError
391
- end
392
-
393
- if RUBY_VERSION > '2.1'
394
- it "should raise for required keyword arguments for expected_arity 0 or 1" do
395
- proc{eval("Sequel::Plugins.def_sequel_method(@m, 'x', 0){|b:| [b, 1]}", binding)}.must_raise Sequel::Error
396
- proc{eval("Sequel::Plugins.def_sequel_method(@m, 'x', 0){|c=1, b:| [c, b, 1]}", binding)}.must_raise Sequel::Error
397
- proc{eval("Sequel::Plugins.def_sequel_method(@m, 'x', 1){|x, b:| [b, 1]}", binding)}.must_raise Sequel::Error
398
- proc{eval("Sequel::Plugins.def_sequel_method(@m, 'x', 1){|x, c=1, b:| [c, b, 1]}", binding)}.must_raise Sequel::Error
399
- end
400
-
401
- it "should ignore keyword arguments for expected_arity 0" do
402
- @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 0){|b:2| [b, 1]}", binding)).must_equal [2, 1]
403
- @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 0){|**b| [b, 1]}", binding)).must_equal [{}, 1]
404
- @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 0){|c=1, b:2| [c, b, 1]}", binding)).must_equal [1, 2, 1]
405
- @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 0){|c=1, **b| [c, b, 1]}", binding)).must_equal [1, {}, 1]
406
- end
407
-
408
- deprecated "should ignore keyword arguments for expected_arity 0 with invalid arity" do
409
- @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 0){|x, b:2| [x, b, 1]}", binding)).must_equal [nil, 2, 1]
410
- @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 0){|x, **b| [x, b, 1]}", binding)).must_equal [nil, {}, 1]
411
- @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 0){|x, c=1, b:2| [x, c, b, 1]}", binding)).must_equal [nil, 1, 2, 1]
412
- @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 0){|x, c=1, **b| [x, c, b, 1]}", binding)).must_equal [nil, 1, {}, 1]
413
- end
414
-
415
- deprecated "should ignore keyword arguments for expected_arity 1 with invalid arity" do
416
- @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 1){|b:2| [b, 1]}", binding), 3).must_equal [2, 1]
417
- @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 1){|**b| [b, 1]}", binding), 3).must_equal [{}, 1]
418
- end
419
-
420
- it "should ignore keyword arguments for expected_arity 1" do
421
- @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 1){|c=1, b:2| [c, b, 1]}", binding), 3).must_equal [3, 2, 1]
422
- @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 1){|c=1, **b| [c, b, 1]}", binding), 3).must_equal [3, {}, 1]
423
- @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 1){|x, b:2| [x, b, 1]}", binding), 3).must_equal [3, 2, 1]
424
- @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 1){|x, **b| [x, b, 1]}", binding), 3).must_equal [3, {}, 1]
425
- @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 1){|x, c=1, b:2| [x, c, b, 1]}", binding), 3).must_equal [3, 1, 2, 1]
426
- @scope.send(eval("Sequel::Plugins.def_sequel_method(@m, 'x', 1){|x, c=1, **b| [x, c, b, 1]}", binding), 3).must_equal [3, 1, {}, 1]
427
- end
428
- end
429
- end
@@ -1,2118 +0,0 @@
1
- require_relative "spec_helper"
2
-
3
- describe "Model#values" do
4
- before do
5
- @c = Class.new(Sequel::Model(:items))
6
- end
7
-
8
- it "should return the hash of model values" do
9
- hash = {:x=>1}
10
- @c.load(hash).values.must_be_same_as(hash)
11
- end
12
-
13
- it "should be aliased as to_hash" do
14
- hash = {:x=>1}
15
- @c.load(hash).to_hash.must_be_same_as(hash)
16
- end
17
- end
18
-
19
- describe "Model#get_column_value and set_column_value" do
20
- before do
21
- @c = Class.new(Sequel::Model(:items))
22
- @c.columns :x
23
- @o = @c.load(:x=>1)
24
- end
25
-
26
- it "should get and set column values" do
27
- @o.get_column_value(:x).must_equal 1
28
- @o.set_column_value(:x=, 2)
29
- @o.get_column_value(:x).must_equal 2
30
- @o.x.must_equal 2
31
- end
32
- end
33
-
34
- describe "Model#save server use" do
35
- before do
36
- @db = Sequel.mock(:autoid=>proc{|sql| 10}, :fetch=>{:x=>1, :id=>10}, :numrows=>1, :servers=>{:blah=>{}, :read_only=>{}})
37
- @c = Class.new(Sequel::Model(@db[:items]))
38
- @c.columns :id, :x, :y
39
- @c.dataset.columns(:id, :x, :y)
40
- @db.sqls
41
- end
42
-
43
- it "should use the :default server if the model doesn't have one already specified" do
44
- @c.new(:x=>1).save.must_equal @c.load(:x=>1, :id=>10)
45
- @db.sqls.must_equal ["INSERT INTO items (x) VALUES (1)", 'SELECT * FROM items WHERE (id = 10) LIMIT 1']
46
- end
47
-
48
- it "should use the model's server if the model has one already specified" do
49
- @c.dataset = @c.dataset.server(:blah)
50
- @c.new(:x=>1).save.must_equal @c.load(:x=>1, :id=>10)
51
- @db.sqls.must_equal ["INSERT INTO items (x) VALUES (1) -- blah", 'SELECT * FROM items WHERE (id = 10) LIMIT 1 -- blah']
52
- end
53
-
54
- it "should use transactions on the correct server" do
55
- @c.use_transactions = true
56
- @c.dataset = @c.dataset.server(:blah)
57
- @c.new(:x=>1).save.must_equal @c.load(:x=>1, :id=>10)
58
- @db.sqls.must_equal ["BEGIN -- blah", "INSERT INTO items (x) VALUES (1) -- blah", 'SELECT * FROM items WHERE (id = 10) LIMIT 1 -- blah', 'COMMIT -- blah']
59
-
60
- o = @c.load(:id=>1)
61
- o.x = 2
62
- o.this
63
- o.save
64
- @db.sqls.must_equal ["BEGIN -- blah", "UPDATE items SET x = 2 WHERE (id = 1) -- blah", 'COMMIT -- blah']
65
- end
66
- end
67
-
68
- describe "Model#save" do
69
- before do
70
- @c = Class.new(Sequel::Model(:items)) do
71
- columns :id, :x, :y
72
- end
73
- @c.dataset = @c.dataset.with_autoid(13)
74
- DB.reset
75
- end
76
-
77
- it "should insert a record for a new model instance" do
78
- o = @c.new(:x => 1)
79
- o.save
80
- DB.sqls.must_equal ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE id = 13"]
81
- end
82
-
83
- it "should raise if the object can't be refreshed after save" do
84
- o = @c.new(:x => 1)
85
- @c.dataset = @c.dataset.with_fetch([])
86
- proc{o.save}.must_raise(Sequel::NoExistingObject)
87
- end
88
-
89
- it "should use dataset's insert_select method if present" do
90
- @c.dataset = @c.dataset.with_fetch(:y=>2).with_extend do
91
- def supports_insert_select?; true end
92
- def insert_select(hash)
93
- with_sql_first("INSERT INTO items (y) VALUES (2) RETURNING *")
94
- end
95
- end
96
- o = @c.new(:x => 1)
97
- o.save
98
-
99
- o.values.must_equal(:y=>2)
100
- DB.sqls.must_equal ["INSERT INTO items (y) VALUES (2) RETURNING *"]
101
- end
102
-
103
- it "should issue regular insert query if insert_select returns nil" do
104
- @c.dataset = @c.dataset.with_fetch(:id=>4, :x=>2).with_autoid(4).with_extend do
105
- def supports_insert_select?; true end
106
- def insert_select(hash)
107
- end
108
- end
109
- o = @c.new(:x => 1)
110
- o.save
111
-
112
- DB.sqls.must_equal ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE id = 4"]
113
- o.values.must_equal(:id=>4, :x=>2)
114
- end
115
-
116
- it "should assume insert statement already ran if insert_select returns false" do
117
- @c.dataset = @c.dataset.with_fetch(:y=>2).with_extend do
118
- def supports_insert_select?; true end
119
- def insert_select(hash)
120
- with_sql_first("INSERT INTO items (y) VALUES (2) RETURNING *")
121
- false
122
- end
123
- end
124
- o = @c.new(:x => 1)
125
- o.save
126
-
127
- o.values.must_equal(:x=>1)
128
- DB.sqls.must_equal ["INSERT INTO items (y) VALUES (2) RETURNING *"]
129
- end
130
-
131
- it "should not use dataset's insert_select method if specific columns are selected" do
132
- @c.dataset = @c.dataset.select(:y).with_extend{def insert_select(*) raise; end}
133
- @c.new(:x => 1).save
134
- end
135
-
136
- it "should use dataset's insert_select method if the dataset uses returning, even if specific columns are selected" do
137
- @c.dataset = @c.dataset.select(:y).with_fetch(:y=>2).with_extend do
138
- def supports_returning?(_) true end
139
- def supports_insert_select?; true end
140
- def insert_select(hash)
141
- with_sql_first("INSERT INTO items (y) VALUES (2) RETURNING y")
142
- end
143
- end.returning(:y)
144
- DB.reset
145
- o = @c.new(:x => 1)
146
- o.save
147
-
148
- o.values.must_equal(:y=>2)
149
- DB.sqls.must_equal ["INSERT INTO items (y) VALUES (2) RETURNING y"]
150
- end
151
-
152
- it "should use value returned by insert as the primary key and refresh the object" do
153
- o = @c.new(:x => 11)
154
- o.save
155
- DB.sqls.must_equal ["INSERT INTO items (x) VALUES (11)", "SELECT * FROM items WHERE id = 13"]
156
- end
157
-
158
- it "should allow you to skip refreshing by overridding _save_refresh" do
159
- @c.send(:define_method, :_save_refresh){}
160
- @c.create(:x => 11)
161
- DB.sqls.must_equal ["INSERT INTO items (x) VALUES (11)"]
162
- end
163
-
164
- it "should work correctly for inserting a record without a primary key" do
165
- @c.no_primary_key
166
- o = @c.new(:x => 11)
167
- o.save
168
- DB.sqls.must_equal ["INSERT INTO items (x) VALUES (11)"]
169
- end
170
-
171
- it "should set the autoincrementing_primary_key value to the value returned by insert" do
172
- @c.unrestrict_primary_key
173
- @c.set_primary_key [:x, :y]
174
- o = @c.new(:x => 11)
175
- def o.autoincrementing_primary_key() :y end
176
- o.save
177
- DB.sqls.must_equal ["INSERT INTO items (x) VALUES (11)",
178
- 'SELECT * FROM items WHERE ((x = 11) AND (y = 13)) LIMIT 1']
179
- end
180
-
181
- it "should update a record for an existing model instance" do
182
- o = @c.load(:id => 3, :x => 1)
183
- o.save
184
- DB.sqls.must_equal ["UPDATE items SET x = 1 WHERE (id = 3)"]
185
- end
186
-
187
- it "should raise a NoExistingObject exception if the dataset update call doesn't return 1, unless require_modification is false" do
188
- i = 0
189
- @c.dataset = @c.dataset.with_extend{define_method(:numrows){i}}
190
- o = @c.load(:id => 3, :x => 1)
191
- proc{o.save}.must_raise(Sequel::NoExistingObject)
192
- i = 2
193
- proc{o.save}.must_raise(Sequel::NoExistingObject)
194
- i = 1
195
- o.save
196
-
197
- o.require_modification = false
198
- i = 0
199
- o.save
200
- i = 2
201
- o.save
202
- end
203
-
204
- it "should respect the :columns option to specify the columns to save" do
205
- o = @c.load(:id => 3, :x => 1, :y => nil)
206
- o.save(:columns=>:y)
207
- DB.sqls.first.must_equal "UPDATE items SET y = NULL WHERE (id = 3)"
208
- end
209
-
210
- it "should mark saved columns as not changed" do
211
- o = @c.load(:id => 3, :x => 1, :y => nil)
212
- o[:y] = 4
213
- o.changed_columns.must_equal [:y]
214
- o.save(:columns=>:x)
215
- o.changed_columns.must_equal [:y]
216
- o.save(:columns=>:y)
217
- o.changed_columns.must_equal []
218
- end
219
-
220
- it "should mark all columns as not changed if this is a new record" do
221
- o = @c.new(:x => 1, :y => nil)
222
- o.x = 4
223
- o.changed_columns.must_equal [:x]
224
- o.save
225
- o.changed_columns.must_equal []
226
- end
227
-
228
- it "should mark all columns as not changed if this is a new record and insert_select was used" do
229
- @c.dataset = @c.dataset.with_extend{def insert_select(h) h.merge(:id=>1) end}
230
- o = @c.new(:x => 1, :y => nil)
231
- o.x = 4
232
- o.changed_columns.must_equal [:x]
233
- o.save
234
- o.changed_columns.must_equal []
235
- end
236
-
237
- it "should use Model's use_transactions setting by default" do
238
- @c.use_transactions = true
239
- @c.load(:id => 3, :x => 1, :y => nil).save(:columns=>:y)
240
- DB.sqls.must_equal ["BEGIN", "UPDATE items SET y = NULL WHERE (id = 3)", "COMMIT"]
241
- @c.use_transactions = false
242
- @c.load(:id => 3, :x => 1, :y => nil).save(:columns=>:y)
243
- DB.sqls.must_equal ["UPDATE items SET y = NULL WHERE (id = 3)"]
244
- end
245
-
246
- it "should inherit Model's use_transactions setting" do
247
- @c.use_transactions = true
248
- Class.new(@c).load(:id => 3, :x => 1, :y => nil).save(:columns=>:y)
249
- DB.sqls.must_equal ["BEGIN", "UPDATE items SET y = NULL WHERE (id = 3)", "COMMIT"]
250
- @c.use_transactions = false
251
- Class.new(@c).load(:id => 3, :x => 1, :y => nil).save(:columns=>:y)
252
- DB.sqls.must_equal ["UPDATE items SET y = NULL WHERE (id = 3)"]
253
- end
254
-
255
- it "should use object's use_transactions setting" do
256
- o = @c.load(:id => 3, :x => 1, :y => nil)
257
- o.use_transactions = false
258
- @c.use_transactions = true
259
- o.save(:columns=>:y)
260
- DB.sqls.must_equal ["UPDATE items SET y = NULL WHERE (id = 3)"]
261
- o = @c.load(:id => 3, :x => 1, :y => nil)
262
- o.use_transactions = true
263
- @c.use_transactions = false
264
- o.save(:columns=>:y)
265
- DB.sqls.must_equal ["BEGIN", "UPDATE items SET y = NULL WHERE (id = 3)", "COMMIT"]
266
- end
267
-
268
- it "should use :transaction option if given" do
269
- o = @c.load(:id => 3, :x => 1, :y => nil)
270
- o.use_transactions = true
271
- o.save(:columns=>:y, :transaction=>false)
272
- DB.sqls.must_equal ["UPDATE items SET y = NULL WHERE (id = 3)"]
273
- o = @c.load(:id => 3, :x => 1, :y => nil)
274
- o.use_transactions = false
275
- o.save(:columns=>:y, :transaction=>true)
276
- DB.sqls.must_equal ["BEGIN", "UPDATE items SET y = NULL WHERE (id = 3)", "COMMIT"]
277
- end
278
-
279
- it "should rollback if before_save calls cancel_action and raise_on_save_failure = true" do
280
- o = @c.load(:id => 3, :x => 1, :y => nil)
281
- o.use_transactions = true
282
- o.raise_on_save_failure = true
283
- def o.before_save
284
- cancel_action
285
- end
286
- proc { o.save(:columns=>:y) }.must_raise(Sequel::HookFailed)
287
- DB.sqls.must_equal ["BEGIN", "ROLLBACK"]
288
- end
289
-
290
- it "should rollback if before_save calls cancel_action and :raise_on_failure option is true" do
291
- o = @c.load(:id => 3, :x => 1, :y => nil)
292
- o.use_transactions = true
293
- o.raise_on_save_failure = false
294
- def o.before_save
295
- cancel_action
296
- end
297
- proc { o.save(:columns=>:y, :raise_on_failure => true) }.must_raise(Sequel::HookFailed)
298
- DB.sqls.must_equal ["BEGIN", "ROLLBACK"]
299
- end
300
-
301
- it "should not rollback outer transactions if before_save calls cancel_action and raise_on_save_failure = false" do
302
- o = @c.load(:id => 3, :x => 1, :y => nil)
303
- o.use_transactions = true
304
- o.raise_on_save_failure = false
305
- def o.before_save
306
- cancel_action
307
- end
308
- DB.transaction do
309
- o.save(:columns=>:y).must_be_nil
310
- DB.run "BLAH"
311
- end
312
- DB.sqls.must_equal ["BEGIN", "BLAH", "COMMIT"]
313
- end
314
-
315
- it "should rollback if before_save calls cancel_action and raise_on_save_failure = false" do
316
- o = @c.load(:id => 3, :x => 1, :y => nil)
317
- o.use_transactions = true
318
- o.raise_on_save_failure = false
319
- def o.before_save
320
- cancel_action
321
- end
322
- o.save(:columns=>:y).must_be_nil
323
- DB.sqls.must_equal ["BEGIN", "ROLLBACK"]
324
- end
325
-
326
- it "should not rollback if before_save throws Rollback and use_transactions = false" do
327
- o = @c.load(:id => 3, :x => 1, :y => nil)
328
- o.use_transactions = false
329
- def o.before_save
330
- raise Sequel::Rollback
331
- end
332
- proc { o.save(:columns=>:y) }.must_raise(Sequel::Rollback)
333
- DB.sqls.must_equal []
334
- end
335
-
336
- it "should support a :server option to set the server/shard to use" do
337
- db = Sequel.mock(:fetch=>{:id=>13, :x=>1}, :autoid=>proc{13}, :numrows=>1, :servers=>{:s1=>{}})
338
- c = Class.new(Sequel::Model(db[:items]))
339
- c.columns :id, :x
340
- db.sqls
341
- o = c.new(:x => 1)
342
- o.save(:server=>:s1)
343
- db.sqls.must_equal ["INSERT INTO items (x) VALUES (1) -- s1", "SELECT * FROM items WHERE (id = 13) LIMIT 1 -- s1"]
344
- o.save(:server=>:s1, :transaction=>true)
345
- db.sqls.must_equal ["BEGIN -- s1", "UPDATE items SET x = 1 WHERE (id = 13) -- s1", 'COMMIT -- s1']
346
- end
347
- end
348
-
349
- describe "Model#set_server" do
350
- before do
351
- @db = Sequel.mock(:fetch=>{:id=>13, :x=>1}, :autoid=>proc{13}, :numrows=>1, :servers=>{:s1=>{}})
352
- @c = Class.new(Sequel::Model(@db[:items])) do
353
- columns :id, :x
354
- end
355
- @db.sqls
356
- end
357
-
358
- it "should set the server to use when inserting" do
359
- @c.new(:x => 1).set_server(:s1).save
360
- @db.sqls.must_equal ["INSERT INTO items (x) VALUES (1) -- s1", "SELECT * FROM items WHERE (id = 13) LIMIT 1 -- s1"]
361
- end
362
-
363
- it "should set the server to use when updating" do
364
- @c.load(:id=>13, :x => 1).set_server(:s1).save
365
- @db.sqls.must_equal ["UPDATE items SET x = 1 WHERE (id = 13) -- s1"]
366
- end
367
-
368
- it "should set the server to use for transactions when saving" do
369
- @c.load(:id=>13, :x => 1).set_server(:s1).save(:transaction=>true)
370
- @db.sqls.must_equal ["BEGIN -- s1", "UPDATE items SET x = 1 WHERE (id = 13) -- s1", 'COMMIT -- s1']
371
- end
372
-
373
- it "should set the server to use when deleting" do
374
- @c.load(:id=>13).set_server(:s1).delete
375
- @db.sqls.must_equal ["DELETE FROM items WHERE (id = 13) -- s1"]
376
- end
377
-
378
- it "should set the server to use when deleting when using optimized delete" do
379
- @c.set_primary_key :id
380
- @c.load(:id=>13).set_server(:s1).delete
381
- @db.sqls.must_equal ["DELETE FROM items WHERE id = 13 -- s1"]
382
- end
383
-
384
- it "should set the server to use for transactions when destroying" do
385
- o = @c.load(:id=>13).set_server(:s1)
386
- o.use_transactions = true
387
- o.destroy
388
- @db.sqls.must_equal ["BEGIN -- s1", "DELETE FROM items WHERE (id = 13) -- s1", 'COMMIT -- s1']
389
- end
390
-
391
- it "should set the server on this if this is already loaded" do
392
- o = @c.load(:id=>13, :x => 1)
393
- o.this
394
- o.set_server(:s1)
395
- o.this.opts[:server].must_equal :s1
396
- end
397
-
398
- it "should set the server on this if this is not already loaded" do
399
- @c.load(:id=>13, :x => 1).set_server(:s1).this.opts[:server].must_equal :s1
400
- end
401
- end
402
-
403
- describe "Model#freeze" do
404
- before do
405
- class ::Album < Sequel::Model
406
- columns :id
407
- class B < Sequel::Model
408
- columns :id, :album_id
409
- end
410
- end
411
- @o = Album.load(:id=>1).freeze
412
- DB.sqls
413
- end
414
- after do
415
- Object.send(:remove_const, :Album)
416
- end
417
-
418
- it "should freeze the object" do
419
- @o.frozen?.must_equal true
420
- end
421
-
422
- it "should freeze the object if the model doesn't have a primary key" do
423
- Album.no_primary_key
424
- @o = Album.load(:id=>1).freeze
425
- @o.frozen?.must_equal true
426
- end
427
-
428
- it "should freeze the object's values, associations, changed_columns, errors, and this" do
429
- @o.values.frozen?.must_equal true
430
- @o.changed_columns.frozen?.must_equal true
431
- @o.errors.frozen?.must_equal true
432
- @o.this.frozen?.must_equal true
433
- end
434
-
435
- it "should still have working class attr overriddable methods" do
436
- [:typecast_empty_string_to_nil, :typecast_on_assignment, :strict_param_setting, :raise_on_save_failure, :raise_on_typecast_failure, :require_modification, :use_transactions].each{|m| @o.send(m) == Album.send(m)}
437
- end
438
-
439
- it "should have working new? method" do
440
- @o.new?.must_equal false
441
- Album.new.freeze.new?.must_equal true
442
- end
443
-
444
- it "should have working valid? method" do
445
- @o.valid?.must_equal true
446
- o = Album.new
447
- def o.validate() errors.add(:foo, '') end
448
- o.freeze
449
- o.valid?.must_equal false
450
- end
451
-
452
- it "should not call validate if errors is already frozen" do
453
- @o.valid?.must_equal true
454
- o = Album.new
455
- o.errors.freeze
456
- def o.validate() errors.add(:foo, '') end
457
- o.freeze
458
- o.valid?.must_equal true
459
- end
460
-
461
- it "should raise an Error if trying to save/destroy/delete/refresh" do
462
- proc{@o.save}.must_raise(Sequel::Error)
463
- proc{@o.destroy}.must_raise(Sequel::Error)
464
- proc{@o.delete}.must_raise(Sequel::Error)
465
- proc{@o.refresh}.must_raise(Sequel::Error)
466
- @o.db.sqls.must_equal []
467
- end
468
- end
469
-
470
- describe "Model#dup" do
471
- before do
472
- @Album = Class.new(Sequel::Model(:albums))
473
- @o = @Album.load(:id=>1)
474
- DB.sqls
475
- end
476
-
477
- it "should be equal to existing object" do
478
- @o.dup.must_equal @o
479
- @o.dup.values.must_equal @o.values
480
- @o.dup.changed_columns.must_equal @o.changed_columns
481
- @o.dup.errors.must_equal @o.errors
482
- @o.dup.this.must_equal @o.this
483
- end
484
-
485
- it "should not use identical structures" do
486
- @o.dup.wont_be_same_as(@o)
487
- @o.dup.values.wont_be_same_as(@o.values)
488
- @o.dup.changed_columns.wont_be_same_as(@o.changed_columns)
489
- @o.dup.errors.wont_be_same_as(@o.errors)
490
- @o.dup.this.wont_be_same_as(@o.this)
491
- end
492
-
493
- it "should keep new status" do
494
- @o.dup.new?.must_equal false
495
- @Album.new.dup.new?.must_equal true
496
- end
497
-
498
- it "should not copy frozen status" do
499
- this_frozen = @o.this.frozen?
500
- d = @o.freeze.dup
501
- d.wont_be :frozen?
502
- d.values.wont_be :frozen?
503
- d.changed_columns.wont_be :frozen?
504
- d.errors.wont_be :frozen?
505
- d.this.frozen?.must_equal this_frozen
506
- end
507
- end
508
-
509
- describe "Model#clone" do
510
- before do
511
- @Album = Class.new(Sequel::Model(:albums))
512
- @o = @Album.load(:id=>1)
513
- DB.sqls
514
- end
515
-
516
- it "should be equal to existing object" do
517
- @o.clone.must_equal @o
518
- @o.clone.values.must_equal @o.values
519
- @o.clone.changed_columns.must_equal @o.changed_columns
520
- @o.clone.errors.must_equal @o.errors
521
- @o.clone.this.must_equal @o.this
522
- end
523
-
524
- it "should not use identical structures" do
525
- @o.clone.wont_be_same_as(@o)
526
- @o.clone.values.wont_be_same_as(@o.values)
527
- @o.clone.changed_columns.wont_be_same_as(@o.changed_columns)
528
- @o.clone.errors.wont_be_same_as(@o.errors)
529
- @o.clone.this.wont_be_same_as(@o.this)
530
- end
531
-
532
- it "should keep new status" do
533
- @o.clone.new?.must_equal false
534
- @Album.new.clone.new?.must_equal true
535
- end
536
-
537
- it "should copy frozen status" do
538
- @o.freeze.clone.must_be :frozen?
539
- @o.freeze.clone.values.must_be :frozen?
540
- @o.freeze.clone.changed_columns.must_be :frozen?
541
- @o.freeze.clone.errors.must_be :frozen?
542
- @o.freeze.clone.this.must_be :frozen?
543
- end
544
- end
545
-
546
- describe "Model#marshallable" do
547
- before do
548
- class ::Album < Sequel::Model
549
- columns :id, :x
550
- end
551
- end
552
- after do
553
- Object.send(:remove_const, :Album)
554
- end
555
-
556
- it "should make an object marshallable" do
557
- i = Album.new(:x=>2)
558
- s = nil
559
- i2 = nil
560
- i.marshallable!
561
- s = Marshal.dump(i)
562
- i2 = Marshal.load(s)
563
- i2.must_equal i
564
-
565
- i.save
566
- i.marshallable!
567
- s = Marshal.dump(i)
568
- i2 = Marshal.load(s)
569
- i2.must_equal i
570
-
571
- i.save
572
- i.marshallable!
573
- s = Marshal.dump(i)
574
- i2 = Marshal.load(s)
575
- i2.must_equal i
576
- end
577
- end
578
-
579
- describe "Model#modified?" do
580
- before do
581
- @c = Class.new(Sequel::Model(:items))
582
- @c.class_eval do
583
- columns :id, :x
584
- @db_schema = {:x => {:type => :integer}}
585
- end
586
- DB.reset
587
- end
588
-
589
- it "should be true if the object is new" do
590
- @c.new.modified?.must_equal true
591
- end
592
-
593
- it "should be false if the object has not been modified" do
594
- @c.load(:id=>1).modified?.must_equal false
595
- end
596
-
597
- it "should be true if the object has been modified" do
598
- o = @c.load(:id=>1, :x=>2)
599
- o.x = 3
600
- o.modified?.must_equal true
601
- end
602
-
603
- it "should be true if the object is marked modified!" do
604
- o = @c.load(:id=>1, :x=>2)
605
- o.modified!
606
- o.modified?.must_equal true
607
- end
608
-
609
- it "should be false if the object is marked modified! after saving until modified! again" do
610
- o = @c.load(:id=>1, :x=>2)
611
- o.modified!
612
- o.save
613
- o.modified?.must_equal false
614
- o.modified!
615
- o.modified?.must_equal true
616
- end
617
-
618
- it "should be false if a column value is set that is the same as the current value after typecasting" do
619
- o = @c.load(:id=>1, :x=>2)
620
- o.x = '2'
621
- o.modified?.must_equal false
622
- end
623
-
624
- it "should be true if a column value is set that is the different as the current value after typecasting" do
625
- o = @c.load(:id=>1, :x=>'2')
626
- o.x = '2'
627
- o.modified?.must_equal true
628
- end
629
-
630
- it "should be true if given a column argument and the column has been changed" do
631
- o = @c.new
632
- o.modified?(:id).must_equal false
633
- o.id = 1
634
- o.modified?(:id).must_equal true
635
- end
636
- end
637
-
638
- describe "Model#modified!" do
639
- before do
640
- @c = Class.new(Sequel::Model(:items))
641
- @c.class_eval do
642
- columns :id, :x
643
- end
644
- DB.reset
645
- end
646
-
647
- it "should mark the object as modified so that save_changes still runs the callbacks" do
648
- o = @c.load(:id=>1, :x=>2)
649
- def o.after_save
650
- values[:x] = 3
651
- end
652
- o.update({})
653
- o.x.must_equal 2
654
-
655
- o.modified!
656
- o.update({})
657
- o.x.must_equal 3
658
- o.db.sqls.must_equal []
659
- end
660
-
661
- it "should mark given column argument as modified" do
662
- o = @c.load(:id=>1, :x=>2)
663
- o.modified!(:x)
664
- o.changed_columns.must_equal [:x]
665
- o.save
666
- o.db.sqls.must_equal ["UPDATE items SET x = 2 WHERE (id = 1)"]
667
- end
668
- end
669
-
670
- describe "Model#save_changes" do
671
- before do
672
- @c = Class.new(Sequel::Model(:items)) do
673
- unrestrict_primary_key
674
- columns :id, :x, :y
675
- end
676
- DB.reset
677
- end
678
-
679
- it "should always save if the object is new" do
680
- o = @c.new(:x => 1)
681
- o.save_changes
682
- DB.sqls.first.must_equal "INSERT INTO items (x) VALUES (1)"
683
- end
684
-
685
- it "should take options passed to save" do
686
- o = @c.load(:id=>1, :x => 1)
687
- o.x = 2
688
- o.save_changes
689
- DB.sqls.must_equal ["UPDATE items SET x = 2 WHERE (id = 1)"]
690
-
691
- o.x = 3
692
- o.save_changes(:transaction=>true)
693
- DB.sqls.must_equal ["BEGIN", "UPDATE items SET x = 3 WHERE (id = 1)", "COMMIT"]
694
- end
695
-
696
- it "should do nothing if no changed columns" do
697
- o = @c.load(:id => 3, :x => 1, :y => nil)
698
- o.save_changes
699
- DB.sqls.must_equal []
700
- end
701
-
702
- it "should do nothing if modified? is false" do
703
- o = @c.load(:id => 3, :x => 1, :y => nil)
704
- def o.modified?; false; end
705
- o.save_changes
706
- DB.sqls.must_equal []
707
- end
708
-
709
- it "should update only changed columns" do
710
- o = @c.load(:id => 3, :x => 1, :y => nil)
711
- o.x = 2
712
-
713
- o.save_changes
714
- DB.sqls.must_equal ["UPDATE items SET x = 2 WHERE (id = 3)"]
715
- o.save_changes
716
- o.save_changes
717
- DB.sqls.must_equal []
718
-
719
- o.y = 4
720
- o.save_changes
721
- DB.sqls.must_equal ["UPDATE items SET y = 4 WHERE (id = 3)"]
722
- o.save_changes
723
- o.save_changes
724
- DB.sqls.must_equal []
725
- end
726
-
727
- it "should not consider columns changed if the values did not change" do
728
- o = @c.load(:id => 3, :x => 1, :y => nil)
729
- o.x = 1
730
-
731
- o.save_changes
732
- DB.sqls.must_equal []
733
- o.x = 3
734
- o.save_changes
735
- DB.sqls.must_equal ["UPDATE items SET x = 3 WHERE (id = 3)"]
736
-
737
- o[:y] = nil
738
- o.save_changes
739
- DB.sqls.must_equal []
740
- o[:y] = 4
741
- o.save_changes
742
- DB.sqls.must_equal ["UPDATE items SET y = 4 WHERE (id = 3)"]
743
- end
744
-
745
- it "should clear changed_columns" do
746
- o = @c.load(:id => 3, :x => 1, :y => nil)
747
- o.x = 4
748
- o.changed_columns.must_equal [:x]
749
- o.save_changes
750
- o.changed_columns.must_equal []
751
- end
752
-
753
- it "should update columns changed in a before_update hook" do
754
- o = @c.load(:id => 3, :x => 1, :y => nil)
755
- @c.send(:define_method, :before_update){self.x += 1}
756
- o.save_changes
757
- DB.sqls.must_equal []
758
- o.x = 2
759
- o.save_changes
760
- DB.sqls.must_equal ["UPDATE items SET x = 3 WHERE (id = 3)"]
761
- o.save_changes
762
- DB.sqls.must_equal []
763
- o.x = 4
764
- o.save_changes
765
- DB.sqls.must_equal ["UPDATE items SET x = 5 WHERE (id = 3)"]
766
- end
767
-
768
- it "should update columns changed in a before_save hook" do
769
- o = @c.load(:id => 3, :x => 1, :y => nil)
770
- @c.send(:define_method, :before_update){self.x += 1}
771
- o.save_changes
772
- DB.sqls.must_equal []
773
- o.x = 2
774
- o.save_changes
775
- DB.sqls.must_equal ["UPDATE items SET x = 3 WHERE (id = 3)"]
776
- o.save_changes
777
- DB.sqls.must_equal []
778
- o.x = 4
779
- o.save_changes
780
- DB.sqls.must_equal ["UPDATE items SET x = 5 WHERE (id = 3)"]
781
- end
782
- end
783
-
784
- describe "Model#new?" do
785
- before do
786
- @c = Class.new(Sequel::Model(:items)) do
787
- unrestrict_primary_key
788
- columns :x
789
- end
790
- DB.reset
791
- end
792
-
793
- it "should be true for a new instance" do
794
- n = @c.new(:x => 1)
795
- n.must_be :new?
796
- end
797
-
798
- it "should be false after saving" do
799
- n = @c.new(:x => 1)
800
- n.save
801
- n.wont_be :new?
802
- end
803
- end
804
-
805
- describe Sequel::Model, "with a primary key" do
806
- it "should default to :id" do
807
- model_a = Class.new Sequel::Model
808
- model_a.primary_key.must_equal :id
809
- end
810
-
811
- it "should be changed through 'set_primary_key'" do
812
- model_a = Class.new(Sequel::Model){ set_primary_key :a }
813
- model_a.primary_key.must_equal :a
814
- end
815
-
816
- it "should accept single argument composite keys" do
817
- model_a = Class.new(Sequel::Model){ set_primary_key [:a, :b] }
818
- model_a.primary_key.must_equal [:a, :b]
819
- end
820
- end
821
-
822
- describe Sequel::Model, "without a primary key" do
823
- it "should return nil for primary key" do
824
- Class.new(Sequel::Model){no_primary_key}.primary_key.must_be_nil
825
- end
826
-
827
- it "should raise a Sequel::Error on 'this'" do
828
- instance = Class.new(Sequel::Model){no_primary_key}.new
829
- proc{instance.this}.must_raise(Sequel::Error)
830
- end
831
- end
832
-
833
- describe Sequel::Model, "#this" do
834
- before do
835
- @example = Class.new(Sequel::Model(:examples))
836
- @example.columns :id, :a, :x, :y
837
- end
838
-
839
- it "should return a dataset identifying the record" do
840
- instance = @example.load(:id => 3)
841
- instance.this.sql.must_equal "SELECT * FROM examples WHERE (id = 3) LIMIT 1"
842
- end
843
-
844
- it "should support arbitary primary keys" do
845
- @example.set_primary_key :a
846
-
847
- instance = @example.load(:a => 3)
848
- instance.this.sql.must_equal "SELECT * FROM examples WHERE (a = 3) LIMIT 1"
849
- end
850
-
851
- it "should use a subquery if the dataset is joined" do
852
- @example.dataset = @example.dataset.cross_join(:a)
853
- instance = @example.load(:id => 3)
854
- instance.this.sql.must_equal "SELECT * FROM (SELECT * FROM examples CROSS JOIN a) AS examples WHERE (id = 3) LIMIT 1"
855
- end
856
-
857
- it "should use a primary key if the dataset uses a subquery" do
858
- @example.dataset = @example.dataset.cross_join(:a).from_self(:alias=>:b)
859
- instance = @example.load(:id => 3)
860
- instance.this.sql.must_equal "SELECT * FROM (SELECT * FROM examples CROSS JOIN a) AS b WHERE (id = 3) LIMIT 1"
861
- end
862
-
863
- it "should support composite primary keys" do
864
- @example.set_primary_key [:x, :y]
865
- instance = @example.load(:x => 4, :y => 5)
866
- instance.this.sql.must_equal 'SELECT * FROM examples WHERE ((x = 4) AND (y = 5)) LIMIT 1'
867
- end
868
- end
869
-
870
- describe "Model#pk" do
871
- before do
872
- @m = Class.new(Sequel::Model)
873
- @m.columns :id, :x, :y
874
- end
875
-
876
- it "should by default return the value of the :id column" do
877
- m = @m.load(:id => 111, :x => 2, :y => 3)
878
- m.pk.must_equal 111
879
- end
880
-
881
- it "should return the primary key value for custom primary key" do
882
- @m.set_primary_key :x
883
- m = @m.load(:id => 111, :x => 2, :y => 3)
884
- m.pk.must_equal 2
885
- end
886
-
887
- it "should return the primary key value for composite primary key" do
888
- @m.set_primary_key [:y, :x]
889
- m = @m.load(:id => 111, :x => 2, :y => 3)
890
- m.pk.must_equal [3, 2]
891
- end
892
-
893
- it "should raise if no primary key" do
894
- @m.set_primary_key nil
895
- m = @m.new(:id => 111, :x => 2, :y => 3)
896
- proc {m.pk}.must_raise(Sequel::Error)
897
-
898
- @m.no_primary_key
899
- m = @m.new(:id => 111, :x => 2, :y => 3)
900
- proc {m.pk}.must_raise(Sequel::Error)
901
- end
902
- end
903
-
904
- describe "Model#pk_hash" do
905
- before do
906
- @m = Class.new(Sequel::Model)
907
- @m.columns :id, :x, :y
908
- end
909
-
910
- it "should by default return a hash with the value of the :id column" do
911
- m = @m.load(:id => 111, :x => 2, :y => 3)
912
- m.pk_hash.must_equal(:id => 111)
913
- end
914
-
915
- it "should return a hash with the primary key value for custom primary key" do
916
- @m.set_primary_key :x
917
- m = @m.load(:id => 111, :x => 2, :y => 3)
918
- m.pk_hash.must_equal(:x => 2)
919
- end
920
-
921
- it "should return a hash with the primary key values for composite primary key" do
922
- @m.set_primary_key [:y, :x]
923
- m = @m.load(:id => 111, :x => 2, :y => 3)
924
- m.pk_hash.must_equal(:y => 3, :x => 2)
925
- end
926
-
927
- it "should raise if no primary key" do
928
- @m.set_primary_key nil
929
- m = @m.new(:id => 111, :x => 2, :y => 3)
930
- proc{m.pk_hash}.must_raise(Sequel::Error)
931
-
932
- @m.no_primary_key
933
- m = @m.new(:id => 111, :x => 2, :y => 3)
934
- proc{m.pk_hash}.must_raise(Sequel::Error)
935
- end
936
- end
937
-
938
- describe "Model#qualified_pk_hash" do
939
- before do
940
- @m = Class.new(Sequel::Model(:items))
941
- @m.columns :id, :x, :y
942
- end
943
-
944
- it "should by default return a hash with the value of the :id column" do
945
- m = @m.load(:id => 111, :x => 2, :y => 3)
946
- m.qualified_pk_hash.must_equal(Sequel.qualify(:items, :id) => 111)
947
- end
948
-
949
- it "should accept a custom qualifier" do
950
- m = @m.load(:id => 111, :x => 2, :y => 3)
951
- m.qualified_pk_hash(:foo).must_equal(Sequel.qualify(:foo, :id) => 111)
952
- end
953
-
954
- it "should return a hash with the primary key value for custom primary key" do
955
- @m.set_primary_key :x
956
- m = @m.load(:id => 111, :x => 2, :y => 3)
957
- m.qualified_pk_hash.must_equal(Sequel.qualify(:items, :x) => 2)
958
- end
959
-
960
- it "should return a hash with the primary key values for composite primary key" do
961
- @m.set_primary_key [:y, :x]
962
- m = @m.load(:id => 111, :x => 2, :y => 3)
963
- m.qualified_pk_hash.must_equal(Sequel.qualify(:items, :y) => 3, Sequel.qualify(:items, :x) => 2)
964
- end
965
-
966
- it "should raise if no primary key" do
967
- @m.set_primary_key nil
968
- m = @m.new(:id => 111, :x => 2, :y => 3)
969
- proc{m.qualified_pk_hash}.must_raise(Sequel::Error)
970
-
971
- @m.no_primary_key
972
- m = @m.new(:id => 111, :x => 2, :y => 3)
973
- proc{m.qualified_pk_hash}.must_raise(Sequel::Error)
974
- end
975
- end
976
-
977
- describe Sequel::Model, "#set" do
978
- before do
979
- @c = Class.new(Sequel::Model(:items)) do
980
- set_primary_key :id
981
- columns :x, :y, :id
982
- end
983
- @c.strict_param_setting = false
984
- @o1 = @c.new
985
- @o2 = @c.load(:id => 5)
986
- DB.reset
987
- end
988
-
989
- it "should filter the given params using the model columns" do
990
- @o1.set(:x => 1, :z => 2)
991
- @o1.values.must_equal(:x => 1)
992
- DB.sqls.must_equal []
993
-
994
- @o2.set(:y => 1, :abc => 2)
995
- @o2.values.must_equal(:y => 1, :id=> 5)
996
- DB.sqls.must_equal []
997
- end
998
-
999
- it "should work with both strings and symbols" do
1000
- @o1.set('x'=> 1, 'z'=> 2)
1001
- @o1.values.must_equal(:x => 1)
1002
- DB.sqls.must_equal []
1003
-
1004
- @o2.set('y'=> 1, 'abc'=> 2)
1005
- @o2.values.must_equal(:y => 1, :id=> 5)
1006
- DB.sqls.must_equal []
1007
- end
1008
-
1009
- it "should support virtual attributes" do
1010
- @c.send(:define_method, :blah=){|v| self.x = v}
1011
- @o1.set(:blah => 333)
1012
- @o1.values.must_equal(:x => 333)
1013
- DB.sqls.must_equal []
1014
- @o1.set('blah'=> 334)
1015
- @o1.values.must_equal(:x => 334)
1016
- DB.sqls.must_equal []
1017
- end
1018
-
1019
- it "should not modify the primary key" do
1020
- @o1.set(:x => 1, :id => 2)
1021
- @o1.values.must_equal(:x => 1)
1022
- DB.sqls.must_equal []
1023
- @o2.set('y'=> 1, 'id'=> 2)
1024
- @o2.values.must_equal(:y => 1, :id=> 5)
1025
- DB.sqls.must_equal []
1026
- end
1027
-
1028
- it "should return self" do
1029
- returned_value = @o1.set(:x => 1, :z => 2)
1030
- returned_value.must_equal @o1
1031
- DB.sqls.must_equal []
1032
- end
1033
-
1034
- it "should raise error if strict_param_setting is true and method does not exist" do
1035
- @o1.strict_param_setting = true
1036
- proc{@o1.set('foo' => 1)}.must_raise(Sequel::MassAssignmentRestriction)
1037
- end
1038
-
1039
- it "should raise error if strict_param_setting is true and column is a primary key" do
1040
- @o1.strict_param_setting = true
1041
- proc{@o1.set('id' => 1)}.must_raise(Sequel::MassAssignmentRestriction)
1042
- end
1043
-
1044
- it "should raise error if strict_param_setting is true and column is restricted" do
1045
- @o1.strict_param_setting = true
1046
- @c.setter_methods.delete("x=")
1047
- proc{@o1.set('x' => 1)}.must_raise(Sequel::MassAssignmentRestriction)
1048
- end
1049
-
1050
- it "should not create a symbol if strict_param_setting is true and string is given" do
1051
- @o1.strict_param_setting = true
1052
- proc{@o1.set('sadojafdso' => 1)}.must_raise(Sequel::MassAssignmentRestriction)
1053
- Symbol.all_symbols.map(&:to_s).wont_include('sadojafdso')
1054
- end
1055
-
1056
- it "#set should correctly handle cases where an instance method is added to the class" do
1057
- @o1.set(:x => 1)
1058
- @o1.values.must_equal(:x => 1)
1059
-
1060
- @c.class_eval do
1061
- def z=(v)
1062
- self[:z] = v
1063
- end
1064
- end
1065
- @o1.set(:x => 2, :z => 3)
1066
- @o1.values.must_equal(:x => 2, :z=>3)
1067
- end
1068
-
1069
- it "#set should correctly handle cases where a singleton method is added to the object" do
1070
- @o1.set(:x => 1)
1071
- @o1.values.must_equal(:x => 1)
1072
-
1073
- def @o1.z=(v)
1074
- self[:z] = v
1075
- end
1076
- @o1.set(:x => 2, :z => 3)
1077
- @o1.values.must_equal(:x => 2, :z=>3)
1078
- end
1079
-
1080
- it "#set should correctly handle cases where a module with a setter method is included in the class" do
1081
- @o1.set(:x => 1)
1082
- @o1.values.must_equal(:x => 1)
1083
-
1084
- @c.send(:include, Module.new do
1085
- def z=(v)
1086
- self[:z] = v
1087
- end
1088
- end)
1089
- @o1.set(:x => 2, :z => 3)
1090
- @o1.values.must_equal(:x => 2, :z=>3)
1091
- end
1092
-
1093
- it "#set should correctly handle cases where the object extends a module with a setter method " do
1094
- @o1.set(:x => 1)
1095
- @o1.values.must_equal(:x => 1)
1096
-
1097
- @o1.extend(Module.new do
1098
- def z=(v)
1099
- self[:z] = v
1100
- end
1101
- end)
1102
- @o1.set(:x => 2, :z => 3)
1103
- @o1.values.must_equal(:x => 2, :z=>3)
1104
- end
1105
- end
1106
-
1107
- describe Sequel::Model, "#update" do
1108
- before do
1109
- @c = Class.new(Sequel::Model(:items)) do
1110
- set_primary_key :id
1111
- columns :x, :y, :id
1112
- end
1113
- @c.strict_param_setting = false
1114
- @o1 = @c.new
1115
- @o2 = @c.load(:id => 5)
1116
- DB.reset
1117
- end
1118
-
1119
- it "should filter the given params using the model columns" do
1120
- @o1.update(:x => 1, :z => 2)
1121
- DB.sqls.must_equal ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE id = 10"]
1122
-
1123
- DB.reset
1124
- @o2.update(:y => 1, :abc => 2)
1125
- DB.sqls.must_equal ["UPDATE items SET y = 1 WHERE (id = 5)"]
1126
- end
1127
-
1128
- it "should support virtual attributes" do
1129
- @c.send(:define_method, :blah=){|v| self.x = v}
1130
- @o1.update(:blah => 333)
1131
- DB.sqls.must_equal ["INSERT INTO items (x) VALUES (333)", "SELECT * FROM items WHERE id = 10"]
1132
- end
1133
-
1134
- it "should not modify the primary key" do
1135
- @o1.update(:x => 1, :id => 2)
1136
- DB.sqls.must_equal ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE id = 10"]
1137
- DB.reset
1138
- @o2.update('y'=> 1, 'id'=> 2)
1139
- @o2.values.must_equal(:y => 1, :id=> 5)
1140
- DB.sqls.must_equal ["UPDATE items SET y = 1 WHERE (id = 5)"]
1141
- end
1142
- end
1143
-
1144
- describe Sequel::Model, "#set_fields" do
1145
- before do
1146
- @c = Class.new(Sequel::Model(:items)) do
1147
- set_primary_key :id
1148
- columns :x, :y, :z, :id
1149
- end
1150
- @o1 = @c.new
1151
- DB.reset
1152
- end
1153
-
1154
- it "should set only the given fields" do
1155
- @o1.set_fields({:x => 1, :y => 2, :z=>3, :id=>4}, [:x, :y])
1156
- @o1.values.must_equal(:x => 1, :y => 2)
1157
- @o1.set_fields({:x => 9, :y => 8, :z=>6, :id=>7}, [:x, :y, :id])
1158
- @o1.values.must_equal(:x => 9, :y => 8, :id=>7)
1159
- DB.sqls.must_equal []
1160
- end
1161
-
1162
- it "should lookup into the hash without checking if the entry exists" do
1163
- @o1.set_fields({:x => 1}, [:x, :y])
1164
- @o1.values.must_equal(:x => 1, :y => nil)
1165
- @o1.set_fields(Hash.new(2), [:x, :y])
1166
- @o1.values.must_equal(:x => 2, :y => 2)
1167
- end
1168
-
1169
- it "should skip missing fields if :missing=>:skip option is used" do
1170
- @o1.set_fields({:x => 3}, [:x, :y], :missing=>:skip)
1171
- @o1.values.must_equal(:x => 3)
1172
- @o1.set_fields({"x" => 4}, [:x, :y], :missing=>:skip)
1173
- @o1.values.must_equal(:x => 4)
1174
- @o1.set_fields(Hash.new(2).merge(:x=>2), [:x, :y], :missing=>:skip)
1175
- @o1.values.must_equal(:x => 2)
1176
- @o1.set_fields({:x => 1, :y => 2, :z=>3, :id=>4}, [:x, :y], :missing=>:skip)
1177
- @o1.values.must_equal(:x => 1, :y => 2)
1178
- end
1179
-
1180
- it "should raise for missing fields if :missing=>:raise option is used" do
1181
- proc{@o1.set_fields({:x => 1}, [:x, :y], :missing=>:raise)}.must_raise(Sequel::Error)
1182
- proc{@o1.set_fields(Hash.new(2).merge(:x=>2), [:x, :y], :missing=>:raise)}.must_raise(Sequel::Error)
1183
- proc{@o1.set_fields({"x" => 1}, [:x, :y], :missing=>:raise)}.must_raise(Sequel::Error)
1184
- @o1.set_fields({:x => 5, "y"=>2}, [:x, :y], :missing=>:raise)
1185
- @o1.values.must_equal(:x => 5, :y => 2)
1186
- @o1.set_fields({:x => 1, :y => 3, :z=>3, :id=>4}, [:x, :y], :missing=>:raise)
1187
- @o1.values.must_equal(:x => 1, :y => 3)
1188
- end
1189
-
1190
- it "should use default behavior for an unrecognized :missing option" do
1191
- @o1.set_fields({:x => 1, :y => 2, :z=>3, :id=>4}, [:x, :y], :missing=>:foo)
1192
- @o1.values.must_equal(:x => 1, :y => 2)
1193
- @o1.set_fields({:x => 9, :y => 8, :z=>6, :id=>7}, [:x, :y, :id], :missing=>:foo)
1194
- @o1.values.must_equal(:x => 9, :y => 8, :id=>7)
1195
- DB.sqls.must_equal []
1196
- end
1197
-
1198
- it "should respect model's default_set_fields_options" do
1199
- @c.default_set_fields_options = {:missing=>:skip}
1200
- @o1.set_fields({:x => 3}, [:x, :y])
1201
- @o1.values.must_equal(:x => 3)
1202
- @o1.set_fields({:x => 4}, [:x, :y], {})
1203
- @o1.values.must_equal(:x => 4)
1204
- proc{@o1.set_fields({:x => 3}, [:x, :y], :missing=>:raise)}.must_raise(Sequel::Error)
1205
- @c.default_set_fields_options = {:missing=>:raise}
1206
- proc{@o1.set_fields({:x => 3}, [:x, :y])}.must_raise(Sequel::Error)
1207
- proc{@o1.set_fields({:x => 3}, [:x, :y], {})}.must_raise(Sequel::Error)
1208
- @o1.set_fields({:x => 5}, [:x, :y], :missing=>:skip)
1209
- @o1.values.must_equal(:x => 5)
1210
- @o1.set_fields({:x => 5}, [:x, :y], :missing=>nil)
1211
- @o1.values.must_equal(:x => 5, :y=>nil)
1212
- DB.sqls.must_equal []
1213
- end
1214
-
1215
- it "should respect model's default_set_fields_options in a subclass" do
1216
- @c.default_set_fields_options = {:missing=>:skip}
1217
- o = Class.new(@c).new
1218
- o.set_fields({:x => 3}, [:x, :y])
1219
- o.values.must_equal(:x => 3)
1220
- end
1221
-
1222
- it "should respect set_column_value" do
1223
- @c.class_eval do
1224
- def set_column_value(c, v)
1225
- if c.to_s == 'model='
1226
- self[:model] = v
1227
- else
1228
- send(c, v)
1229
- end
1230
- end
1231
- end
1232
- @o1.set_fields({:model=>2, :x=>3}, [:model, :x])
1233
- @o1[:model].must_equal 2
1234
- @o1.x.must_equal 3
1235
- end
1236
- end
1237
-
1238
- describe Sequel::Model, "#update_fields" do
1239
- before do
1240
- @c = Class.new(Sequel::Model(:items)) do
1241
- set_primary_key :id
1242
- columns :x, :y, :z, :id
1243
- end
1244
- @c.strict_param_setting = true
1245
- @o1 = @c.load(:id=>1)
1246
- DB.reset
1247
- end
1248
-
1249
- it "should set only the given fields, and then save the changes to the record" do
1250
- @o1.update_fields({:x => 1, :y => 2, :z=>3, :id=>4}, [:x, :y])
1251
- @o1.values.must_equal(:x => 1, :y => 2, :id=>1)
1252
- DB.sqls.must_equal ['UPDATE items SET x = 1, y = 2 WHERE (id = 1)']
1253
-
1254
- @o1.update_fields({:x => 1, :y => 5, :z=>6, :id=>7}, [:x, :y])
1255
- @o1.values.must_equal(:x => 1, :y => 5, :id=>1)
1256
- DB.sqls.must_equal ["UPDATE items SET y = 5 WHERE (id = 1)"]
1257
- end
1258
-
1259
- it "should support :missing=>:skip option" do
1260
- @o1.update_fields({:x => 1, :z=>3, :id=>4}, [:x, :y], :missing=>:skip)
1261
- @o1.values.must_equal(:x => 1, :id=>1)
1262
- DB.sqls.must_equal ["UPDATE items SET x = 1 WHERE (id = 1)"]
1263
- end
1264
-
1265
- it "should support :missing=>:raise option" do
1266
- proc{@o1.update_fields({:x => 1}, [:x, :y], :missing=>:raise)}.must_raise(Sequel::Error)
1267
- end
1268
-
1269
- it "should respect model's default_set_fields_options" do
1270
- @c.default_set_fields_options = {:missing=>:skip}
1271
- @o1.update_fields({:x => 3}, [:x, :y])
1272
- @o1.values.must_equal(:x => 3, :id=>1)
1273
- DB.sqls.must_equal ["UPDATE items SET x = 3 WHERE (id = 1)"]
1274
-
1275
- @c.default_set_fields_options = {:missing=>:raise}
1276
- proc{@o1.update_fields({:x => 3}, [:x, :y])}.must_raise(Sequel::Error)
1277
- DB.sqls.must_equal []
1278
- end
1279
- end
1280
-
1281
- describe Sequel::Model, "#destroy with filtered dataset" do
1282
- before do
1283
- @model = Class.new(Sequel::Model(DB[:items].where(:a=>1)))
1284
- @model.columns :id, :a
1285
- @instance = @model.load(:id => 1234)
1286
- DB.reset
1287
- end
1288
-
1289
- it "should raise a NoExistingObject exception if the dataset delete call doesn't return 1" do
1290
- i = 0
1291
- @model.dataset = @model.dataset.with_extend{define_method(:execute_dui){|*| i}}
1292
- proc{@instance.delete}.must_raise(Sequel::NoExistingObject)
1293
- i = 2
1294
- proc{@instance.delete}.must_raise(Sequel::NoExistingObject)
1295
- i = 1
1296
- @instance.delete
1297
-
1298
- @instance.require_modification = false
1299
- i = 0
1300
- @instance.delete
1301
- i = 2
1302
- @instance.delete
1303
- end
1304
-
1305
- it "should include WHERE clause when deleting" do
1306
- @instance.destroy
1307
- DB.sqls.must_equal ["DELETE FROM items WHERE ((a = 1) AND (id = 1234))"]
1308
- end
1309
- end
1310
-
1311
- describe Sequel::Model, "#destroy" do
1312
- before do
1313
- @model = Class.new(Sequel::Model(:items))
1314
- @model.columns :id
1315
- @instance = @model.load(:id => 1234)
1316
- DB.reset
1317
- end
1318
-
1319
- it "should return self" do
1320
- @model.send(:define_method, :after_destroy){3}
1321
- @instance.destroy.must_equal @instance
1322
- end
1323
-
1324
- it "should raise a NoExistingObject exception if the dataset delete call doesn't return 1" do
1325
- i = 0
1326
- @model.dataset = @model.dataset.with_extend{define_method(:execute_dui){|*| i}}
1327
- proc{@instance.delete}.must_raise(Sequel::NoExistingObject)
1328
- i = 2
1329
- proc{@instance.delete}.must_raise(Sequel::NoExistingObject)
1330
- i = 1
1331
- @instance.delete
1332
-
1333
- @instance.require_modification = false
1334
- i = 0
1335
- @instance.delete
1336
- i = 2
1337
- @instance.delete
1338
- end
1339
-
1340
- it "should run within a transaction if use_transactions is true" do
1341
- @instance.use_transactions = true
1342
- @instance.destroy
1343
- DB.sqls.must_equal ["BEGIN", "DELETE FROM items WHERE id = 1234", "COMMIT"]
1344
- end
1345
-
1346
- it "should not run within a transaction if use_transactions is false" do
1347
- @instance.use_transactions = false
1348
- @instance.destroy
1349
- DB.sqls.must_equal ["DELETE FROM items WHERE id = 1234"]
1350
- end
1351
-
1352
- it "should run within a transaction if :transaction option is true" do
1353
- @instance.use_transactions = false
1354
- @instance.destroy(:transaction => true)
1355
- DB.sqls.must_equal ["BEGIN", "DELETE FROM items WHERE id = 1234", "COMMIT"]
1356
- end
1357
-
1358
- it "should not run within a transaction if :transaction option is false" do
1359
- @instance.use_transactions = true
1360
- @instance.destroy(:transaction => false)
1361
- DB.sqls.must_equal ["DELETE FROM items WHERE id = 1234"]
1362
- end
1363
-
1364
- it "should run before_destroy and after_destroy hooks" do
1365
- @model.send(:define_method, :before_destroy){DB.execute('before blah')}
1366
- @model.send(:define_method, :after_destroy){DB.execute('after blah')}
1367
- @instance.destroy
1368
- DB.sqls.must_equal ["before blah", "DELETE FROM items WHERE id = 1234", "after blah"]
1369
- end
1370
- end
1371
-
1372
- describe Sequel::Model, "#exists?" do
1373
- before do
1374
- @model = Class.new(Sequel::Model(:items))
1375
- @model.dataset = @model.dataset.with_fetch(proc{|sql| {:x=>1} if sql =~ /id = 1/})
1376
- DB.reset
1377
- end
1378
-
1379
- it "should do a query to check if the record exists" do
1380
- @model.load(:id=>1).exists?.must_equal true
1381
- DB.sqls.must_equal ['SELECT 1 AS one FROM items WHERE (id = 1) LIMIT 1']
1382
- end
1383
-
1384
- it "should return false when #this.count == 0" do
1385
- @model.load(:id=>2).exists?.must_equal false
1386
- DB.sqls.must_equal ['SELECT 1 AS one FROM items WHERE (id = 2) LIMIT 1']
1387
- end
1388
-
1389
- it "should return false without issuing a query if the model object is new" do
1390
- @model.new.exists?.must_equal false
1391
- DB.sqls.must_equal []
1392
- end
1393
- end
1394
-
1395
- describe Sequel::Model, "#each" do
1396
- before do
1397
- @model = Class.new(Sequel::Model(:items))
1398
- @model.columns :a, :b, :id
1399
- @m = @model.load(:a => 1, :b => 2, :id => 4444)
1400
- end
1401
-
1402
- it "should iterate over the values" do
1403
- h = {}
1404
- @m.each{|k, v| h[k] = v}
1405
- h.must_equal(:a => 1, :b => 2, :id => 4444)
1406
- end
1407
- end
1408
-
1409
- describe Sequel::Model, "#keys" do
1410
- before do
1411
- @model = Class.new(Sequel::Model(:items))
1412
- @model.columns :a, :b, :id
1413
- @m = @model.load(:a => 1, :b => 2, :id => 4444)
1414
- end
1415
-
1416
- it "should return the value keys" do
1417
- @m.keys.sort_by{|k| k.to_s}.must_equal [:a, :b, :id]
1418
- @model.new.keys.must_equal []
1419
- end
1420
- end
1421
-
1422
- describe Sequel::Model, "#==" do
1423
- it "should compare instances by values" do
1424
- z = Class.new(Sequel::Model)
1425
- z.columns :id, :x
1426
- a = z.load(:id => 1, :x => 3)
1427
- b = z.load(:id => 1, :x => 4)
1428
- c = z.load(:id => 1, :x => 3)
1429
-
1430
- a.wont_equal b
1431
- a.must_equal c
1432
- b.wont_equal c
1433
- end
1434
-
1435
- it "should be aliased to #eql?" do
1436
- z = Class.new(Sequel::Model)
1437
- z.columns :id, :x
1438
- a = z.load(:id => 1, :x => 3)
1439
- b = z.load(:id => 1, :x => 4)
1440
- c = z.load(:id => 1, :x => 3)
1441
-
1442
- a.eql?(b).must_equal false
1443
- a.eql?(c).must_equal true
1444
- b.eql?(c).must_equal false
1445
- end
1446
- end
1447
-
1448
- [:===, :pk_equal?].each do |method_name|
1449
- describe Sequel::Model, "##{method_name}" do
1450
- it "should compare instances by class and pk if pk is not nil" do
1451
- z = Class.new(Sequel::Model)
1452
- z.columns :id, :x
1453
- y = Class.new(Sequel::Model)
1454
- y.columns :id, :x
1455
- a = z.load(:id => 1, :x => 3)
1456
- b = z.load(:id => 1, :x => 4)
1457
- c = z.load(:id => 2, :x => 3)
1458
- d = y.load(:id => 1, :x => 3)
1459
-
1460
- a.must_be method_name, b
1461
- a.wont_be method_name, c
1462
- a.wont_be method_name, d
1463
- end
1464
-
1465
- it "should always be false if the primary key is nil" do
1466
- z = Class.new(Sequel::Model)
1467
- z.columns :id, :x
1468
- y = Class.new(Sequel::Model)
1469
- y.columns :id, :x
1470
- a = z.new(:x => 3)
1471
- b = z.new(:x => 4)
1472
- c = z.new(:x => 3)
1473
- d = y.new(:x => 3)
1474
-
1475
- a.wont_be method_name, b
1476
- a.wont_be method_name, c
1477
- a.wont_be method_name, d
1478
- end
1479
-
1480
- it "should always be false if the primary key is an array containing nil" do
1481
- z = Class.new(Sequel::Model)
1482
- z.columns :id, :x
1483
- z.set_primary_key [:id, :x]
1484
- z.load(:id => nil, :x => nil).wont_be method_name, z.load(:id => nil, :x => nil)
1485
- z.load(:id => 1, :x => nil).wont_be method_name, z.load(:id => 1, :x => nil)
1486
- z.load(:id => nil, :x => 2).wont_be method_name, z.load(:id => nil, :x => 2)
1487
- end
1488
- end
1489
- end
1490
-
1491
- describe Sequel::Model, "#hash" do
1492
- it "should be the same only for objects with the same class and pk if the pk is not nil" do
1493
- z = Class.new(Sequel::Model)
1494
- z.columns :id, :x
1495
- y = Class.new(Sequel::Model)
1496
- y.columns :id, :x
1497
- a = z.load(:id => 1, :x => 3)
1498
-
1499
- a.hash.must_equal z.load(:id => 1, :x => 4).hash
1500
- a.hash.wont_equal z.load(:id => 2, :x => 3).hash
1501
- a.hash.wont_equal y.load(:id => 1, :x => 3).hash
1502
- end
1503
-
1504
- it "should be the same only for objects with the same class and values if the pk is nil" do
1505
- z = Class.new(Sequel::Model)
1506
- z.columns :id, :x
1507
- y = Class.new(Sequel::Model)
1508
- y.columns :id, :x
1509
- a = z.new(:x => 3)
1510
-
1511
- a.hash.wont_equal z.new(:x => 4).hash
1512
- a.hash.must_equal z.new(:x => 3).hash
1513
- a.hash.wont_equal y.new(:x => 3).hash
1514
- end
1515
-
1516
- it "should be the same only for objects with the same class and pk if pk is composite and all values are non-NULL" do
1517
- z = Class.new(Sequel::Model)
1518
- z.columns :id, :id2, :x
1519
- z.set_primary_key([:id, :id2])
1520
- y = Class.new(Sequel::Model)
1521
- y.columns :id, :id2, :x
1522
- y.set_primary_key([:id, :id2])
1523
- a = z.load(:id => 1, :id2=>2, :x => 3)
1524
-
1525
- a.hash.must_equal z.load(:id => 1, :id2=>2, :x => 4).hash
1526
- a.hash.wont_equal z.load(:id => 2, :id2=>1, :x => 3).hash
1527
- a.hash.wont_equal y.load(:id => 1, :id2=>1, :x => 3).hash
1528
- end
1529
-
1530
- it "should be the same only for objects with the same class and value if pk is composite and one values is NULL" do
1531
- z = Class.new(Sequel::Model)
1532
- z.columns :id, :id2, :x
1533
- z.set_primary_key([:id, :id2])
1534
- y = Class.new(Sequel::Model)
1535
- y.columns :id, :id2, :x
1536
- y.set_primary_key([:id, :id2])
1537
-
1538
- a = z.load(:id => 1, :id2 => nil, :x => 3)
1539
- a.hash.must_equal z.load(:id => 1, :id2=>nil, :x => 3).hash
1540
- a.hash.wont_equal z.load(:id => 1, :id2=>nil, :x => 4).hash
1541
- a.hash.wont_equal y.load(:id => 1, :id2=>nil, :x => 3).hash
1542
-
1543
- a = z.load(:id =>nil, :id2 => nil, :x => 3)
1544
- a.hash.must_equal z.load(:id => nil, :id2=>nil, :x => 3).hash
1545
- a.hash.wont_equal z.load(:id => nil, :id2=>nil, :x => 4).hash
1546
- a.hash.wont_equal y.load(:id => nil, :id2=>nil, :x => 3).hash
1547
-
1548
- a = z.load(:id => 1, :x => 3)
1549
- a.hash.must_equal z.load(:id => 1, :x => 3).hash
1550
- a.hash.wont_equal z.load(:id => 1, :id2=>nil, :x => 3).hash
1551
- a.hash.wont_equal z.load(:id => 1, :x => 4).hash
1552
- a.hash.wont_equal y.load(:id => 1, :x => 3).hash
1553
-
1554
- a = z.load(:x => 3)
1555
- a.hash.must_equal z.load(:x => 3).hash
1556
- a.hash.wont_equal z.load(:id => nil, :id2=>nil, :x => 3).hash
1557
- a.hash.wont_equal z.load(:x => 4).hash
1558
- a.hash.wont_equal y.load(:x => 3).hash
1559
- end
1560
-
1561
- it "should be the same only for objects with the same class and values if the no primary key" do
1562
- z = Class.new(Sequel::Model)
1563
- z.columns :id, :x
1564
- z.no_primary_key
1565
- y = Class.new(Sequel::Model)
1566
- y.columns :id, :x
1567
- y.no_primary_key
1568
- a = z.new(:x => 3)
1569
-
1570
- a.hash.wont_equal z.new(:x => 4).hash
1571
- a.hash.must_equal z.new(:x => 3).hash
1572
- a.hash.wont_equal y.new(:x => 3).hash
1573
- end
1574
-
1575
- end
1576
-
1577
- describe Sequel::Model, "#initialize" do
1578
- before do
1579
- @c = Class.new(Sequel::Model) do
1580
- columns :id, :x
1581
- end
1582
- @c.strict_param_setting = false
1583
- end
1584
-
1585
- it "should accept values" do
1586
- m = @c.new(:x => 2)
1587
- m.values.must_equal(:x => 2)
1588
- end
1589
-
1590
- it "should not modify the primary key" do
1591
- m = @c.new(:id => 1, :x => 2)
1592
- m.values.must_equal(:x => 2)
1593
- end
1594
-
1595
- it "should accept no values" do
1596
- m = @c.new
1597
- m.values.must_equal({})
1598
- end
1599
-
1600
- it "should accept a block to execute" do
1601
- m = @c.new {|o| o[:id] = 1234}
1602
- m.id.must_equal 1234
1603
- end
1604
-
1605
- it "should accept virtual attributes" do
1606
- @c.send(:define_method, :blah=){|x| @blah = x}
1607
- @c.send(:define_method, :blah){@blah}
1608
-
1609
- m = @c.new(:x => 2, :blah => 3)
1610
- m.values.must_equal(:x => 2)
1611
- m.blah.must_equal 3
1612
- end
1613
-
1614
- it "should convert string keys into symbol keys" do
1615
- m = @c.new('x' => 2)
1616
- m.values.must_equal(:x => 2)
1617
- end
1618
- end
1619
-
1620
- describe Sequel::Model, "#initialize_set" do
1621
- before do
1622
- @c = Class.new(Sequel::Model){columns :id, :x, :y}
1623
- end
1624
-
1625
- it "should be called by initialize to set the column values" do
1626
- @c.send(:define_method, :initialize_set){|h| set(:y => 3)}
1627
- @c.new(:x => 2).values.must_equal(:y => 3)
1628
- end
1629
-
1630
- it "should be called with the hash given to initialize " do
1631
- x = nil
1632
- @c.send(:define_method, :initialize_set){|y| x = y}
1633
- @c.new(:x => 2)
1634
- x.must_equal(:x => 2)
1635
- end
1636
-
1637
- it "should not cause columns modified by the method to be considered as changed" do
1638
- @c.send(:define_method, :initialize_set){|h| set(:y => 3)}
1639
- @c.new(:x => 2).changed_columns.must_equal []
1640
- end
1641
- end
1642
-
1643
- describe Sequel::Model, ".create" do
1644
- before do
1645
- DB.reset
1646
- @c = Class.new(Sequel::Model(:items)) do
1647
- unrestrict_primary_key
1648
- columns :x
1649
- end
1650
- end
1651
-
1652
- it "should be able to create rows in the associated table" do
1653
- o = @c.create(:x => 1)
1654
- o.class.must_equal @c
1655
- DB.sqls.must_equal ['INSERT INTO items (x) VALUES (1)', "SELECT * FROM items WHERE id = 10"]
1656
- end
1657
-
1658
- it "should be able to create rows without any values specified" do
1659
- o = @c.create
1660
- o.class.must_equal @c
1661
- DB.sqls.must_equal ["INSERT INTO items DEFAULT VALUES", "SELECT * FROM items WHERE id = 10"]
1662
- end
1663
-
1664
- it "should accept a block and call it" do
1665
- o1, o2, o3 = nil, nil, nil
1666
- o = @c.create {|o4| o1 = o4; o3 = o4; o2 = :blah; o3.x = 333}
1667
- o.class.must_equal @c
1668
- o1.must_be :===, o
1669
- o3.must_be :===, o
1670
- o2.must_equal :blah
1671
- DB.sqls.must_equal ["INSERT INTO items (x) VALUES (333)", "SELECT * FROM items WHERE id = 10"]
1672
- end
1673
-
1674
- it "should create a row for a model with custom primary key" do
1675
- @c.set_primary_key :x
1676
- o = @c.create(:x => 30)
1677
- o.class.must_equal @c
1678
- DB.sqls.must_equal ["INSERT INTO items (x) VALUES (30)", "SELECT * FROM items WHERE x = 30"]
1679
- end
1680
- end
1681
-
1682
- describe Sequel::Model, "#refresh" do
1683
- before do
1684
- @c = Class.new(Sequel::Model(:items)) do
1685
- unrestrict_primary_key
1686
- columns :id, :x
1687
- end
1688
- DB.reset
1689
- end
1690
-
1691
- it "should reload the instance values from the database" do
1692
- @m = @c.new(:id => 555)
1693
- @m[:x] = 'blah'
1694
- @c.dataset = @c.dataset.with_fetch(:x => 'kaboom', :id => 555)
1695
- @m.refresh
1696
- @m[:x].must_equal 'kaboom'
1697
- DB.sqls.must_equal ["SELECT * FROM items WHERE id = 555"]
1698
- end
1699
-
1700
- it "should raise if the instance is not found" do
1701
- @m = @c.new(:id => 555)
1702
- @c.dataset = @c.dataset.with_fetch([])
1703
- proc {@m.refresh}.must_raise(Sequel::NoExistingObject)
1704
- DB.sqls.must_equal ["SELECT * FROM items WHERE id = 555"]
1705
- end
1706
-
1707
- it "should be aliased by #reload" do
1708
- @m = @c.new(:id => 555)
1709
- @c.dataset = @c.dataset.with_fetch(:x => 'kaboom', :id => 555)
1710
- @m.reload
1711
- @m[:x].must_equal 'kaboom'
1712
- DB.sqls.must_equal ["SELECT * FROM items WHERE id = 555"]
1713
- end
1714
- end
1715
-
1716
- describe Sequel::Model, "typecasting" do
1717
- before do
1718
- @c = Class.new(Sequel::Model(:items)) do
1719
- columns :x
1720
- end
1721
- @c.db_schema = {:x=>{:type=>:integer}}
1722
- @c.raise_on_typecast_failure = true
1723
- DB.reset
1724
- end
1725
-
1726
- after do
1727
- Sequel.datetime_class = Time
1728
- end
1729
-
1730
- it "should not convert if typecasting is turned off" do
1731
- @c.typecast_on_assignment = false
1732
- m = @c.new
1733
- m.x = '1'
1734
- m.x.must_equal '1'
1735
- end
1736
-
1737
- it "should convert to integer for an integer field" do
1738
- @c.db_schema = {:x=>{:type=>:integer}}
1739
- m = @c.new
1740
- m.x = '1'
1741
- m.x.must_equal 1
1742
- m.x = 1
1743
- m.x.must_equal 1
1744
- m.x = 1.3
1745
- m.x.must_equal 1
1746
- end
1747
-
1748
- it "should typecast '' to nil unless type is string or blob" do
1749
- [:integer, :float, :decimal, :boolean, :date, :time, :datetime].each do |x|
1750
- @c.db_schema = {:x=>{:type=>x}}
1751
- m = @c.new
1752
- m.x = ''
1753
- m.x.must_be_nil
1754
- end
1755
- [:string, :blob].each do |x|
1756
- @c.db_schema = {:x=>{:type=>x}}
1757
- m = @c.new
1758
- m.x = ''
1759
- m.x.must_equal ''
1760
- end
1761
- end
1762
-
1763
- it "should not typecast '' to nil if typecast_empty_string_to_nil is false" do
1764
- m = @c.new
1765
- m.typecast_empty_string_to_nil = false
1766
- proc{m.x = ''}.must_raise Sequel::InvalidValue
1767
- @c.typecast_empty_string_to_nil = false
1768
- proc{@c.new.x = ''}.must_raise Sequel::InvalidValue
1769
- end
1770
-
1771
- it "should handle typecasting where == raises an error on the object" do
1772
- m = @c.new
1773
- o = Object.new
1774
- def o.==(v) raise ArgumentError end
1775
- def o.to_i() 4 end
1776
- m.x = o
1777
- m.x.must_equal 4
1778
- end
1779
-
1780
- it "should not typecast nil if NULLs are allowed" do
1781
- @c.db_schema[:x][:allow_null] = true
1782
- m = @c.new
1783
- m.x = nil
1784
- m.x.must_be_nil
1785
- end
1786
-
1787
- it "should raise an error if attempting to typecast nil and NULLs are not allowed" do
1788
- @c.db_schema[:x][:allow_null] = false
1789
- proc{@c.new.x = nil}.must_raise(Sequel::InvalidValue)
1790
- proc{@c.new.x = ''}.must_raise(Sequel::InvalidValue)
1791
- end
1792
-
1793
- it "should not raise an error if NULLs are not allowed and typecasting is turned off" do
1794
- @c.typecast_on_assignment = false
1795
- @c.db_schema[:x][:allow_null] = false
1796
- m = @c.new
1797
- m.x = nil
1798
- m.x.must_be_nil
1799
- end
1800
-
1801
- it "should not raise when typecasting nil to NOT NULL column but raise_on_typecast_failure is off" do
1802
- @c.raise_on_typecast_failure = false
1803
- @c.typecast_on_assignment = true
1804
- m = @c.new
1805
- m.x = ''
1806
- m.x.must_be_nil
1807
- m.x = nil
1808
- m.x.must_be_nil
1809
- end
1810
-
1811
- it "should raise an error if invalid data is used in an integer field" do
1812
- proc{@c.new.x = 'a'}.must_raise(Sequel::InvalidValue)
1813
- end
1814
-
1815
- it "should assign value if raise_on_typecast_failure is off and assigning invalid integer" do
1816
- @c.raise_on_typecast_failure = false
1817
- model = @c.new
1818
- model.x = '1d'
1819
- model.x.must_equal '1d'
1820
- end
1821
-
1822
- it "should convert to float for a float field" do
1823
- @c.db_schema = {:x=>{:type=>:float}}
1824
- m = @c.new
1825
- m.x = '1.3'
1826
- m.x.must_equal 1.3
1827
- m.x = 1
1828
- m.x.must_equal 1.0
1829
- m.x = 1.3
1830
- m.x.must_equal 1.3
1831
- end
1832
-
1833
- it "should raise an error if invalid data is used in an float field" do
1834
- @c.db_schema = {:x=>{:type=>:float}}
1835
- proc{@c.new.x = 'a'}.must_raise(Sequel::InvalidValue)
1836
- end
1837
-
1838
- it "should assign value if raise_on_typecast_failure is off and assigning invalid float" do
1839
- @c.raise_on_typecast_failure = false
1840
- @c.db_schema = {:x=>{:type=>:float}}
1841
- model = @c.new
1842
- model.x = '1d'
1843
- model.x.must_equal '1d'
1844
- end
1845
-
1846
- it "should convert to BigDecimal for a decimal field" do
1847
- @c.db_schema = {:x=>{:type=>:decimal}}
1848
- m = @c.new
1849
- bd = BigDecimal('1.0')
1850
- m.x = '1.0'
1851
- m.x.must_equal bd
1852
- m.x = 1.0
1853
- m.x.must_equal bd
1854
- m.x = 1
1855
- m.x.must_equal bd
1856
- m.x = bd
1857
- m.x.must_equal bd
1858
- m.x = '0'
1859
- m.x.must_equal 0
1860
- end
1861
-
1862
- it "should raise an error if invalid data is used in an decimal field" do
1863
- @c.db_schema = {:x=>{:type=>:decimal}}
1864
- proc{@c.new.x = Date.today}.must_raise(Sequel::InvalidValue)
1865
- proc{@c.new.x = 'foo'}.must_raise(Sequel::InvalidValue)
1866
- end
1867
-
1868
- it "should assign value if raise_on_typecast_failure is off and assigning invalid decimal" do
1869
- @c.raise_on_typecast_failure = false
1870
- @c.db_schema = {:x=>{:type=>:decimal}}
1871
- model = @c.new
1872
- time = Time.now
1873
- model.x = time
1874
- model.x.must_equal time
1875
- end
1876
-
1877
- it "should convert to string for a string field" do
1878
- @c.db_schema = {:x=>{:type=>:string}}
1879
- m = @c.new
1880
- m.x = '1.3'
1881
- m.x.must_equal '1.3'
1882
- m.x = 1
1883
- m.x.must_equal '1'
1884
- m.x = 1.3
1885
- m.x.must_equal '1.3'
1886
- end
1887
-
1888
- it "should convert to boolean for a boolean field" do
1889
- @c.db_schema = {:x=>{:type=>:boolean}}
1890
- m = @c.new
1891
- m.x = '1.3'
1892
- m.x.must_equal true
1893
- m.x = 1
1894
- m.x.must_equal true
1895
- m.x = 1.3
1896
- m.x.must_equal true
1897
- m.x = 't'
1898
- m.x.must_equal true
1899
- m.x = 'T'
1900
- m.x.must_equal true
1901
- m.x = 'y'
1902
- m.x.must_equal true
1903
- m.x = 'Y'
1904
- m.x.must_equal true
1905
- m.x = true
1906
- m.x.must_equal true
1907
- m.x = nil
1908
- m.x.must_be_nil
1909
- m.x = ''
1910
- m.x.must_be_nil
1911
- m.x = []
1912
- m.x.must_be_nil
1913
- m.x = 'f'
1914
- m.x.must_equal false
1915
- m.x = 'F'
1916
- m.x.must_equal false
1917
- m.x = 'false'
1918
- m.x.must_equal false
1919
- m.x = 'FALSE'
1920
- m.x.must_equal false
1921
- m.x = 'n'
1922
- m.x.must_equal false
1923
- m.x = 'N'
1924
- m.x.must_equal false
1925
- m.x = 'no'
1926
- m.x.must_equal false
1927
- m.x = 'NO'
1928
- m.x.must_equal false
1929
- m.x = '0'
1930
- m.x.must_equal false
1931
- m.x = 0
1932
- m.x.must_equal false
1933
- m.x = false
1934
- m.x.must_equal false
1935
- end
1936
-
1937
- it "should convert to date for a date field" do
1938
- @c.db_schema = {:x=>{:type=>:date}}
1939
- m = @c.new
1940
- y = Date.new(2007,10,21)
1941
- m.x = '2007-10-21'
1942
- m.x.must_equal y
1943
- m.x = Date.parse('2007-10-21')
1944
- m.x.must_equal y
1945
- m.x = Time.parse('2007-10-21')
1946
- m.x.must_equal y
1947
- m.x = DateTime.parse('2007-10-21')
1948
- m.x.must_equal y
1949
- end
1950
-
1951
- it "should accept a hash with symbol or string keys for a date field" do
1952
- @c.db_schema = {:x=>{:type=>:date}}
1953
- m = @c.new
1954
- y = Date.new(2007,10,21)
1955
- m.x = {:year=>2007, :month=>10, :day=>21}
1956
- m.x.must_equal y
1957
- m.x = {'year'=>'2007', 'month'=>'10', 'day'=>'21'}
1958
- m.x.must_equal y
1959
- end
1960
-
1961
- it "should raise an error if invalid data is used in a date field" do
1962
- @c.db_schema = {:x=>{:type=>:date}}
1963
- proc{@c.new.x = 'a'}.must_raise(Sequel::InvalidValue)
1964
- proc{@c.new.x = 100}.must_raise(Sequel::InvalidValue)
1965
- end
1966
-
1967
- it "should assign value if raise_on_typecast_failure is off and assigning invalid date" do
1968
- @c.raise_on_typecast_failure = false
1969
- @c.db_schema = {:x=>{:type=>:date}}
1970
- model = @c.new
1971
- model.x = 4
1972
- model.x.must_equal 4
1973
- end
1974
-
1975
- it "should convert to Sequel::SQLTime for a time field" do
1976
- @c.db_schema = {:x=>{:type=>:time}}
1977
- m = @c.new
1978
- x = '10:20:30'
1979
- y = Sequel::SQLTime.parse(x)
1980
- m.x = x
1981
- m.x.must_equal y
1982
- m.x = y
1983
- m.x.must_equal y
1984
- m.x.must_be_kind_of(Sequel::SQLTime)
1985
- end
1986
-
1987
- it "should accept a hash with symbol or string keys for a time field" do
1988
- @c.db_schema = {:x=>{:type=>:time}}
1989
- m = @c.new
1990
- y = Time.parse('10:20:30')
1991
- m.x = {:hour=>10, :minute=>20, :second=>30}
1992
- m.x.must_equal y
1993
- m.x = {'hour'=>'10', 'minute'=>'20', 'second'=>'30'}
1994
- m.x.must_equal y
1995
- end
1996
-
1997
- it "should raise an error if invalid data is used in a time field" do
1998
- @c.db_schema = {:x=>{:type=>:time}}
1999
- proc{@c.new.x = '0000'}.must_raise(Sequel::InvalidValue)
2000
- proc{@c.new.x = Date.parse('2008-10-21')}.must_raise(Sequel::InvalidValue)
2001
- proc{@c.new.x = DateTime.parse('2008-10-21')}.must_raise(Sequel::InvalidValue)
2002
- end
2003
-
2004
- it "should assign value if raise_on_typecast_failure is off and assigning invalid time" do
2005
- @c.raise_on_typecast_failure = false
2006
- @c.db_schema = {:x=>{:type=>:time}}
2007
- model = @c.new
2008
- model.x = '0000'
2009
- model.x.must_equal '0000'
2010
- end
2011
-
2012
- it "should convert to the Sequel.datetime_class for a datetime field" do
2013
- @c.db_schema = {:x=>{:type=>:datetime}}
2014
- m = @c.new
2015
- x = '2007-10-21T10:20:30-07:00'
2016
- y = Time.parse(x)
2017
- m.x = x
2018
- m.x.must_equal y
2019
- m.x = DateTime.parse(x)
2020
- m.x.must_equal y
2021
- m.x = Time.parse(x)
2022
- m.x.must_equal y
2023
- m.x = Date.parse('2007-10-21')
2024
- m.x.must_equal Time.parse('2007-10-21')
2025
- Sequel.datetime_class = DateTime
2026
- y = DateTime.parse(x)
2027
- m.x = x
2028
- m.x.must_equal y
2029
- m.x = DateTime.parse(x)
2030
- m.x.must_equal y
2031
- m.x = Time.parse(x)
2032
- m.x.must_equal y
2033
- m.x = Date.parse('2007-10-21')
2034
- m.x.must_equal DateTime.parse('2007-10-21')
2035
- end
2036
-
2037
- it "should accept a hash with symbol or string keys for a datetime field" do
2038
- @c.db_schema = {:x=>{:type=>:datetime}}
2039
- m = @c.new
2040
- y = Time.parse('2007-10-21 10:20:30')
2041
- m.x = {:year=>2007, :month=>10, :day=>21, :hour=>10, :minute=>20, :second=>30}
2042
- m.x.must_equal y
2043
- m.x = {'year'=>'2007', 'month'=>'10', 'day'=>'21', 'hour'=>'10', 'minute'=>'20', 'second'=>'30'}
2044
- m.x.must_equal y
2045
- Sequel.datetime_class = DateTime
2046
- y = DateTime.parse('2007-10-21 10:20:30')
2047
- m.x = {:year=>2007, :month=>10, :day=>21, :hour=>10, :minute=>20, :second=>30}
2048
- m.x.must_equal y
2049
- m.x = {'year'=>'2007', 'month'=>'10', 'day'=>'21', 'hour'=>'10', 'minute'=>'20', 'second'=>'30'}
2050
- m.x.must_equal y
2051
- end
2052
-
2053
- it "should raise an error if invalid data is used in a datetime field" do
2054
- @c.db_schema = {:x=>{:type=>:datetime}}
2055
- proc{@c.new.x = '0000'}.must_raise(Sequel::InvalidValue)
2056
- Sequel.datetime_class = DateTime
2057
- proc{@c.new.x = '0000'}.must_raise(Sequel::InvalidValue)
2058
- proc{@c.new.x = 'a'}.must_raise(Sequel::InvalidValue)
2059
- end
2060
-
2061
- it "should assign value if raise_on_typecast_failure is off and assigning invalid datetime" do
2062
- @c.raise_on_typecast_failure = false
2063
- @c.db_schema = {:x=>{:type=>:datetime}}
2064
- model = @c.new
2065
- model.x = '0000'
2066
- model.x.must_equal '0000'
2067
- Sequel.datetime_class = DateTime
2068
- model = @c.new
2069
- model.x = '0000'
2070
- model.x.must_equal '0000'
2071
- model.x = 'a'
2072
- model.x.must_equal 'a'
2073
- end
2074
- end
2075
-
2076
- describe "Model#lock!" do
2077
- before do
2078
- @c = Class.new(Sequel::Model(:items)) do
2079
- columns :id
2080
- end
2081
- @c.dataset = @c.dataset.with_fetch(:id=>1)
2082
- DB.reset
2083
- end
2084
-
2085
- it "should do nothing if the record is a new record" do
2086
- o = @c.new
2087
- def o._refresh(x) raise Sequel::Error; super(x) end
2088
- x = o.lock!
2089
- x.must_equal o
2090
- DB.sqls.must_equal []
2091
- end
2092
-
2093
- it "should refresh the record using for_update if it is not a new record" do
2094
- o = @c.load(:id => 1)
2095
- def o._refresh(x) instance_variable_set(:@a, 1); super(x) end
2096
- x = o.lock!
2097
- x.must_equal o
2098
- o.instance_variable_get(:@a).must_equal 1
2099
- DB.sqls.must_equal ["SELECT * FROM items WHERE (id = 1) LIMIT 1 FOR UPDATE"]
2100
- end
2101
-
2102
- it "should refresh the record using the specified lock when it is not a new record and a style is given" do
2103
- o = @c.load(:id => 1)
2104
- def o._refresh(x) instance_variable_set(:@a, 1); super(x) end
2105
- x = o.lock!('FOR NO KEY UPDATE')
2106
- x.must_equal o
2107
- o.instance_variable_get(:@a).must_equal 1
2108
- DB.sqls.must_equal ["SELECT * FROM items WHERE (id = 1) LIMIT 1 FOR NO KEY UPDATE"]
2109
- end
2110
- end
2111
-
2112
- describe "Model#schema_type_class" do
2113
- it "should return the class or array of classes for the given type symbol" do
2114
- @c = Class.new(Sequel::Model(:items))
2115
- @c.class_eval{@db_schema = {:id=>{:type=>:integer}}}
2116
- @c.new.send(:schema_type_class, :id).must_equal Integer
2117
- end
2118
- end