sequel 5.8.0 → 5.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (510) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +409 -1795
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -4
  5. data/bin/sequel +4 -0
  6. data/doc/advanced_associations.rdoc +136 -18
  7. data/doc/association_basics.rdoc +10 -5
  8. data/doc/cheat_sheet.rdoc +1 -0
  9. data/doc/code_order.rdoc +12 -2
  10. data/doc/dataset_filtering.rdoc +17 -2
  11. data/doc/mass_assignment.rdoc +3 -3
  12. data/doc/model_dataset_method_design.rdoc +1 -1
  13. data/doc/model_plugins.rdoc +1 -1
  14. data/doc/opening_databases.rdoc +30 -8
  15. data/doc/postgresql.rdoc +107 -2
  16. data/doc/release_notes/5.10.0.txt +84 -0
  17. data/doc/release_notes/5.11.0.txt +83 -0
  18. data/doc/release_notes/5.12.0.txt +141 -0
  19. data/doc/release_notes/5.13.0.txt +27 -0
  20. data/doc/release_notes/5.14.0.txt +63 -0
  21. data/doc/release_notes/5.15.0.txt +39 -0
  22. data/doc/release_notes/5.16.0.txt +110 -0
  23. data/doc/release_notes/5.17.0.txt +31 -0
  24. data/doc/release_notes/5.18.0.txt +69 -0
  25. data/doc/release_notes/5.19.0.txt +28 -0
  26. data/doc/release_notes/5.20.0.txt +89 -0
  27. data/doc/release_notes/5.21.0.txt +87 -0
  28. data/doc/release_notes/5.22.0.txt +48 -0
  29. data/doc/release_notes/5.23.0.txt +56 -0
  30. data/doc/release_notes/5.24.0.txt +56 -0
  31. data/doc/release_notes/5.25.0.txt +32 -0
  32. data/doc/release_notes/5.26.0.txt +35 -0
  33. data/doc/release_notes/5.27.0.txt +21 -0
  34. data/doc/release_notes/5.28.0.txt +16 -0
  35. data/doc/release_notes/5.29.0.txt +22 -0
  36. data/doc/release_notes/5.30.0.txt +20 -0
  37. data/doc/release_notes/5.31.0.txt +148 -0
  38. data/doc/release_notes/5.32.0.txt +46 -0
  39. data/doc/release_notes/5.33.0.txt +24 -0
  40. data/doc/release_notes/5.34.0.txt +40 -0
  41. data/doc/release_notes/5.35.0.txt +56 -0
  42. data/doc/release_notes/5.36.0.txt +60 -0
  43. data/doc/release_notes/5.37.0.txt +30 -0
  44. data/doc/release_notes/5.38.0.txt +28 -0
  45. data/doc/release_notes/5.9.0.txt +99 -0
  46. data/doc/security.rdoc +10 -0
  47. data/doc/sharding.rdoc +42 -28
  48. data/doc/sql.rdoc +12 -0
  49. data/doc/testing.rdoc +24 -17
  50. data/doc/transactions.rdoc +78 -0
  51. data/doc/validations.rdoc +2 -2
  52. data/lib/sequel/adapters/ado.rb +26 -18
  53. data/lib/sequel/adapters/ado/access.rb +2 -2
  54. data/lib/sequel/adapters/ado/mssql.rb +5 -8
  55. data/lib/sequel/adapters/amalgalite.rb +1 -1
  56. data/lib/sequel/adapters/jdbc.rb +71 -27
  57. data/lib/sequel/adapters/jdbc/mysql.rb +6 -6
  58. data/lib/sequel/adapters/jdbc/oracle.rb +7 -6
  59. data/lib/sequel/adapters/jdbc/postgresql.rb +17 -28
  60. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +5 -6
  61. data/lib/sequel/adapters/jdbc/sqlite.rb +33 -2
  62. data/lib/sequel/adapters/jdbc/sqlserver.rb +4 -3
  63. data/lib/sequel/adapters/jdbc/transactions.rb +14 -28
  64. data/lib/sequel/adapters/mysql.rb +14 -15
  65. data/lib/sequel/adapters/mysql2.rb +5 -3
  66. data/lib/sequel/adapters/odbc.rb +4 -6
  67. data/lib/sequel/adapters/oracle.rb +7 -7
  68. data/lib/sequel/adapters/postgres.rb +52 -16
  69. data/lib/sequel/adapters/shared/access.rb +16 -12
  70. data/lib/sequel/adapters/shared/db2.rb +5 -0
  71. data/lib/sequel/adapters/shared/mssql.rb +41 -18
  72. data/lib/sequel/adapters/shared/mysql.rb +66 -19
  73. data/lib/sequel/adapters/shared/oracle.rb +29 -23
  74. data/lib/sequel/adapters/shared/postgres.rb +341 -95
  75. data/lib/sequel/adapters/shared/sqlanywhere.rb +23 -10
  76. data/lib/sequel/adapters/shared/sqlite.rb +174 -21
  77. data/lib/sequel/adapters/sqlanywhere.rb +33 -17
  78. data/lib/sequel/adapters/sqlite.rb +78 -68
  79. data/lib/sequel/adapters/tinytds.rb +14 -6
  80. data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +2 -5
  81. data/lib/sequel/adapters/utils/mysql_mysql2.rb +5 -1
  82. data/lib/sequel/connection_pool.rb +2 -6
  83. data/lib/sequel/connection_pool/sharded_single.rb +7 -4
  84. data/lib/sequel/connection_pool/sharded_threaded.rb +32 -21
  85. data/lib/sequel/connection_pool/single.rb +1 -1
  86. data/lib/sequel/connection_pool/threaded.rb +26 -11
  87. data/lib/sequel/core.rb +327 -319
  88. data/lib/sequel/database/connecting.rb +7 -8
  89. data/lib/sequel/database/logging.rb +7 -1
  90. data/lib/sequel/database/misc.rb +68 -34
  91. data/lib/sequel/database/query.rb +6 -4
  92. data/lib/sequel/database/schema_generator.rb +31 -11
  93. data/lib/sequel/database/schema_methods.rb +32 -22
  94. data/lib/sequel/database/transactions.rb +129 -25
  95. data/lib/sequel/dataset.rb +4 -2
  96. data/lib/sequel/dataset/actions.rb +34 -23
  97. data/lib/sequel/dataset/features.rb +34 -0
  98. data/lib/sequel/dataset/graph.rb +27 -11
  99. data/lib/sequel/dataset/misc.rb +17 -3
  100. data/lib/sequel/dataset/placeholder_literalizer.rb +50 -21
  101. data/lib/sequel/dataset/prepared_statements.rb +96 -26
  102. data/lib/sequel/dataset/query.rb +43 -8
  103. data/lib/sequel/dataset/sql.rb +189 -41
  104. data/lib/sequel/deprecated.rb +3 -1
  105. data/lib/sequel/exceptions.rb +2 -0
  106. data/lib/sequel/extensions/_pretty_table.rb +1 -2
  107. data/lib/sequel/extensions/any_not_empty.rb +45 -0
  108. data/lib/sequel/extensions/caller_logging.rb +79 -0
  109. data/lib/sequel/extensions/columns_introspection.rb +1 -2
  110. data/lib/sequel/extensions/connection_expiration.rb +6 -6
  111. data/lib/sequel/extensions/connection_validator.rb +7 -6
  112. data/lib/sequel/extensions/constant_sql_override.rb +65 -0
  113. data/lib/sequel/extensions/constraint_validations.rb +53 -28
  114. data/lib/sequel/extensions/core_refinements.rb +2 -0
  115. data/lib/sequel/extensions/duplicate_columns_handler.rb +2 -0
  116. data/lib/sequel/extensions/escaped_like.rb +100 -0
  117. data/lib/sequel/extensions/eval_inspect.rb +3 -1
  118. data/lib/sequel/extensions/exclude_or_null.rb +68 -0
  119. data/lib/sequel/extensions/fiber_concurrency.rb +24 -0
  120. data/lib/sequel/extensions/index_caching.rb +9 -7
  121. data/lib/sequel/extensions/integer64.rb +3 -1
  122. data/lib/sequel/extensions/looser_typecasting.rb +3 -3
  123. data/lib/sequel/extensions/migration.rb +13 -6
  124. data/lib/sequel/extensions/named_timezones.rb +84 -23
  125. data/lib/sequel/extensions/pg_array.rb +87 -79
  126. data/lib/sequel/extensions/pg_array_ops.rb +14 -6
  127. data/lib/sequel/extensions/pg_enum.rb +34 -18
  128. data/lib/sequel/extensions/pg_extended_date_support.rb +34 -14
  129. data/lib/sequel/extensions/pg_hstore.rb +6 -0
  130. data/lib/sequel/extensions/pg_hstore_ops.rb +2 -0
  131. data/lib/sequel/extensions/pg_inet.rb +15 -5
  132. data/lib/sequel/extensions/pg_interval.rb +2 -0
  133. data/lib/sequel/extensions/pg_json.rb +387 -123
  134. data/lib/sequel/extensions/pg_json_ops.rb +168 -0
  135. data/lib/sequel/extensions/pg_range.rb +20 -10
  136. data/lib/sequel/extensions/pg_range_ops.rb +2 -0
  137. data/lib/sequel/extensions/pg_row.rb +3 -2
  138. data/lib/sequel/extensions/pg_row_ops.rb +24 -0
  139. data/lib/sequel/extensions/pg_static_cache_updater.rb +2 -2
  140. data/lib/sequel/extensions/pg_timestamptz.rb +2 -0
  141. data/lib/sequel/extensions/query.rb +1 -0
  142. data/lib/sequel/extensions/run_transaction_hooks.rb +72 -0
  143. data/lib/sequel/extensions/s.rb +2 -0
  144. data/lib/sequel/extensions/schema_dumper.rb +13 -7
  145. data/lib/sequel/extensions/sequel_4_dataset_methods.rb +4 -2
  146. data/lib/sequel/extensions/server_block.rb +18 -7
  147. data/lib/sequel/extensions/sql_comments.rb +2 -2
  148. data/lib/sequel/extensions/symbol_aref_refinement.rb +2 -0
  149. data/lib/sequel/extensions/symbol_as_refinement.rb +2 -0
  150. data/lib/sequel/extensions/to_dot.rb +9 -3
  151. data/lib/sequel/model.rb +3 -1
  152. data/lib/sequel/model/associations.rb +403 -69
  153. data/lib/sequel/model/base.rb +170 -90
  154. data/lib/sequel/model/plugins.rb +105 -0
  155. data/lib/sequel/plugins/after_initialize.rb +1 -1
  156. data/lib/sequel/plugins/association_dependencies.rb +3 -3
  157. data/lib/sequel/plugins/association_lazy_eager_option.rb +66 -0
  158. data/lib/sequel/plugins/association_multi_add_remove.rb +85 -0
  159. data/lib/sequel/plugins/association_pks.rb +74 -22
  160. data/lib/sequel/plugins/association_proxies.rb +6 -2
  161. data/lib/sequel/plugins/auto_validations.rb +36 -17
  162. data/lib/sequel/plugins/blacklist_security.rb +1 -2
  163. data/lib/sequel/plugins/boolean_subsets.rb +4 -1
  164. data/lib/sequel/plugins/caching.rb +3 -0
  165. data/lib/sequel/plugins/class_table_inheritance.rb +62 -34
  166. data/lib/sequel/plugins/composition.rb +13 -9
  167. data/lib/sequel/plugins/csv_serializer.rb +28 -9
  168. data/lib/sequel/plugins/defaults_setter.rb +2 -2
  169. data/lib/sequel/plugins/dirty.rb +60 -22
  170. data/lib/sequel/plugins/eager_graph_eager.rb +139 -0
  171. data/lib/sequel/plugins/empty_failure_backtraces.rb +38 -0
  172. data/lib/sequel/plugins/finder.rb +2 -2
  173. data/lib/sequel/plugins/forbid_lazy_load.rb +216 -0
  174. data/lib/sequel/plugins/hook_class_methods.rb +17 -5
  175. data/lib/sequel/plugins/insert_conflict.rb +72 -0
  176. data/lib/sequel/plugins/instance_specific_default.rb +113 -0
  177. data/lib/sequel/plugins/inverted_subsets.rb +2 -2
  178. data/lib/sequel/plugins/json_serializer.rb +21 -14
  179. data/lib/sequel/plugins/lazy_attributes.rb +1 -1
  180. data/lib/sequel/plugins/list.rb +22 -10
  181. data/lib/sequel/plugins/many_through_many.rb +1 -1
  182. data/lib/sequel/plugins/nested_attributes.rb +27 -5
  183. data/lib/sequel/plugins/pg_array_associations.rb +12 -9
  184. data/lib/sequel/plugins/pg_auto_constraint_validations.rb +149 -61
  185. data/lib/sequel/plugins/prepared_statements.rb +6 -12
  186. data/lib/sequel/plugins/prepared_statements_safe.rb +1 -3
  187. data/lib/sequel/plugins/rcte_tree.rb +20 -22
  188. data/lib/sequel/plugins/sharding.rb +13 -7
  189. data/lib/sequel/plugins/single_table_inheritance.rb +20 -15
  190. data/lib/sequel/plugins/skip_saving_columns.rb +108 -0
  191. data/lib/sequel/plugins/static_cache.rb +36 -17
  192. data/lib/sequel/plugins/static_cache_cache.rb +53 -0
  193. data/lib/sequel/plugins/string_stripper.rb +1 -1
  194. data/lib/sequel/plugins/subclasses.rb +2 -0
  195. data/lib/sequel/plugins/subset_conditions.rb +2 -2
  196. data/lib/sequel/plugins/tactical_eager_loading.rb +73 -2
  197. data/lib/sequel/plugins/throw_failures.rb +110 -0
  198. data/lib/sequel/plugins/tree.rb +49 -31
  199. data/lib/sequel/plugins/typecast_on_load.rb +3 -2
  200. data/lib/sequel/plugins/validation_class_methods.rb +11 -5
  201. data/lib/sequel/plugins/validation_helpers.rb +2 -2
  202. data/lib/sequel/sql.rb +120 -30
  203. data/lib/sequel/timezones.rb +55 -14
  204. data/lib/sequel/version.rb +6 -1
  205. metadata +101 -361
  206. data/Rakefile +0 -151
  207. data/doc/release_notes/4.0.0.txt +0 -262
  208. data/doc/release_notes/4.1.0.txt +0 -85
  209. data/doc/release_notes/4.10.0.txt +0 -226
  210. data/doc/release_notes/4.11.0.txt +0 -147
  211. data/doc/release_notes/4.12.0.txt +0 -105
  212. data/doc/release_notes/4.13.0.txt +0 -169
  213. data/doc/release_notes/4.14.0.txt +0 -68
  214. data/doc/release_notes/4.15.0.txt +0 -56
  215. data/doc/release_notes/4.16.0.txt +0 -36
  216. data/doc/release_notes/4.17.0.txt +0 -38
  217. data/doc/release_notes/4.18.0.txt +0 -36
  218. data/doc/release_notes/4.19.0.txt +0 -45
  219. data/doc/release_notes/4.2.0.txt +0 -129
  220. data/doc/release_notes/4.20.0.txt +0 -79
  221. data/doc/release_notes/4.21.0.txt +0 -94
  222. data/doc/release_notes/4.22.0.txt +0 -72
  223. data/doc/release_notes/4.23.0.txt +0 -65
  224. data/doc/release_notes/4.24.0.txt +0 -99
  225. data/doc/release_notes/4.25.0.txt +0 -181
  226. data/doc/release_notes/4.26.0.txt +0 -44
  227. data/doc/release_notes/4.27.0.txt +0 -78
  228. data/doc/release_notes/4.28.0.txt +0 -57
  229. data/doc/release_notes/4.29.0.txt +0 -41
  230. data/doc/release_notes/4.3.0.txt +0 -40
  231. data/doc/release_notes/4.30.0.txt +0 -37
  232. data/doc/release_notes/4.31.0.txt +0 -57
  233. data/doc/release_notes/4.32.0.txt +0 -132
  234. data/doc/release_notes/4.33.0.txt +0 -88
  235. data/doc/release_notes/4.34.0.txt +0 -86
  236. data/doc/release_notes/4.35.0.txt +0 -130
  237. data/doc/release_notes/4.36.0.txt +0 -116
  238. data/doc/release_notes/4.37.0.txt +0 -50
  239. data/doc/release_notes/4.38.0.txt +0 -67
  240. data/doc/release_notes/4.39.0.txt +0 -127
  241. data/doc/release_notes/4.4.0.txt +0 -92
  242. data/doc/release_notes/4.40.0.txt +0 -179
  243. data/doc/release_notes/4.41.0.txt +0 -77
  244. data/doc/release_notes/4.42.0.txt +0 -221
  245. data/doc/release_notes/4.43.0.txt +0 -87
  246. data/doc/release_notes/4.44.0.txt +0 -125
  247. data/doc/release_notes/4.45.0.txt +0 -370
  248. data/doc/release_notes/4.46.0.txt +0 -404
  249. data/doc/release_notes/4.47.0.txt +0 -56
  250. data/doc/release_notes/4.48.0.txt +0 -293
  251. data/doc/release_notes/4.49.0.txt +0 -222
  252. data/doc/release_notes/4.5.0.txt +0 -34
  253. data/doc/release_notes/4.6.0.txt +0 -30
  254. data/doc/release_notes/4.7.0.txt +0 -103
  255. data/doc/release_notes/4.8.0.txt +0 -175
  256. data/doc/release_notes/4.9.0.txt +0 -190
  257. data/spec/adapter_spec.rb +0 -4
  258. data/spec/adapters/db2_spec.rb +0 -170
  259. data/spec/adapters/mssql_spec.rb +0 -804
  260. data/spec/adapters/mysql_spec.rb +0 -1041
  261. data/spec/adapters/oracle_spec.rb +0 -327
  262. data/spec/adapters/postgres_spec.rb +0 -4000
  263. data/spec/adapters/spec_helper.rb +0 -43
  264. data/spec/adapters/sqlanywhere_spec.rb +0 -97
  265. data/spec/adapters/sqlite_spec.rb +0 -600
  266. data/spec/bin_spec.rb +0 -269
  267. data/spec/core/connection_pool_spec.rb +0 -1228
  268. data/spec/core/database_spec.rb +0 -2673
  269. data/spec/core/dataset_spec.rb +0 -5419
  270. data/spec/core/deprecated_spec.rb +0 -70
  271. data/spec/core/expression_filters_spec.rb +0 -1344
  272. data/spec/core/mock_adapter_spec.rb +0 -722
  273. data/spec/core/object_graph_spec.rb +0 -306
  274. data/spec/core/placeholder_literalizer_spec.rb +0 -166
  275. data/spec/core/schema_generator_spec.rb +0 -214
  276. data/spec/core/schema_spec.rb +0 -1820
  277. data/spec/core/spec_helper.rb +0 -23
  278. data/spec/core/version_spec.rb +0 -7
  279. data/spec/core_extensions_spec.rb +0 -762
  280. data/spec/core_model_spec.rb +0 -2
  281. data/spec/core_spec.rb +0 -1
  282. data/spec/deprecation_helper.rb +0 -30
  283. data/spec/extensions/accessed_columns_spec.rb +0 -51
  284. data/spec/extensions/active_model_spec.rb +0 -99
  285. data/spec/extensions/after_initialize_spec.rb +0 -24
  286. data/spec/extensions/arbitrary_servers_spec.rb +0 -109
  287. data/spec/extensions/association_dependencies_spec.rb +0 -125
  288. data/spec/extensions/association_pks_spec.rb +0 -423
  289. data/spec/extensions/association_proxies_spec.rb +0 -100
  290. data/spec/extensions/auto_literal_strings_spec.rb +0 -205
  291. data/spec/extensions/auto_validations_spec.rb +0 -202
  292. data/spec/extensions/blacklist_security_spec.rb +0 -95
  293. data/spec/extensions/blank_spec.rb +0 -69
  294. data/spec/extensions/boolean_readers_spec.rb +0 -93
  295. data/spec/extensions/boolean_subsets_spec.rb +0 -47
  296. data/spec/extensions/caching_spec.rb +0 -273
  297. data/spec/extensions/class_table_inheritance_spec.rb +0 -568
  298. data/spec/extensions/column_conflicts_spec.rb +0 -75
  299. data/spec/extensions/column_select_spec.rb +0 -129
  300. data/spec/extensions/columns_introspection_spec.rb +0 -90
  301. data/spec/extensions/columns_updated_spec.rb +0 -35
  302. data/spec/extensions/composition_spec.rb +0 -248
  303. data/spec/extensions/connection_expiration_spec.rb +0 -133
  304. data/spec/extensions/connection_validator_spec.rb +0 -127
  305. data/spec/extensions/constraint_validations_plugin_spec.rb +0 -300
  306. data/spec/extensions/constraint_validations_spec.rb +0 -395
  307. data/spec/extensions/core_refinements_spec.rb +0 -528
  308. data/spec/extensions/csv_serializer_spec.rb +0 -183
  309. data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
  310. data/spec/extensions/dataset_associations_spec.rb +0 -365
  311. data/spec/extensions/dataset_source_alias_spec.rb +0 -51
  312. data/spec/extensions/date_arithmetic_spec.rb +0 -181
  313. data/spec/extensions/datetime_parse_to_time_spec.rb +0 -169
  314. data/spec/extensions/def_dataset_method_spec.rb +0 -100
  315. data/spec/extensions/defaults_setter_spec.rb +0 -141
  316. data/spec/extensions/delay_add_association_spec.rb +0 -73
  317. data/spec/extensions/dirty_spec.rb +0 -189
  318. data/spec/extensions/duplicate_columns_handler_spec.rb +0 -104
  319. data/spec/extensions/eager_each_spec.rb +0 -62
  320. data/spec/extensions/empty_array_consider_nulls_spec.rb +0 -24
  321. data/spec/extensions/error_splitter_spec.rb +0 -18
  322. data/spec/extensions/error_sql_spec.rb +0 -20
  323. data/spec/extensions/eval_inspect_spec.rb +0 -74
  324. data/spec/extensions/finder_spec.rb +0 -260
  325. data/spec/extensions/force_encoding_spec.rb +0 -126
  326. data/spec/extensions/freeze_datasets_spec.rb +0 -31
  327. data/spec/extensions/graph_each_spec.rb +0 -113
  328. data/spec/extensions/hook_class_methods_spec.rb +0 -380
  329. data/spec/extensions/identifier_mangling_spec.rb +0 -201
  330. data/spec/extensions/implicit_subquery_spec.rb +0 -58
  331. data/spec/extensions/index_caching_spec.rb +0 -66
  332. data/spec/extensions/inflector_spec.rb +0 -183
  333. data/spec/extensions/input_transformer_spec.rb +0 -69
  334. data/spec/extensions/insert_returning_select_spec.rb +0 -72
  335. data/spec/extensions/instance_filters_spec.rb +0 -79
  336. data/spec/extensions/instance_hooks_spec.rb +0 -246
  337. data/spec/extensions/integer64_spec.rb +0 -22
  338. data/spec/extensions/inverted_subsets_spec.rb +0 -33
  339. data/spec/extensions/json_serializer_spec.rb +0 -336
  340. data/spec/extensions/lazy_attributes_spec.rb +0 -183
  341. data/spec/extensions/list_spec.rb +0 -275
  342. data/spec/extensions/looser_typecasting_spec.rb +0 -43
  343. data/spec/extensions/many_through_many_spec.rb +0 -2177
  344. data/spec/extensions/migration_spec.rb +0 -840
  345. data/spec/extensions/modification_detection_spec.rb +0 -93
  346. data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -92
  347. data/spec/extensions/named_timezones_spec.rb +0 -109
  348. data/spec/extensions/nested_attributes_spec.rb +0 -703
  349. data/spec/extensions/null_dataset_spec.rb +0 -85
  350. data/spec/extensions/optimistic_locking_spec.rb +0 -127
  351. data/spec/extensions/pagination_spec.rb +0 -116
  352. data/spec/extensions/pg_array_associations_spec.rb +0 -802
  353. data/spec/extensions/pg_array_ops_spec.rb +0 -144
  354. data/spec/extensions/pg_array_spec.rb +0 -398
  355. data/spec/extensions/pg_auto_constraint_validations_spec.rb +0 -165
  356. data/spec/extensions/pg_enum_spec.rb +0 -113
  357. data/spec/extensions/pg_extended_date_support_spec.rb +0 -126
  358. data/spec/extensions/pg_hstore_ops_spec.rb +0 -238
  359. data/spec/extensions/pg_hstore_spec.rb +0 -219
  360. data/spec/extensions/pg_inet_ops_spec.rb +0 -102
  361. data/spec/extensions/pg_inet_spec.rb +0 -72
  362. data/spec/extensions/pg_interval_spec.rb +0 -103
  363. data/spec/extensions/pg_json_ops_spec.rb +0 -289
  364. data/spec/extensions/pg_json_spec.rb +0 -262
  365. data/spec/extensions/pg_loose_count_spec.rb +0 -23
  366. data/spec/extensions/pg_range_ops_spec.rb +0 -60
  367. data/spec/extensions/pg_range_spec.rb +0 -487
  368. data/spec/extensions/pg_row_ops_spec.rb +0 -61
  369. data/spec/extensions/pg_row_plugin_spec.rb +0 -60
  370. data/spec/extensions/pg_row_spec.rb +0 -363
  371. data/spec/extensions/pg_static_cache_updater_spec.rb +0 -93
  372. data/spec/extensions/pg_timestamptz_spec.rb +0 -17
  373. data/spec/extensions/prepared_statements_safe_spec.rb +0 -66
  374. data/spec/extensions/prepared_statements_spec.rb +0 -182
  375. data/spec/extensions/pretty_table_spec.rb +0 -123
  376. data/spec/extensions/query_spec.rb +0 -94
  377. data/spec/extensions/rcte_tree_spec.rb +0 -381
  378. data/spec/extensions/round_timestamps_spec.rb +0 -39
  379. data/spec/extensions/s_spec.rb +0 -60
  380. data/spec/extensions/schema_caching_spec.rb +0 -64
  381. data/spec/extensions/schema_dumper_spec.rb +0 -868
  382. data/spec/extensions/select_remove_spec.rb +0 -38
  383. data/spec/extensions/sequel_4_dataset_methods_spec.rb +0 -121
  384. data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
  385. data/spec/extensions/serialization_spec.rb +0 -365
  386. data/spec/extensions/server_block_spec.rb +0 -97
  387. data/spec/extensions/server_logging_spec.rb +0 -45
  388. data/spec/extensions/sharding_spec.rb +0 -189
  389. data/spec/extensions/shared_caching_spec.rb +0 -151
  390. data/spec/extensions/single_table_inheritance_spec.rb +0 -347
  391. data/spec/extensions/singular_table_names_spec.rb +0 -22
  392. data/spec/extensions/skip_create_refresh_spec.rb +0 -18
  393. data/spec/extensions/spec_helper.rb +0 -61
  394. data/spec/extensions/split_array_nil_spec.rb +0 -24
  395. data/spec/extensions/split_values_spec.rb +0 -57
  396. data/spec/extensions/sql_comments_spec.rb +0 -33
  397. data/spec/extensions/sql_expr_spec.rb +0 -59
  398. data/spec/extensions/static_cache_spec.rb +0 -410
  399. data/spec/extensions/string_agg_spec.rb +0 -90
  400. data/spec/extensions/string_date_time_spec.rb +0 -95
  401. data/spec/extensions/string_stripper_spec.rb +0 -68
  402. data/spec/extensions/subclasses_spec.rb +0 -79
  403. data/spec/extensions/subset_conditions_spec.rb +0 -38
  404. data/spec/extensions/symbol_aref_refinement_spec.rb +0 -28
  405. data/spec/extensions/symbol_as_refinement_spec.rb +0 -21
  406. data/spec/extensions/synchronize_sql_spec.rb +0 -124
  407. data/spec/extensions/table_select_spec.rb +0 -83
  408. data/spec/extensions/tactical_eager_loading_spec.rb +0 -141
  409. data/spec/extensions/thread_local_timezones_spec.rb +0 -67
  410. data/spec/extensions/timestamps_spec.rb +0 -209
  411. data/spec/extensions/to_dot_spec.rb +0 -153
  412. data/spec/extensions/touch_spec.rb +0 -226
  413. data/spec/extensions/tree_spec.rb +0 -284
  414. data/spec/extensions/typecast_on_load_spec.rb +0 -86
  415. data/spec/extensions/unlimited_update_spec.rb +0 -21
  416. data/spec/extensions/update_or_create_spec.rb +0 -83
  417. data/spec/extensions/update_primary_key_spec.rb +0 -105
  418. data/spec/extensions/update_refresh_spec.rb +0 -59
  419. data/spec/extensions/uuid_spec.rb +0 -101
  420. data/spec/extensions/validate_associated_spec.rb +0 -52
  421. data/spec/extensions/validation_class_methods_spec.rb +0 -1040
  422. data/spec/extensions/validation_contexts_spec.rb +0 -31
  423. data/spec/extensions/validation_helpers_spec.rb +0 -525
  424. data/spec/extensions/whitelist_security_spec.rb +0 -157
  425. data/spec/extensions/xml_serializer_spec.rb +0 -213
  426. data/spec/files/bad_down_migration/001_create_alt_basic.rb +0 -4
  427. data/spec/files/bad_down_migration/002_create_alt_advanced.rb +0 -4
  428. data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  429. data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  430. data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +0 -3
  431. data/spec/files/bad_up_migration/001_create_alt_basic.rb +0 -4
  432. data/spec/files/bad_up_migration/002_create_alt_advanced.rb +0 -3
  433. data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +0 -9
  434. data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +0 -9
  435. data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +0 -4
  436. data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +0 -9
  437. data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +0 -9
  438. data/spec/files/double_migration/001_create_sessions.rb +0 -9
  439. data/spec/files/double_migration/002_create_nodes.rb +0 -19
  440. data/spec/files/double_migration/003_3_create_users.rb +0 -4
  441. data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +0 -4
  442. data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +0 -4
  443. data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  444. data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +0 -9
  445. data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +0 -4
  446. data/spec/files/empty_migration/001_create_sessions.rb +0 -9
  447. data/spec/files/empty_migration/002_create_nodes.rb +0 -0
  448. data/spec/files/empty_migration/003_3_create_users.rb +0 -4
  449. data/spec/files/integer_migrations/001_create_sessions.rb +0 -9
  450. data/spec/files/integer_migrations/002_create_nodes.rb +0 -9
  451. data/spec/files/integer_migrations/003_3_create_users.rb +0 -4
  452. data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  453. data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +0 -9
  454. data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  455. data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +0 -9
  456. data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  457. data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +0 -4
  458. data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +0 -4
  459. data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  460. data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  461. data/spec/files/reversible_migrations/001_reversible.rb +0 -5
  462. data/spec/files/reversible_migrations/002_reversible.rb +0 -5
  463. data/spec/files/reversible_migrations/003_reversible.rb +0 -5
  464. data/spec/files/reversible_migrations/004_reversible.rb +0 -5
  465. data/spec/files/reversible_migrations/005_reversible.rb +0 -10
  466. data/spec/files/reversible_migrations/006_reversible.rb +0 -10
  467. data/spec/files/reversible_migrations/007_reversible.rb +0 -10
  468. data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +0 -9
  469. data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +0 -9
  470. data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +0 -4
  471. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +0 -4
  472. data/spec/files/transaction_specified_migrations/002_create_basic.rb +0 -4
  473. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +0 -3
  474. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +0 -3
  475. data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +0 -9
  476. data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +0 -9
  477. data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +0 -4
  478. data/spec/guards_helper.rb +0 -58
  479. data/spec/integration/associations_test.rb +0 -2513
  480. data/spec/integration/database_test.rb +0 -113
  481. data/spec/integration/dataset_test.rb +0 -1880
  482. data/spec/integration/eager_loader_test.rb +0 -687
  483. data/spec/integration/migrator_test.rb +0 -262
  484. data/spec/integration/model_test.rb +0 -203
  485. data/spec/integration/plugin_test.rb +0 -2302
  486. data/spec/integration/prepared_statement_test.rb +0 -398
  487. data/spec/integration/schema_test.rb +0 -869
  488. data/spec/integration/spec_helper.rb +0 -64
  489. data/spec/integration/timezone_test.rb +0 -86
  490. data/spec/integration/transaction_test.rb +0 -354
  491. data/spec/integration/type_test.rb +0 -127
  492. data/spec/model/association_reflection_spec.rb +0 -803
  493. data/spec/model/associations_spec.rb +0 -4538
  494. data/spec/model/base_spec.rb +0 -817
  495. data/spec/model/class_dataset_methods_spec.rb +0 -146
  496. data/spec/model/dataset_methods_spec.rb +0 -198
  497. data/spec/model/eager_loading_spec.rb +0 -2262
  498. data/spec/model/hooks_spec.rb +0 -370
  499. data/spec/model/inflector_spec.rb +0 -26
  500. data/spec/model/model_spec.rb +0 -953
  501. data/spec/model/plugins_spec.rb +0 -318
  502. data/spec/model/record_spec.rb +0 -2107
  503. data/spec/model/spec_helper.rb +0 -45
  504. data/spec/model/validations_spec.rb +0 -193
  505. data/spec/model_no_assoc_spec.rb +0 -1
  506. data/spec/model_spec.rb +0 -1
  507. data/spec/plugin_spec.rb +0 -1
  508. data/spec/sequel_coverage.rb +0 -15
  509. data/spec/sequel_warning.rb +0 -4
  510. data/spec/spec_config.rb +0 -12
@@ -1,318 +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
@@ -1,2107 +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
- describe Sequel::Model, "#===" do
1449
- it "should compare instances by class and pk if pk is not nil" do
1450
- z = Class.new(Sequel::Model)
1451
- z.columns :id, :x
1452
- y = Class.new(Sequel::Model)
1453
- y.columns :id, :x
1454
- a = z.load(:id => 1, :x => 3)
1455
- b = z.load(:id => 1, :x => 4)
1456
- c = z.load(:id => 2, :x => 3)
1457
- d = y.load(:id => 1, :x => 3)
1458
-
1459
- a.must_be :===, b
1460
- a.wont_be :===, c
1461
- a.wont_be :===, d
1462
- end
1463
-
1464
- it "should always be false if the primary key is nil" do
1465
- z = Class.new(Sequel::Model)
1466
- z.columns :id, :x
1467
- y = Class.new(Sequel::Model)
1468
- y.columns :id, :x
1469
- a = z.new(:x => 3)
1470
- b = z.new(:x => 4)
1471
- c = z.new(:x => 3)
1472
- d = y.new(:x => 3)
1473
-
1474
- a.wont_be :===, b
1475
- a.wont_be :===, c
1476
- a.wont_be :===, d
1477
- end
1478
- end
1479
-
1480
- describe Sequel::Model, "#hash" do
1481
- it "should be the same only for objects with the same class and pk if the pk is not nil" do
1482
- z = Class.new(Sequel::Model)
1483
- z.columns :id, :x
1484
- y = Class.new(Sequel::Model)
1485
- y.columns :id, :x
1486
- a = z.load(:id => 1, :x => 3)
1487
-
1488
- a.hash.must_equal z.load(:id => 1, :x => 4).hash
1489
- a.hash.wont_equal z.load(:id => 2, :x => 3).hash
1490
- a.hash.wont_equal y.load(:id => 1, :x => 3).hash
1491
- end
1492
-
1493
- it "should be the same only for objects with the same class and values if the pk is nil" do
1494
- z = Class.new(Sequel::Model)
1495
- z.columns :id, :x
1496
- y = Class.new(Sequel::Model)
1497
- y.columns :id, :x
1498
- a = z.new(:x => 3)
1499
-
1500
- a.hash.wont_equal z.new(:x => 4).hash
1501
- a.hash.must_equal z.new(:x => 3).hash
1502
- a.hash.wont_equal y.new(:x => 3).hash
1503
- end
1504
-
1505
- 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
1506
- z = Class.new(Sequel::Model)
1507
- z.columns :id, :id2, :x
1508
- z.set_primary_key([:id, :id2])
1509
- y = Class.new(Sequel::Model)
1510
- y.columns :id, :id2, :x
1511
- y.set_primary_key([:id, :id2])
1512
- a = z.load(:id => 1, :id2=>2, :x => 3)
1513
-
1514
- a.hash.must_equal z.load(:id => 1, :id2=>2, :x => 4).hash
1515
- a.hash.wont_equal z.load(:id => 2, :id2=>1, :x => 3).hash
1516
- a.hash.wont_equal y.load(:id => 1, :id2=>1, :x => 3).hash
1517
- end
1518
-
1519
- it "should be the same only for objects with the same class and value if pk is composite and one values is NULL" do
1520
- z = Class.new(Sequel::Model)
1521
- z.columns :id, :id2, :x
1522
- z.set_primary_key([:id, :id2])
1523
- y = Class.new(Sequel::Model)
1524
- y.columns :id, :id2, :x
1525
- y.set_primary_key([:id, :id2])
1526
-
1527
- a = z.load(:id => 1, :id2 => nil, :x => 3)
1528
- a.hash.must_equal z.load(:id => 1, :id2=>nil, :x => 3).hash
1529
- a.hash.wont_equal z.load(:id => 1, :id2=>nil, :x => 4).hash
1530
- a.hash.wont_equal y.load(:id => 1, :id2=>nil, :x => 3).hash
1531
-
1532
- a = z.load(:id =>nil, :id2 => nil, :x => 3)
1533
- a.hash.must_equal z.load(:id => nil, :id2=>nil, :x => 3).hash
1534
- a.hash.wont_equal z.load(:id => nil, :id2=>nil, :x => 4).hash
1535
- a.hash.wont_equal y.load(:id => nil, :id2=>nil, :x => 3).hash
1536
-
1537
- a = z.load(:id => 1, :x => 3)
1538
- a.hash.must_equal z.load(:id => 1, :x => 3).hash
1539
- a.hash.wont_equal z.load(:id => 1, :id2=>nil, :x => 3).hash
1540
- a.hash.wont_equal z.load(:id => 1, :x => 4).hash
1541
- a.hash.wont_equal y.load(:id => 1, :x => 3).hash
1542
-
1543
- a = z.load(:x => 3)
1544
- a.hash.must_equal z.load(:x => 3).hash
1545
- a.hash.wont_equal z.load(:id => nil, :id2=>nil, :x => 3).hash
1546
- a.hash.wont_equal z.load(:x => 4).hash
1547
- a.hash.wont_equal y.load(:x => 3).hash
1548
- end
1549
-
1550
- it "should be the same only for objects with the same class and values if the no primary key" do
1551
- z = Class.new(Sequel::Model)
1552
- z.columns :id, :x
1553
- z.no_primary_key
1554
- y = Class.new(Sequel::Model)
1555
- y.columns :id, :x
1556
- y.no_primary_key
1557
- a = z.new(:x => 3)
1558
-
1559
- a.hash.wont_equal z.new(:x => 4).hash
1560
- a.hash.must_equal z.new(:x => 3).hash
1561
- a.hash.wont_equal y.new(:x => 3).hash
1562
- end
1563
-
1564
- end
1565
-
1566
- describe Sequel::Model, "#initialize" do
1567
- before do
1568
- @c = Class.new(Sequel::Model) do
1569
- columns :id, :x
1570
- end
1571
- @c.strict_param_setting = false
1572
- end
1573
-
1574
- it "should accept values" do
1575
- m = @c.new(:x => 2)
1576
- m.values.must_equal(:x => 2)
1577
- end
1578
-
1579
- it "should not modify the primary key" do
1580
- m = @c.new(:id => 1, :x => 2)
1581
- m.values.must_equal(:x => 2)
1582
- end
1583
-
1584
- it "should accept no values" do
1585
- m = @c.new
1586
- m.values.must_equal({})
1587
- end
1588
-
1589
- it "should accept a block to execute" do
1590
- m = @c.new {|o| o[:id] = 1234}
1591
- m.id.must_equal 1234
1592
- end
1593
-
1594
- it "should accept virtual attributes" do
1595
- @c.send(:define_method, :blah=){|x| @blah = x}
1596
- @c.send(:define_method, :blah){@blah}
1597
-
1598
- m = @c.new(:x => 2, :blah => 3)
1599
- m.values.must_equal(:x => 2)
1600
- m.blah.must_equal 3
1601
- end
1602
-
1603
- it "should convert string keys into symbol keys" do
1604
- m = @c.new('x' => 2)
1605
- m.values.must_equal(:x => 2)
1606
- end
1607
- end
1608
-
1609
- describe Sequel::Model, "#initialize_set" do
1610
- before do
1611
- @c = Class.new(Sequel::Model){columns :id, :x, :y}
1612
- end
1613
-
1614
- it "should be called by initialize to set the column values" do
1615
- @c.send(:define_method, :initialize_set){|h| set(:y => 3)}
1616
- @c.new(:x => 2).values.must_equal(:y => 3)
1617
- end
1618
-
1619
- it "should be called with the hash given to initialize " do
1620
- x = nil
1621
- @c.send(:define_method, :initialize_set){|y| x = y}
1622
- @c.new(:x => 2)
1623
- x.must_equal(:x => 2)
1624
- end
1625
-
1626
- it "should not cause columns modified by the method to be considered as changed" do
1627
- @c.send(:define_method, :initialize_set){|h| set(:y => 3)}
1628
- @c.new(:x => 2).changed_columns.must_equal []
1629
- end
1630
- end
1631
-
1632
- describe Sequel::Model, ".create" do
1633
- before do
1634
- DB.reset
1635
- @c = Class.new(Sequel::Model(:items)) do
1636
- unrestrict_primary_key
1637
- columns :x
1638
- end
1639
- end
1640
-
1641
- it "should be able to create rows in the associated table" do
1642
- o = @c.create(:x => 1)
1643
- o.class.must_equal @c
1644
- DB.sqls.must_equal ['INSERT INTO items (x) VALUES (1)', "SELECT * FROM items WHERE id = 10"]
1645
- end
1646
-
1647
- it "should be able to create rows without any values specified" do
1648
- o = @c.create
1649
- o.class.must_equal @c
1650
- DB.sqls.must_equal ["INSERT INTO items DEFAULT VALUES", "SELECT * FROM items WHERE id = 10"]
1651
- end
1652
-
1653
- it "should accept a block and call it" do
1654
- o1, o2, o3 = nil, nil, nil
1655
- o = @c.create {|o4| o1 = o4; o3 = o4; o2 = :blah; o3.x = 333}
1656
- o.class.must_equal @c
1657
- o1.must_be :===, o
1658
- o3.must_be :===, o
1659
- o2.must_equal :blah
1660
- DB.sqls.must_equal ["INSERT INTO items (x) VALUES (333)", "SELECT * FROM items WHERE id = 10"]
1661
- end
1662
-
1663
- it "should create a row for a model with custom primary key" do
1664
- @c.set_primary_key :x
1665
- o = @c.create(:x => 30)
1666
- o.class.must_equal @c
1667
- DB.sqls.must_equal ["INSERT INTO items (x) VALUES (30)", "SELECT * FROM items WHERE x = 30"]
1668
- end
1669
- end
1670
-
1671
- describe Sequel::Model, "#refresh" do
1672
- before do
1673
- @c = Class.new(Sequel::Model(:items)) do
1674
- unrestrict_primary_key
1675
- columns :id, :x
1676
- end
1677
- DB.reset
1678
- end
1679
-
1680
- it "should reload the instance values from the database" do
1681
- @m = @c.new(:id => 555)
1682
- @m[:x] = 'blah'
1683
- @c.dataset = @c.dataset.with_fetch(:x => 'kaboom', :id => 555)
1684
- @m.refresh
1685
- @m[:x].must_equal 'kaboom'
1686
- DB.sqls.must_equal ["SELECT * FROM items WHERE id = 555"]
1687
- end
1688
-
1689
- it "should raise if the instance is not found" do
1690
- @m = @c.new(:id => 555)
1691
- @c.dataset = @c.dataset.with_fetch([])
1692
- proc {@m.refresh}.must_raise(Sequel::NoExistingObject)
1693
- DB.sqls.must_equal ["SELECT * FROM items WHERE id = 555"]
1694
- end
1695
-
1696
- it "should be aliased by #reload" do
1697
- @m = @c.new(:id => 555)
1698
- @c.dataset = @c.dataset.with_fetch(:x => 'kaboom', :id => 555)
1699
- @m.reload
1700
- @m[:x].must_equal 'kaboom'
1701
- DB.sqls.must_equal ["SELECT * FROM items WHERE id = 555"]
1702
- end
1703
- end
1704
-
1705
- describe Sequel::Model, "typecasting" do
1706
- before do
1707
- @c = Class.new(Sequel::Model(:items)) do
1708
- columns :x
1709
- end
1710
- @c.db_schema = {:x=>{:type=>:integer}}
1711
- @c.raise_on_typecast_failure = true
1712
- DB.reset
1713
- end
1714
-
1715
- after do
1716
- Sequel.datetime_class = Time
1717
- end
1718
-
1719
- it "should not convert if typecasting is turned off" do
1720
- @c.typecast_on_assignment = false
1721
- m = @c.new
1722
- m.x = '1'
1723
- m.x.must_equal '1'
1724
- end
1725
-
1726
- it "should convert to integer for an integer field" do
1727
- @c.db_schema = {:x=>{:type=>:integer}}
1728
- m = @c.new
1729
- m.x = '1'
1730
- m.x.must_equal 1
1731
- m.x = 1
1732
- m.x.must_equal 1
1733
- m.x = 1.3
1734
- m.x.must_equal 1
1735
- end
1736
-
1737
- it "should typecast '' to nil unless type is string or blob" do
1738
- [:integer, :float, :decimal, :boolean, :date, :time, :datetime].each do |x|
1739
- @c.db_schema = {:x=>{:type=>x}}
1740
- m = @c.new
1741
- m.x = ''
1742
- m.x.must_be_nil
1743
- end
1744
- [:string, :blob].each do |x|
1745
- @c.db_schema = {:x=>{:type=>x}}
1746
- m = @c.new
1747
- m.x = ''
1748
- m.x.must_equal ''
1749
- end
1750
- end
1751
-
1752
- it "should not typecast '' to nil if typecast_empty_string_to_nil is false" do
1753
- m = @c.new
1754
- m.typecast_empty_string_to_nil = false
1755
- proc{m.x = ''}.must_raise Sequel::InvalidValue
1756
- @c.typecast_empty_string_to_nil = false
1757
- proc{@c.new.x = ''}.must_raise Sequel::InvalidValue
1758
- end
1759
-
1760
- it "should handle typecasting where == raises an error on the object" do
1761
- m = @c.new
1762
- o = Object.new
1763
- def o.==(v) raise ArgumentError end
1764
- def o.to_i() 4 end
1765
- m.x = o
1766
- m.x.must_equal 4
1767
- end
1768
-
1769
- it "should not typecast nil if NULLs are allowed" do
1770
- @c.db_schema[:x][:allow_null] = true
1771
- m = @c.new
1772
- m.x = nil
1773
- m.x.must_be_nil
1774
- end
1775
-
1776
- it "should raise an error if attempting to typecast nil and NULLs are not allowed" do
1777
- @c.db_schema[:x][:allow_null] = false
1778
- proc{@c.new.x = nil}.must_raise(Sequel::InvalidValue)
1779
- proc{@c.new.x = ''}.must_raise(Sequel::InvalidValue)
1780
- end
1781
-
1782
- it "should not raise an error if NULLs are not allowed and typecasting is turned off" do
1783
- @c.typecast_on_assignment = false
1784
- @c.db_schema[:x][:allow_null] = false
1785
- m = @c.new
1786
- m.x = nil
1787
- m.x.must_be_nil
1788
- end
1789
-
1790
- it "should not raise when typecasting nil to NOT NULL column but raise_on_typecast_failure is off" do
1791
- @c.raise_on_typecast_failure = false
1792
- @c.typecast_on_assignment = true
1793
- m = @c.new
1794
- m.x = ''
1795
- m.x.must_be_nil
1796
- m.x = nil
1797
- m.x.must_be_nil
1798
- end
1799
-
1800
- it "should raise an error if invalid data is used in an integer field" do
1801
- proc{@c.new.x = 'a'}.must_raise(Sequel::InvalidValue)
1802
- end
1803
-
1804
- it "should assign value if raise_on_typecast_failure is off and assigning invalid integer" do
1805
- @c.raise_on_typecast_failure = false
1806
- model = @c.new
1807
- model.x = '1d'
1808
- model.x.must_equal '1d'
1809
- end
1810
-
1811
- it "should convert to float for a float field" do
1812
- @c.db_schema = {:x=>{:type=>:float}}
1813
- m = @c.new
1814
- m.x = '1.3'
1815
- m.x.must_equal 1.3
1816
- m.x = 1
1817
- m.x.must_equal 1.0
1818
- m.x = 1.3
1819
- m.x.must_equal 1.3
1820
- end
1821
-
1822
- it "should raise an error if invalid data is used in an float field" do
1823
- @c.db_schema = {:x=>{:type=>:float}}
1824
- proc{@c.new.x = 'a'}.must_raise(Sequel::InvalidValue)
1825
- end
1826
-
1827
- it "should assign value if raise_on_typecast_failure is off and assigning invalid float" do
1828
- @c.raise_on_typecast_failure = false
1829
- @c.db_schema = {:x=>{:type=>:float}}
1830
- model = @c.new
1831
- model.x = '1d'
1832
- model.x.must_equal '1d'
1833
- end
1834
-
1835
- it "should convert to BigDecimal for a decimal field" do
1836
- @c.db_schema = {:x=>{:type=>:decimal}}
1837
- m = @c.new
1838
- bd = BigDecimal.new('1.0')
1839
- m.x = '1.0'
1840
- m.x.must_equal bd
1841
- m.x = 1.0
1842
- m.x.must_equal bd
1843
- m.x = 1
1844
- m.x.must_equal bd
1845
- m.x = bd
1846
- m.x.must_equal bd
1847
- m.x = '0'
1848
- m.x.must_equal 0
1849
- end
1850
-
1851
- it "should raise an error if invalid data is used in an decimal field" do
1852
- @c.db_schema = {:x=>{:type=>:decimal}}
1853
- proc{@c.new.x = Date.today}.must_raise(Sequel::InvalidValue)
1854
- proc{@c.new.x = 'foo'}.must_raise(Sequel::InvalidValue)
1855
- end
1856
-
1857
- it "should assign value if raise_on_typecast_failure is off and assigning invalid decimal" do
1858
- @c.raise_on_typecast_failure = false
1859
- @c.db_schema = {:x=>{:type=>:decimal}}
1860
- model = @c.new
1861
- time = Time.now
1862
- model.x = time
1863
- model.x.must_equal time
1864
- end
1865
-
1866
- it "should convert to string for a string field" do
1867
- @c.db_schema = {:x=>{:type=>:string}}
1868
- m = @c.new
1869
- m.x = '1.3'
1870
- m.x.must_equal '1.3'
1871
- m.x = 1
1872
- m.x.must_equal '1'
1873
- m.x = 1.3
1874
- m.x.must_equal '1.3'
1875
- end
1876
-
1877
- it "should convert to boolean for a boolean field" do
1878
- @c.db_schema = {:x=>{:type=>:boolean}}
1879
- m = @c.new
1880
- m.x = '1.3'
1881
- m.x.must_equal true
1882
- m.x = 1
1883
- m.x.must_equal true
1884
- m.x = 1.3
1885
- m.x.must_equal true
1886
- m.x = 't'
1887
- m.x.must_equal true
1888
- m.x = 'T'
1889
- m.x.must_equal true
1890
- m.x = 'y'
1891
- m.x.must_equal true
1892
- m.x = 'Y'
1893
- m.x.must_equal true
1894
- m.x = true
1895
- m.x.must_equal true
1896
- m.x = nil
1897
- m.x.must_be_nil
1898
- m.x = ''
1899
- m.x.must_be_nil
1900
- m.x = []
1901
- m.x.must_be_nil
1902
- m.x = 'f'
1903
- m.x.must_equal false
1904
- m.x = 'F'
1905
- m.x.must_equal false
1906
- m.x = 'false'
1907
- m.x.must_equal false
1908
- m.x = 'FALSE'
1909
- m.x.must_equal false
1910
- m.x = 'n'
1911
- m.x.must_equal false
1912
- m.x = 'N'
1913
- m.x.must_equal false
1914
- m.x = 'no'
1915
- m.x.must_equal false
1916
- m.x = 'NO'
1917
- m.x.must_equal false
1918
- m.x = '0'
1919
- m.x.must_equal false
1920
- m.x = 0
1921
- m.x.must_equal false
1922
- m.x = false
1923
- m.x.must_equal false
1924
- end
1925
-
1926
- it "should convert to date for a date field" do
1927
- @c.db_schema = {:x=>{:type=>:date}}
1928
- m = @c.new
1929
- y = Date.new(2007,10,21)
1930
- m.x = '2007-10-21'
1931
- m.x.must_equal y
1932
- m.x = Date.parse('2007-10-21')
1933
- m.x.must_equal y
1934
- m.x = Time.parse('2007-10-21')
1935
- m.x.must_equal y
1936
- m.x = DateTime.parse('2007-10-21')
1937
- m.x.must_equal y
1938
- end
1939
-
1940
- it "should accept a hash with symbol or string keys for a date field" do
1941
- @c.db_schema = {:x=>{:type=>:date}}
1942
- m = @c.new
1943
- y = Date.new(2007,10,21)
1944
- m.x = {:year=>2007, :month=>10, :day=>21}
1945
- m.x.must_equal y
1946
- m.x = {'year'=>'2007', 'month'=>'10', 'day'=>'21'}
1947
- m.x.must_equal y
1948
- end
1949
-
1950
- it "should raise an error if invalid data is used in a date field" do
1951
- @c.db_schema = {:x=>{:type=>:date}}
1952
- proc{@c.new.x = 'a'}.must_raise(Sequel::InvalidValue)
1953
- proc{@c.new.x = 100}.must_raise(Sequel::InvalidValue)
1954
- end
1955
-
1956
- it "should assign value if raise_on_typecast_failure is off and assigning invalid date" do
1957
- @c.raise_on_typecast_failure = false
1958
- @c.db_schema = {:x=>{:type=>:date}}
1959
- model = @c.new
1960
- model.x = 4
1961
- model.x.must_equal 4
1962
- end
1963
-
1964
- it "should convert to Sequel::SQLTime for a time field" do
1965
- @c.db_schema = {:x=>{:type=>:time}}
1966
- m = @c.new
1967
- x = '10:20:30'
1968
- y = Sequel::SQLTime.parse(x)
1969
- m.x = x
1970
- m.x.must_equal y
1971
- m.x = y
1972
- m.x.must_equal y
1973
- m.x.must_be_kind_of(Sequel::SQLTime)
1974
- end
1975
-
1976
- it "should accept a hash with symbol or string keys for a time field" do
1977
- @c.db_schema = {:x=>{:type=>:time}}
1978
- m = @c.new
1979
- y = Time.parse('10:20:30')
1980
- m.x = {:hour=>10, :minute=>20, :second=>30}
1981
- m.x.must_equal y
1982
- m.x = {'hour'=>'10', 'minute'=>'20', 'second'=>'30'}
1983
- m.x.must_equal y
1984
- end
1985
-
1986
- it "should raise an error if invalid data is used in a time field" do
1987
- @c.db_schema = {:x=>{:type=>:time}}
1988
- proc{@c.new.x = '0000'}.must_raise(Sequel::InvalidValue)
1989
- proc{@c.new.x = Date.parse('2008-10-21')}.must_raise(Sequel::InvalidValue)
1990
- proc{@c.new.x = DateTime.parse('2008-10-21')}.must_raise(Sequel::InvalidValue)
1991
- end
1992
-
1993
- it "should assign value if raise_on_typecast_failure is off and assigning invalid time" do
1994
- @c.raise_on_typecast_failure = false
1995
- @c.db_schema = {:x=>{:type=>:time}}
1996
- model = @c.new
1997
- model.x = '0000'
1998
- model.x.must_equal '0000'
1999
- end
2000
-
2001
- it "should convert to the Sequel.datetime_class for a datetime field" do
2002
- @c.db_schema = {:x=>{:type=>:datetime}}
2003
- m = @c.new
2004
- x = '2007-10-21T10:20:30-07:00'
2005
- y = Time.parse(x)
2006
- m.x = x
2007
- m.x.must_equal y
2008
- m.x = DateTime.parse(x)
2009
- m.x.must_equal y
2010
- m.x = Time.parse(x)
2011
- m.x.must_equal y
2012
- m.x = Date.parse('2007-10-21')
2013
- m.x.must_equal Time.parse('2007-10-21')
2014
- Sequel.datetime_class = DateTime
2015
- y = DateTime.parse(x)
2016
- m.x = x
2017
- m.x.must_equal y
2018
- m.x = DateTime.parse(x)
2019
- m.x.must_equal y
2020
- m.x = Time.parse(x)
2021
- m.x.must_equal y
2022
- m.x = Date.parse('2007-10-21')
2023
- m.x.must_equal DateTime.parse('2007-10-21')
2024
- end
2025
-
2026
- it "should accept a hash with symbol or string keys for a datetime field" do
2027
- @c.db_schema = {:x=>{:type=>:datetime}}
2028
- m = @c.new
2029
- y = Time.parse('2007-10-21 10:20:30')
2030
- m.x = {:year=>2007, :month=>10, :day=>21, :hour=>10, :minute=>20, :second=>30}
2031
- m.x.must_equal y
2032
- m.x = {'year'=>'2007', 'month'=>'10', 'day'=>'21', 'hour'=>'10', 'minute'=>'20', 'second'=>'30'}
2033
- m.x.must_equal y
2034
- Sequel.datetime_class = DateTime
2035
- y = DateTime.parse('2007-10-21 10:20:30')
2036
- m.x = {:year=>2007, :month=>10, :day=>21, :hour=>10, :minute=>20, :second=>30}
2037
- m.x.must_equal y
2038
- m.x = {'year'=>'2007', 'month'=>'10', 'day'=>'21', 'hour'=>'10', 'minute'=>'20', 'second'=>'30'}
2039
- m.x.must_equal y
2040
- end
2041
-
2042
- it "should raise an error if invalid data is used in a datetime field" do
2043
- @c.db_schema = {:x=>{:type=>:datetime}}
2044
- proc{@c.new.x = '0000'}.must_raise(Sequel::InvalidValue)
2045
- Sequel.datetime_class = DateTime
2046
- proc{@c.new.x = '0000'}.must_raise(Sequel::InvalidValue)
2047
- proc{@c.new.x = 'a'}.must_raise(Sequel::InvalidValue)
2048
- end
2049
-
2050
- it "should assign value if raise_on_typecast_failure is off and assigning invalid datetime" do
2051
- @c.raise_on_typecast_failure = false
2052
- @c.db_schema = {:x=>{:type=>:datetime}}
2053
- model = @c.new
2054
- model.x = '0000'
2055
- model.x.must_equal '0000'
2056
- Sequel.datetime_class = DateTime
2057
- model = @c.new
2058
- model.x = '0000'
2059
- model.x.must_equal '0000'
2060
- model.x = 'a'
2061
- model.x.must_equal 'a'
2062
- end
2063
- end
2064
-
2065
- describe "Model#lock!" do
2066
- before do
2067
- @c = Class.new(Sequel::Model(:items)) do
2068
- columns :id
2069
- end
2070
- @c.dataset = @c.dataset.with_fetch(:id=>1)
2071
- DB.reset
2072
- end
2073
-
2074
- it "should do nothing if the record is a new record" do
2075
- o = @c.new
2076
- def o._refresh(x) raise Sequel::Error; super(x) end
2077
- x = o.lock!
2078
- x.must_equal o
2079
- DB.sqls.must_equal []
2080
- end
2081
-
2082
- it "should refresh the record using for_update if it is not a new record" do
2083
- o = @c.load(:id => 1)
2084
- def o._refresh(x) instance_variable_set(:@a, 1); super(x) end
2085
- x = o.lock!
2086
- x.must_equal o
2087
- o.instance_variable_get(:@a).must_equal 1
2088
- DB.sqls.must_equal ["SELECT * FROM items WHERE (id = 1) LIMIT 1 FOR UPDATE"]
2089
- end
2090
-
2091
- it "should refresh the record using the specified lock when it is not a new record and a style is given" do
2092
- o = @c.load(:id => 1)
2093
- def o._refresh(x) instance_variable_set(:@a, 1); super(x) end
2094
- x = o.lock!('FOR NO KEY UPDATE')
2095
- x.must_equal o
2096
- o.instance_variable_get(:@a).must_equal 1
2097
- DB.sqls.must_equal ["SELECT * FROM items WHERE (id = 1) LIMIT 1 FOR NO KEY UPDATE"]
2098
- end
2099
- end
2100
-
2101
- describe "Model#schema_type_class" do
2102
- it "should return the class or array of classes for the given type symbol" do
2103
- @c = Class.new(Sequel::Model(:items))
2104
- @c.class_eval{@db_schema = {:id=>{:type=>:integer}}}
2105
- @c.new.send(:schema_type_class, :id).must_equal Integer
2106
- end
2107
- end