sequel 3.21.0 → 3.41.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 (363) hide show
  1. data/CHANGELOG +1131 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +106 -65
  4. data/Rakefile +59 -27
  5. data/bin/sequel +50 -26
  6. data/doc/active_record.rdoc +68 -52
  7. data/doc/advanced_associations.rdoc +201 -75
  8. data/doc/association_basics.rdoc +327 -79
  9. data/doc/bin_sequel.rdoc +144 -0
  10. data/doc/cheat_sheet.rdoc +21 -21
  11. data/doc/core_extensions.rdoc +374 -0
  12. data/doc/dataset_basics.rdoc +10 -10
  13. data/doc/dataset_filtering.rdoc +54 -42
  14. data/doc/mass_assignment.rdoc +56 -0
  15. data/doc/migration.rdoc +89 -557
  16. data/doc/model_hooks.rdoc +80 -29
  17. data/doc/object_model.rdoc +576 -0
  18. data/doc/opening_databases.rdoc +121 -53
  19. data/doc/prepared_statements.rdoc +41 -15
  20. data/doc/querying.rdoc +137 -56
  21. data/doc/reflection.rdoc +36 -10
  22. data/doc/release_notes/3.22.0.txt +39 -0
  23. data/doc/release_notes/3.23.0.txt +172 -0
  24. data/doc/release_notes/3.24.0.txt +420 -0
  25. data/doc/release_notes/3.25.0.txt +88 -0
  26. data/doc/release_notes/3.26.0.txt +88 -0
  27. data/doc/release_notes/3.27.0.txt +82 -0
  28. data/doc/release_notes/3.28.0.txt +304 -0
  29. data/doc/release_notes/3.29.0.txt +459 -0
  30. data/doc/release_notes/3.30.0.txt +135 -0
  31. data/doc/release_notes/3.31.0.txt +146 -0
  32. data/doc/release_notes/3.32.0.txt +202 -0
  33. data/doc/release_notes/3.33.0.txt +157 -0
  34. data/doc/release_notes/3.34.0.txt +671 -0
  35. data/doc/release_notes/3.35.0.txt +144 -0
  36. data/doc/release_notes/3.36.0.txt +245 -0
  37. data/doc/release_notes/3.37.0.txt +338 -0
  38. data/doc/release_notes/3.38.0.txt +234 -0
  39. data/doc/release_notes/3.39.0.txt +237 -0
  40. data/doc/release_notes/3.40.0.txt +73 -0
  41. data/doc/release_notes/3.41.0.txt +155 -0
  42. data/doc/schema_modification.rdoc +585 -0
  43. data/doc/sharding.rdoc +99 -8
  44. data/doc/sql.rdoc +154 -112
  45. data/doc/testing.rdoc +169 -0
  46. data/doc/thread_safety.rdoc +17 -0
  47. data/doc/transactions.rdoc +137 -0
  48. data/doc/validations.rdoc +1 -1
  49. data/doc/virtual_rows.rdoc +78 -43
  50. data/lib/sequel/adapters/ado/access.rb +334 -0
  51. data/lib/sequel/adapters/ado/mssql.rb +18 -12
  52. data/lib/sequel/adapters/ado.rb +69 -21
  53. data/lib/sequel/adapters/amalgalite.rb +17 -14
  54. data/lib/sequel/adapters/cubrid.rb +143 -0
  55. data/lib/sequel/adapters/db2.rb +178 -85
  56. data/lib/sequel/adapters/dbi.rb +19 -21
  57. data/lib/sequel/adapters/do/mysql.rb +17 -11
  58. data/lib/sequel/adapters/do/postgres.rb +2 -61
  59. data/lib/sequel/adapters/do/sqlite.rb +0 -10
  60. data/lib/sequel/adapters/do.rb +20 -39
  61. data/lib/sequel/adapters/firebird.rb +33 -210
  62. data/lib/sequel/adapters/ibmdb.rb +452 -0
  63. data/lib/sequel/adapters/informix.rb +6 -29
  64. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  65. data/lib/sequel/adapters/jdbc/cubrid.rb +52 -0
  66. data/lib/sequel/adapters/jdbc/db2.rb +78 -0
  67. data/lib/sequel/adapters/jdbc/derby.rb +325 -0
  68. data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
  69. data/lib/sequel/adapters/jdbc/h2.rb +68 -31
  70. data/lib/sequel/adapters/jdbc/hsqldb.rb +189 -0
  71. data/lib/sequel/adapters/jdbc/informix.rb +21 -0
  72. data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
  73. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  74. data/lib/sequel/adapters/jdbc/mysql.rb +16 -28
  75. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  76. data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
  77. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  78. data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
  79. data/lib/sequel/adapters/jdbc/sqlserver.rb +72 -0
  80. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  81. data/lib/sequel/adapters/jdbc.rb +308 -114
  82. data/lib/sequel/adapters/mock.rb +372 -0
  83. data/lib/sequel/adapters/mysql.rb +130 -230
  84. data/lib/sequel/adapters/mysql2.rb +64 -63
  85. data/lib/sequel/adapters/odbc/mssql.rb +17 -9
  86. data/lib/sequel/adapters/odbc.rb +29 -10
  87. data/lib/sequel/adapters/openbase.rb +7 -11
  88. data/lib/sequel/adapters/oracle.rb +364 -57
  89. data/lib/sequel/adapters/postgres.rb +379 -145
  90. data/lib/sequel/adapters/shared/access.rb +236 -11
  91. data/lib/sequel/adapters/shared/cubrid.rb +216 -0
  92. data/lib/sequel/adapters/shared/db2.rb +353 -0
  93. data/lib/sequel/adapters/shared/firebird.rb +231 -0
  94. data/lib/sequel/adapters/shared/informix.rb +53 -0
  95. data/lib/sequel/adapters/shared/mssql.rb +412 -116
  96. data/lib/sequel/adapters/shared/mysql.rb +396 -89
  97. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +166 -0
  98. data/lib/sequel/adapters/shared/oracle.rb +262 -45
  99. data/lib/sequel/adapters/shared/postgres.rb +688 -279
  100. data/lib/sequel/adapters/shared/progress.rb +5 -8
  101. data/lib/sequel/adapters/shared/sqlite.rb +317 -96
  102. data/lib/sequel/adapters/sqlite.rb +109 -46
  103. data/lib/sequel/adapters/swift/mysql.rb +10 -12
  104. data/lib/sequel/adapters/swift/postgres.rb +13 -79
  105. data/lib/sequel/adapters/swift/sqlite.rb +9 -6
  106. data/lib/sequel/adapters/swift.rb +31 -27
  107. data/lib/sequel/adapters/tinytds.rb +177 -25
  108. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
  109. data/lib/sequel/adapters/utils/pg_types.rb +81 -0
  110. data/lib/sequel/adapters/utils/split_alter_table.rb +36 -0
  111. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  112. data/lib/sequel/ast_transformer.rb +194 -0
  113. data/lib/sequel/connection_pool/sharded_single.rb +23 -13
  114. data/lib/sequel/connection_pool/sharded_threaded.rb +64 -13
  115. data/lib/sequel/connection_pool/single.rb +11 -3
  116. data/lib/sequel/connection_pool/threaded.rb +69 -20
  117. data/lib/sequel/connection_pool.rb +20 -18
  118. data/lib/sequel/core.rb +143 -11
  119. data/lib/sequel/database/connecting.rb +66 -29
  120. data/lib/sequel/database/dataset.rb +4 -4
  121. data/lib/sequel/database/dataset_defaults.rb +63 -2
  122. data/lib/sequel/database/logging.rb +7 -2
  123. data/lib/sequel/database/misc.rb +192 -51
  124. data/lib/sequel/database/query.rb +299 -114
  125. data/lib/sequel/database/schema_generator.rb +103 -36
  126. data/lib/sequel/database/schema_methods.rb +310 -69
  127. data/lib/sequel/dataset/actions.rb +344 -90
  128. data/lib/sequel/dataset/features.rb +101 -8
  129. data/lib/sequel/dataset/graph.rb +42 -15
  130. data/lib/sequel/dataset/misc.rb +52 -25
  131. data/lib/sequel/dataset/mutation.rb +12 -7
  132. data/lib/sequel/dataset/prepared_statements.rb +68 -30
  133. data/lib/sequel/dataset/query.rb +322 -68
  134. data/lib/sequel/dataset/sql.rb +716 -293
  135. data/lib/sequel/dataset.rb +8 -0
  136. data/lib/sequel/exceptions.rb +4 -0
  137. data/lib/sequel/extensions/_pretty_table.rb +83 -0
  138. data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
  139. data/lib/sequel/extensions/blank.rb +4 -0
  140. data/lib/sequel/extensions/columns_introspection.rb +72 -0
  141. data/lib/sequel/extensions/connection_validator.rb +109 -0
  142. data/lib/sequel/extensions/constraint_validations.rb +451 -0
  143. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
  144. data/lib/sequel/extensions/eval_inspect.rb +173 -0
  145. data/lib/sequel/extensions/inflector.rb +4 -0
  146. data/lib/sequel/extensions/looser_typecasting.rb +5 -4
  147. data/lib/sequel/extensions/migration.rb +100 -11
  148. data/lib/sequel/extensions/named_timezones.rb +9 -0
  149. data/lib/sequel/extensions/null_dataset.rb +94 -0
  150. data/lib/sequel/extensions/pagination.rb +4 -0
  151. data/lib/sequel/extensions/pg_array.rb +539 -0
  152. data/lib/sequel/extensions/pg_array_ops.rb +263 -0
  153. data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
  154. data/lib/sequel/extensions/pg_hstore.rb +334 -0
  155. data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
  156. data/lib/sequel/extensions/pg_inet.rb +113 -0
  157. data/lib/sequel/extensions/pg_interval.rb +191 -0
  158. data/lib/sequel/extensions/pg_json.rb +212 -0
  159. data/lib/sequel/extensions/pg_range.rb +513 -0
  160. data/lib/sequel/extensions/pg_range_ops.rb +150 -0
  161. data/lib/sequel/extensions/pg_row.rb +576 -0
  162. data/lib/sequel/extensions/pg_row_ops.rb +182 -0
  163. data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
  164. data/lib/sequel/extensions/pretty_table.rb +17 -72
  165. data/lib/sequel/extensions/query.rb +8 -4
  166. data/lib/sequel/extensions/query_literals.rb +79 -0
  167. data/lib/sequel/extensions/schema_caching.rb +76 -0
  168. data/lib/sequel/extensions/schema_dumper.rb +282 -76
  169. data/lib/sequel/extensions/select_remove.rb +39 -0
  170. data/lib/sequel/extensions/server_block.rb +140 -0
  171. data/lib/sequel/extensions/split_array_nil.rb +65 -0
  172. data/lib/sequel/extensions/sql_expr.rb +8 -110
  173. data/lib/sequel/extensions/string_date_time.rb +4 -0
  174. data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
  175. data/lib/sequel/extensions/to_dot.rb +99 -83
  176. data/lib/sequel/model/associations.rb +1263 -409
  177. data/lib/sequel/model/base.rb +624 -171
  178. data/lib/sequel/model/errors.rb +1 -1
  179. data/lib/sequel/model/exceptions.rb +24 -2
  180. data/lib/sequel/model/inflections.rb +1 -1
  181. data/lib/sequel/model.rb +30 -11
  182. data/lib/sequel/no_core_ext.rb +2 -0
  183. data/lib/sequel/plugins/active_model.rb +13 -1
  184. data/lib/sequel/plugins/association_pks.rb +137 -16
  185. data/lib/sequel/plugins/caching.rb +25 -18
  186. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  187. data/lib/sequel/plugins/composition.rb +44 -12
  188. data/lib/sequel/plugins/constraint_validations.rb +198 -0
  189. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  190. data/lib/sequel/plugins/defaults_setter.rb +72 -0
  191. data/lib/sequel/plugins/dirty.rb +214 -0
  192. data/lib/sequel/plugins/eager_each.rb +59 -0
  193. data/lib/sequel/plugins/force_encoding.rb +6 -6
  194. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  195. data/lib/sequel/plugins/identity_map.rb +134 -15
  196. data/lib/sequel/plugins/instance_filters.rb +10 -0
  197. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  198. data/lib/sequel/plugins/json_serializer.rb +77 -6
  199. data/lib/sequel/plugins/list.rb +13 -2
  200. data/lib/sequel/plugins/many_through_many.rb +103 -51
  201. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  202. data/lib/sequel/plugins/nested_attributes.rb +150 -66
  203. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  204. data/lib/sequel/plugins/pg_row.rb +121 -0
  205. data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
  206. data/lib/sequel/plugins/prepared_statements.rb +168 -0
  207. data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
  208. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  209. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  210. data/lib/sequel/plugins/rcte_tree.rb +31 -17
  211. data/lib/sequel/plugins/schema.rb +8 -3
  212. data/lib/sequel/plugins/serialization.rb +98 -49
  213. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  214. data/lib/sequel/plugins/sharding.rb +21 -54
  215. data/lib/sequel/plugins/single_table_inheritance.rb +57 -12
  216. data/lib/sequel/plugins/static_cache.rb +99 -0
  217. data/lib/sequel/plugins/subclasses.rb +29 -3
  218. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  219. data/lib/sequel/plugins/timestamps.rb +1 -1
  220. data/lib/sequel/plugins/touch.rb +18 -6
  221. data/lib/sequel/plugins/tree.rb +3 -3
  222. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  223. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  224. data/lib/sequel/plugins/validation_class_methods.rb +2 -1
  225. data/lib/sequel/plugins/validation_helpers.rb +57 -4
  226. data/lib/sequel/plugins/xml_serializer.rb +15 -4
  227. data/lib/sequel/sql.rb +721 -141
  228. data/lib/sequel/timezones.rb +67 -40
  229. data/lib/sequel/version.rb +1 -1
  230. data/spec/adapters/db2_spec.rb +146 -0
  231. data/spec/adapters/firebird_spec.rb +53 -39
  232. data/spec/adapters/mssql_spec.rb +261 -66
  233. data/spec/adapters/mysql_spec.rb +597 -352
  234. data/spec/adapters/oracle_spec.rb +92 -117
  235. data/spec/adapters/postgres_spec.rb +2103 -341
  236. data/spec/adapters/spec_helper.rb +16 -6
  237. data/spec/adapters/sqlite_spec.rb +237 -76
  238. data/spec/core/connection_pool_spec.rb +270 -141
  239. data/spec/core/database_spec.rb +980 -524
  240. data/spec/core/dataset_spec.rb +1658 -1243
  241. data/spec/core/expression_filters_spec.rb +741 -334
  242. data/spec/core/mock_adapter_spec.rb +453 -0
  243. data/spec/core/object_graph_spec.rb +88 -129
  244. data/spec/core/schema_generator_spec.rb +4 -4
  245. data/spec/core/schema_spec.rb +556 -53
  246. data/spec/core/spec_helper.rb +7 -48
  247. data/spec/core_extensions_spec.rb +626 -0
  248. data/spec/extensions/active_model_spec.rb +13 -0
  249. data/spec/extensions/arbitrary_servers_spec.rb +110 -0
  250. data/spec/extensions/association_autoreloading_spec.rb +18 -10
  251. data/spec/extensions/association_dependencies_spec.rb +15 -25
  252. data/spec/extensions/association_pks_spec.rb +227 -33
  253. data/spec/extensions/association_proxies_spec.rb +4 -4
  254. data/spec/extensions/boolean_readers_spec.rb +25 -25
  255. data/spec/extensions/caching_spec.rb +47 -51
  256. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  257. data/spec/extensions/columns_introspection_spec.rb +91 -0
  258. data/spec/extensions/composition_spec.rb +18 -13
  259. data/spec/extensions/connection_validator_spec.rb +118 -0
  260. data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
  261. data/spec/extensions/constraint_validations_spec.rb +316 -0
  262. data/spec/extensions/dataset_associations_spec.rb +199 -0
  263. data/spec/extensions/defaults_setter_spec.rb +88 -0
  264. data/spec/extensions/dirty_spec.rb +155 -0
  265. data/spec/extensions/eager_each_spec.rb +34 -0
  266. data/spec/extensions/eval_inspect_spec.rb +67 -0
  267. data/spec/extensions/force_encoding_spec.rb +4 -2
  268. data/spec/extensions/hook_class_methods_spec.rb +97 -128
  269. data/spec/extensions/identity_map_spec.rb +142 -24
  270. data/spec/extensions/inflector_spec.rb +0 -4
  271. data/spec/extensions/instance_filters_spec.rb +11 -21
  272. data/spec/extensions/instance_hooks_spec.rb +72 -0
  273. data/spec/extensions/json_serializer_spec.rb +49 -12
  274. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  275. data/spec/extensions/list_spec.rb +49 -40
  276. data/spec/extensions/looser_typecasting_spec.rb +7 -7
  277. data/spec/extensions/many_through_many_spec.rb +368 -254
  278. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  279. data/spec/extensions/migration_spec.rb +140 -35
  280. data/spec/extensions/named_timezones_spec.rb +29 -11
  281. data/spec/extensions/nested_attributes_spec.rb +268 -89
  282. data/spec/extensions/null_dataset_spec.rb +85 -0
  283. data/spec/extensions/optimistic_locking_spec.rb +24 -21
  284. data/spec/extensions/pg_array_ops_spec.rb +112 -0
  285. data/spec/extensions/pg_array_spec.rb +324 -0
  286. data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
  287. data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
  288. data/spec/extensions/pg_hstore_spec.rb +200 -0
  289. data/spec/extensions/pg_inet_spec.rb +47 -0
  290. data/spec/extensions/pg_interval_spec.rb +72 -0
  291. data/spec/extensions/pg_json_spec.rb +99 -0
  292. data/spec/extensions/pg_range_ops_spec.rb +56 -0
  293. data/spec/extensions/pg_range_spec.rb +395 -0
  294. data/spec/extensions/pg_row_ops_spec.rb +58 -0
  295. data/spec/extensions/pg_row_plugin_spec.rb +49 -0
  296. data/spec/extensions/pg_row_spec.rb +340 -0
  297. data/spec/extensions/pg_statement_cache_spec.rb +208 -0
  298. data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
  299. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  300. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  301. data/spec/extensions/prepared_statements_spec.rb +87 -0
  302. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  303. data/spec/extensions/pretty_table_spec.rb +7 -6
  304. data/spec/extensions/query_literals_spec.rb +167 -0
  305. data/spec/extensions/query_spec.rb +9 -3
  306. data/spec/extensions/rcte_tree_spec.rb +50 -43
  307. data/spec/extensions/schema_caching_spec.rb +41 -0
  308. data/spec/extensions/schema_dumper_spec.rb +434 -49
  309. data/spec/extensions/schema_spec.rb +30 -49
  310. data/spec/extensions/select_remove_spec.rb +38 -0
  311. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  312. data/spec/extensions/serialization_spec.rb +86 -48
  313. data/spec/extensions/server_block_spec.rb +90 -0
  314. data/spec/extensions/sharding_spec.rb +69 -143
  315. data/spec/extensions/single_table_inheritance_spec.rb +65 -29
  316. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  317. data/spec/extensions/spec_helper.rb +34 -67
  318. data/spec/extensions/split_array_nil_spec.rb +24 -0
  319. data/spec/extensions/sql_expr_spec.rb +29 -60
  320. data/spec/extensions/static_cache_spec.rb +145 -0
  321. data/spec/extensions/subclasses_spec.rb +14 -0
  322. data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
  323. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  324. data/spec/extensions/timestamps_spec.rb +6 -6
  325. data/spec/extensions/to_dot_spec.rb +8 -11
  326. data/spec/extensions/touch_spec.rb +53 -14
  327. data/spec/extensions/tree_spec.rb +11 -26
  328. data/spec/extensions/typecast_on_load_spec.rb +9 -6
  329. data/spec/extensions/update_primary_key_spec.rb +30 -24
  330. data/spec/extensions/validation_class_methods_spec.rb +77 -68
  331. data/spec/extensions/validation_helpers_spec.rb +48 -37
  332. data/spec/extensions/xml_serializer_spec.rb +29 -4
  333. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
  334. data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
  335. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
  336. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
  337. data/spec/integration/associations_test.rb +659 -21
  338. data/spec/integration/database_test.rb +25 -5
  339. data/spec/integration/dataset_test.rb +729 -141
  340. data/spec/integration/eager_loader_test.rb +38 -54
  341. data/spec/integration/migrator_test.rb +2 -3
  342. data/spec/integration/model_test.rb +81 -2
  343. data/spec/integration/plugin_test.rb +871 -160
  344. data/spec/integration/prepared_statement_test.rb +272 -128
  345. data/spec/integration/schema_test.rb +377 -57
  346. data/spec/integration/spec_helper.rb +49 -32
  347. data/spec/integration/timezone_test.rb +38 -12
  348. data/spec/integration/transaction_test.rb +183 -8
  349. data/spec/integration/type_test.rb +40 -8
  350. data/spec/model/association_reflection_spec.rb +207 -8
  351. data/spec/model/associations_spec.rb +1206 -693
  352. data/spec/model/base_spec.rb +334 -100
  353. data/spec/model/dataset_methods_spec.rb +45 -27
  354. data/spec/model/eager_loading_spec.rb +828 -692
  355. data/spec/model/hooks_spec.rb +355 -67
  356. data/spec/model/model_spec.rb +251 -179
  357. data/spec/model/plugins_spec.rb +24 -13
  358. data/spec/model/record_spec.rb +506 -232
  359. data/spec/model/spec_helper.rb +16 -77
  360. data/spec/model/validations_spec.rb +38 -2
  361. data/spec/rcov.opts +2 -0
  362. metadata +223 -81
  363. data/spec/core/core_sql_spec.rb +0 -451
@@ -1,36 +1,39 @@
1
1
  require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
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.should equal(hash)
11
+ end
12
+
13
+ it "should be aliased as to_hash" do
14
+ hash = {:x=>1}
15
+ @c.load(hash).to_hash.should equal(hash)
16
+ end
17
+ end
18
+
3
19
  describe "Model#save server use" do
4
-
5
- before(:each) do
6
- @c = Class.new(Sequel::Model(:items)) do
7
- columns :id, :x, :y
8
- end
9
- @c.db = MockDatabase.new
10
- db2 = @db2 = MockDatabase.new
11
- @c.class_eval do
12
- define_method(:after_save) do
13
- model.db = db2
14
- ds = model.dataset
15
- def ds.fetch_rows(sql)
16
- yield @db.execute(sql, @opts[:server])
17
- end
18
- @this = nil
19
- end
20
- end
20
+ before do
21
+ @db = Sequel.mock(:autoid=>proc{|sql| 10}, :fetch=>{:x=>1, :id=>10}, :servers=>{:blah=>{}, :read_only=>{}})
22
+ @c = Class.new(Sequel::Model(@db[:items]))
23
+ @c.columns :id, :x, :y
24
+ @c.dataset.columns(:id, :x, :y)
25
+ @db.sqls
21
26
  end
22
27
 
23
28
  it "should use the :default server if the model doesn't have one already specified" do
24
- @c.db.should_receive(:execute).with("INSERT INTO items (x) VALUES (1)").and_return(10)
25
- @db2.should_receive(:execute).with('SELECT * FROM items WHERE (id = 10) LIMIT 1', :default).and_return(:x=>1, :id=>10)
26
- @c.new(:x=>1).save
29
+ @c.new(:x=>1).save.should == @c.load(:x=>1, :id=>10)
30
+ @db.sqls.should == ["INSERT INTO items (x) VALUES (1)", 'SELECT * FROM items WHERE (id = 10) LIMIT 1']
27
31
  end
28
32
 
29
33
  it "should use the model's server if the model has one already specified" do
30
34
  @c.dataset = @c.dataset.server(:blah)
31
- @c.db.should_receive(:execute).with("INSERT INTO items (x) VALUES (1)").and_return(10)
32
- @db2.should_receive(:execute).with('SELECT * FROM items WHERE (id = 10) LIMIT 1', :blah).and_return(:x=>1, :id=>10)
33
- @c.new(:x=>1).save
35
+ @c.new(:x=>1).save.should == @c.load(:x=>1, :id=>10)
36
+ @db.sqls.should == ["INSERT INTO items (x) VALUES (1) -- blah", 'SELECT * FROM items WHERE (id = 10) LIMIT 1 -- blah']
34
37
  end
35
38
  end
36
39
 
@@ -39,32 +42,37 @@ describe "Model#save" do
39
42
  @c = Class.new(Sequel::Model(:items)) do
40
43
  columns :id, :x, :y
41
44
  end
42
- @c.dataset.meta_def(:insert){|h| super(h); 1}
45
+ @c.instance_dataset.autoid = @c.dataset.autoid = 13
43
46
  MODEL_DB.reset
44
47
  end
45
48
 
46
49
  it "should insert a record for a new model instance" do
47
50
  o = @c.new(:x => 1)
48
51
  o.save
49
- MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)",
50
- "SELECT * FROM items WHERE (id = 1) LIMIT 1"]
52
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 13) LIMIT 1"]
51
53
  end
52
54
 
53
55
  it "should use dataset's insert_select method if present" do
54
- ds = @c.dataset = @c.dataset.clone
56
+ ds = @c.instance_dataset
57
+ ds._fetch = {:y=>2}
58
+ def ds.supports_insert_select?() true end
55
59
  def ds.insert_select(hash)
56
- execute("INSERT INTO items (y) VALUES (2)")
57
- {:y=>2}
60
+ execute("INSERT INTO items (y) VALUES (2) RETURNING *"){|r| return r}
58
61
  end
59
62
  o = @c.new(:x => 1)
60
63
  o.save
61
64
 
62
65
  o.values.should == {:y=>2}
63
- MODEL_DB.sqls.should == ["INSERT INTO items (y) VALUES (2)"]
66
+ MODEL_DB.sqls.should == ["INSERT INTO items (y) VALUES (2) RETURNING *"]
67
+ end
68
+
69
+ it "should not use dataset's insert_select method if specific columns are selected" do
70
+ ds = @c.dataset = @c.dataset.select(:y)
71
+ ds.should_not_receive(:insert_select)
72
+ @c.new(:x => 1).save
64
73
  end
65
74
 
66
75
  it "should use value returned by insert as the primary key and refresh the object" do
67
- @c.dataset.meta_def(:insert){|h| super(h); 13}
68
76
  o = @c.new(:x => 11)
69
77
  o.save
70
78
  MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (11)",
@@ -72,14 +80,12 @@ describe "Model#save" do
72
80
  end
73
81
 
74
82
  it "should allow you to skip refreshing by overridding _save_refresh" do
75
- @c.dataset.meta_def(:insert){|h| super(h); 13}
76
83
  @c.send(:define_method, :_save_refresh){}
77
84
  @c.create(:x => 11)
78
85
  MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (11)"]
79
86
  end
80
87
 
81
88
  it "should work correctly for inserting a record without a primary key" do
82
- @c.dataset.meta_def(:insert){|h| super(h); 13}
83
89
  @c.no_primary_key
84
90
  o = @c.new(:x => 11)
85
91
  o.save
@@ -87,15 +93,15 @@ describe "Model#save" do
87
93
  end
88
94
 
89
95
  it "should set the autoincrementing_primary_key value to the value returned by insert" do
90
- @c.dataset.meta_def(:insert){|h| super(h); 13}
91
96
  @c.unrestrict_primary_key
92
97
  @c.set_primary_key [:x, :y]
93
98
  o = @c.new(:x => 11)
94
99
  o.meta_def(:autoincrementing_primary_key){:y}
95
100
  o.save
96
- MODEL_DB.sqls.length.should == 2
97
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (11)"
98
- MODEL_DB.sqls.last.should =~ %r{SELECT \* FROM items WHERE \(\([xy] = 1[13]\) AND \([xy] = 1[13]\)\) LIMIT 1}
101
+ sqls = MODEL_DB.sqls
102
+ sqls.length.should == 2
103
+ sqls.first.should == "INSERT INTO items (x) VALUES (11)"
104
+ sqls.last.should =~ %r{SELECT \* FROM items WHERE \(\([xy] = 1[13]\) AND \([xy] = 1[13]\)\) LIMIT 1}
99
105
  end
100
106
 
101
107
  it "should update a record for an existing model instance" do
@@ -106,17 +112,18 @@ describe "Model#save" do
106
112
 
107
113
  it "should raise a NoExistingObject exception if the dataset update call doesn't return 1, unless require_modification is false" do
108
114
  o = @c.load(:id => 3, :x => 1)
109
- o.this.meta_def(:update){|*a| 0}
115
+ t = o.this
116
+ t.numrows = 0
110
117
  proc{o.save}.should raise_error(Sequel::NoExistingObject)
111
- o.this.meta_def(:update){|*a| 2}
118
+ t.numrows = 2
112
119
  proc{o.save}.should raise_error(Sequel::NoExistingObject)
113
- o.this.meta_def(:update){|*a| 1}
120
+ t.numrows = 1
114
121
  proc{o.save}.should_not raise_error
115
122
 
116
123
  o.require_modification = false
117
- o.this.meta_def(:update){|*a| 0}
124
+ t.numrows = 0
118
125
  proc{o.save}.should_not raise_error
119
- o.this.meta_def(:update){|*a| 2}
126
+ t.numrows = 2
120
127
  proc{o.save}.should_not raise_error
121
128
  end
122
129
 
@@ -185,22 +192,18 @@ describe "Model#save" do
185
192
  @c.use_transactions = true
186
193
  @c.load(:id => 3, :x => 1, :y => nil).save(:y)
187
194
  MODEL_DB.sqls.should == ["BEGIN", "UPDATE items SET y = NULL WHERE (id = 3)", "COMMIT"]
188
- MODEL_DB.reset
189
195
  @c.use_transactions = false
190
196
  @c.load(:id => 3, :x => 1, :y => nil).save(:y)
191
197
  MODEL_DB.sqls.should == ["UPDATE items SET y = NULL WHERE (id = 3)"]
192
- MODEL_DB.reset
193
198
  end
194
199
 
195
200
  it "should inherit Model's use_transactions setting" do
196
201
  @c.use_transactions = true
197
202
  Class.new(@c).load(:id => 3, :x => 1, :y => nil).save(:y)
198
203
  MODEL_DB.sqls.should == ["BEGIN", "UPDATE items SET y = NULL WHERE (id = 3)", "COMMIT"]
199
- MODEL_DB.reset
200
204
  @c.use_transactions = false
201
205
  Class.new(@c).load(:id => 3, :x => 1, :y => nil).save(:y)
202
206
  MODEL_DB.sqls.should == ["UPDATE items SET y = NULL WHERE (id = 3)"]
203
- MODEL_DB.reset
204
207
  end
205
208
 
206
209
  it "should use object's use_transactions setting" do
@@ -209,13 +212,11 @@ describe "Model#save" do
209
212
  @c.use_transactions = true
210
213
  o.save(:y)
211
214
  MODEL_DB.sqls.should == ["UPDATE items SET y = NULL WHERE (id = 3)"]
212
- MODEL_DB.reset
213
215
  o = @c.load(:id => 3, :x => 1, :y => nil)
214
216
  o.use_transactions = true
215
217
  @c.use_transactions = false
216
218
  o.save(:y)
217
219
  MODEL_DB.sqls.should == ["BEGIN", "UPDATE items SET y = NULL WHERE (id = 3)", "COMMIT"]
218
- MODEL_DB.reset
219
220
  end
220
221
 
221
222
  it "should use :transaction option if given" do
@@ -223,12 +224,10 @@ describe "Model#save" do
223
224
  o.use_transactions = true
224
225
  o.save(:y, :transaction=>false)
225
226
  MODEL_DB.sqls.should == ["UPDATE items SET y = NULL WHERE (id = 3)"]
226
- MODEL_DB.reset
227
227
  o = @c.load(:id => 3, :x => 1, :y => nil)
228
228
  o.use_transactions = false
229
229
  o.save(:y, :transaction=>true)
230
230
  MODEL_DB.sqls.should == ["BEGIN", "UPDATE items SET y = NULL WHERE (id = 3)", "COMMIT"]
231
- MODEL_DB.reset
232
231
  end
233
232
 
234
233
  it "should rollback if before_save returns false and raise_on_save_failure = true" do
@@ -240,7 +239,6 @@ describe "Model#save" do
240
239
  end
241
240
  proc { o.save(:y) }.should raise_error(Sequel::BeforeHookFailed)
242
241
  MODEL_DB.sqls.should == ["BEGIN", "ROLLBACK"]
243
- MODEL_DB.reset
244
242
  end
245
243
 
246
244
  it "should rollback if before_save returns false and :raise_on_failure option is true" do
@@ -252,7 +250,6 @@ describe "Model#save" do
252
250
  end
253
251
  proc { o.save(:y, :raise_on_failure => true) }.should raise_error(Sequel::BeforeHookFailed)
254
252
  MODEL_DB.sqls.should == ["BEGIN", "ROLLBACK"]
255
- MODEL_DB.reset
256
253
  end
257
254
 
258
255
  it "should not rollback outer transactions if before_save returns false and raise_on_save_failure = false" do
@@ -267,7 +264,6 @@ describe "Model#save" do
267
264
  MODEL_DB.run "BLAH"
268
265
  end
269
266
  MODEL_DB.sqls.should == ["BEGIN", "BLAH", "COMMIT"]
270
- MODEL_DB.reset
271
267
  end
272
268
 
273
269
  it "should rollback if before_save returns false and raise_on_save_failure = false" do
@@ -279,7 +275,6 @@ describe "Model#save" do
279
275
  end
280
276
  o.save(:y).should == nil
281
277
  MODEL_DB.sqls.should == ["BEGIN", "ROLLBACK"]
282
- MODEL_DB.reset
283
278
  end
284
279
 
285
280
  it "should not rollback if before_save throws Rollback and use_transactions = false" do
@@ -290,7 +285,118 @@ describe "Model#save" do
290
285
  end
291
286
  proc { o.save(:y) }.should raise_error(Sequel::Rollback)
292
287
  MODEL_DB.sqls.should == []
293
- MODEL_DB.reset
288
+ end
289
+
290
+ it "should support a :server option to set the server/shard to use" do
291
+ db = Sequel.mock(:fetch=>{:id=>13, :x=>1}, :autoid=>proc{13}, :numrows=>1, :servers=>{:s1=>{}})
292
+ c = Class.new(Sequel::Model(db[:items]))
293
+ c.columns :id, :x
294
+ db.sqls
295
+ o = c.new(:x => 1)
296
+ o.save(:server=>:s1)
297
+ db.sqls.should == ["INSERT INTO items (x) VALUES (1) -- s1", "SELECT * FROM items WHERE (id = 13) LIMIT 1 -- s1"]
298
+ o.save(:server=>:s1, :transaction=>true)
299
+ db.sqls.should == ["BEGIN -- s1", "UPDATE items SET x = 1 WHERE (id = 13) -- s1", 'COMMIT -- s1']
300
+ end
301
+ end
302
+
303
+ describe "Model#set_server" do
304
+ before do
305
+ @db = Sequel.mock(:fetch=>{:id=>13, :x=>1}, :autoid=>proc{13}, :numrows=>1, :servers=>{:s1=>{}})
306
+ @c = Class.new(Sequel::Model(@db[:items])) do
307
+ columns :id, :x
308
+ end
309
+ @db.sqls
310
+ end
311
+
312
+ it "should set the server to use when inserting" do
313
+ @c.new(:x => 1).set_server(:s1).save
314
+ @db.sqls.should == ["INSERT INTO items (x) VALUES (1) -- s1", "SELECT * FROM items WHERE (id = 13) LIMIT 1 -- s1"]
315
+ end
316
+
317
+ it "should set the server to use when updating" do
318
+ @c.load(:id=>13, :x => 1).set_server(:s1).save
319
+ @db.sqls.should == ["UPDATE items SET x = 1 WHERE (id = 13) -- s1"]
320
+ end
321
+
322
+ it "should set the server to use for transactions when saving" do
323
+ @c.load(:id=>13, :x => 1).set_server(:s1).save(:transaction=>true)
324
+ @db.sqls.should == ["BEGIN -- s1", "UPDATE items SET x = 1 WHERE (id = 13) -- s1", 'COMMIT -- s1']
325
+ end
326
+
327
+ it "should set the server to use when deleting" do
328
+ @c.load(:id=>13).set_server(:s1).delete
329
+ @db.sqls.should == ["DELETE FROM items WHERE (id = 13) -- s1"]
330
+ end
331
+
332
+ it "should set the server to use for transactions when destroying" do
333
+ o = @c.load(:id=>13).set_server(:s1)
334
+ o.use_transactions = true
335
+ o.destroy
336
+ @db.sqls.should == ["BEGIN -- s1", "DELETE FROM items WHERE (id = 13) -- s1", 'COMMIT -- s1']
337
+ end
338
+
339
+ it "should set the server on this if this is already loaded" do
340
+ o = @c.load(:id=>13, :x => 1)
341
+ o.this
342
+ o.set_server(:s1)
343
+ o.this.opts[:server].should == :s1
344
+ end
345
+
346
+ it "should set the server on this if this is not already loaded" do
347
+ @c.load(:id=>13, :x => 1).set_server(:s1).this.opts[:server].should == :s1
348
+ end
349
+ end
350
+
351
+ describe "Model#freeze" do
352
+ before do
353
+ class ::Album < Sequel::Model
354
+ columns :id
355
+ class B < Sequel::Model
356
+ columns :id, :album_id
357
+ end
358
+ end
359
+ @o = Album.load(:id=>1).freeze
360
+ MODEL_DB.sqls
361
+ end
362
+ after do
363
+ Object.send(:remove_const, :Album)
364
+ end
365
+
366
+ it "should freeze the object" do
367
+ @o.frozen?.should be_true
368
+ end
369
+
370
+ it "should freeze the object's values, associations, changed_columns, errors, and this" do
371
+ @o.values.frozen?.should be_true
372
+ @o.changed_columns.frozen?.should be_true
373
+ @o.errors.frozen?.should be_true
374
+ @o.this.frozen?.should be_true
375
+ end
376
+
377
+ it "should still have working class attr overriddable methods" do
378
+ Sequel::Model::BOOLEAN_SETTINGS.each{|m| @o.send(m) == Album.send(m)}
379
+ end
380
+
381
+ it "should have working new? method" do
382
+ @o.new?.should be_false
383
+ Album.new.freeze.new?.should be_true
384
+ end
385
+
386
+ it "should have working valid? method" do
387
+ @o.valid?.should be_true
388
+ o = Album.new
389
+ def o.validate() errors.add(:foo, '') end
390
+ o.freeze
391
+ o.valid?.should be_false
392
+ end
393
+
394
+ it "should raise an Error if trying to save/destroy/delete/refresh" do
395
+ proc{@o.save}.should raise_error(Sequel::Error)
396
+ proc{@o.destroy}.should raise_error(Sequel::Error)
397
+ proc{@o.delete}.should raise_error(Sequel::Error)
398
+ proc{@o.refresh}.should raise_error(Sequel::Error)
399
+ @o.db.sqls.should == []
294
400
  end
295
401
  end
296
402
 
@@ -299,7 +405,6 @@ describe "Model#marshallable" do
299
405
  class ::Album < Sequel::Model
300
406
  columns :id, :x
301
407
  end
302
- Album.dataset.meta_def(:insert){|h| super(h); 1}
303
408
  end
304
409
  after do
305
410
  Object.send(:remove_const, :Album)
@@ -381,7 +486,6 @@ describe "Model#modified[!?]" do
381
486
  end
382
487
 
383
488
  describe "Model#save_changes" do
384
-
385
489
  before do
386
490
  @c = Class.new(Sequel::Model(:items)) do
387
491
  unrestrict_primary_key
@@ -426,15 +530,14 @@ describe "Model#save_changes" do
426
530
  MODEL_DB.sqls.should == ["UPDATE items SET x = 2 WHERE (id = 3)"]
427
531
  o.save_changes
428
532
  o.save_changes
429
- MODEL_DB.sqls.should == ["UPDATE items SET x = 2 WHERE (id = 3)"]
430
- MODEL_DB.reset
533
+ MODEL_DB.sqls.should == []
431
534
 
432
535
  o.y = 4
433
536
  o.save_changes
434
537
  MODEL_DB.sqls.should == ["UPDATE items SET y = 4 WHERE (id = 3)"]
435
538
  o.save_changes
436
539
  o.save_changes
437
- MODEL_DB.sqls.should == ["UPDATE items SET y = 4 WHERE (id = 3)"]
540
+ MODEL_DB.sqls.should == []
438
541
  end
439
542
 
440
543
  it "should not consider columns changed if the values did not change" do
@@ -446,7 +549,6 @@ describe "Model#save_changes" do
446
549
  o.x = 3
447
550
  o.save_changes
448
551
  MODEL_DB.sqls.should == ["UPDATE items SET x = 3 WHERE (id = 3)"]
449
- MODEL_DB.reset
450
552
 
451
553
  o[:y] = nil
452
554
  o.save_changes
@@ -472,13 +574,11 @@ describe "Model#save_changes" do
472
574
  o.x = 2
473
575
  o.save_changes
474
576
  MODEL_DB.sqls.should == ["UPDATE items SET x = 3 WHERE (id = 3)"]
475
- MODEL_DB.reset
476
577
  o.save_changes
477
578
  MODEL_DB.sqls.should == []
478
579
  o.x = 4
479
580
  o.save_changes
480
581
  MODEL_DB.sqls.should == ["UPDATE items SET x = 5 WHERE (id = 3)"]
481
- MODEL_DB.reset
482
582
  end
483
583
 
484
584
  it "should update columns changed in a before_save hook" do
@@ -489,25 +589,21 @@ describe "Model#save_changes" do
489
589
  o.x = 2
490
590
  o.save_changes
491
591
  MODEL_DB.sqls.should == ["UPDATE items SET x = 3 WHERE (id = 3)"]
492
- MODEL_DB.reset
493
592
  o.save_changes
494
593
  MODEL_DB.sqls.should == []
495
594
  o.x = 4
496
595
  o.save_changes
497
596
  MODEL_DB.sqls.should == ["UPDATE items SET x = 5 WHERE (id = 3)"]
498
- MODEL_DB.reset
499
597
  end
500
598
  end
501
599
 
502
600
  describe "Model#new?" do
503
-
504
- before(:each) do
505
- MODEL_DB.reset
506
-
601
+ before do
507
602
  @c = Class.new(Sequel::Model(:items)) do
508
603
  unrestrict_primary_key
509
604
  columns :x
510
605
  end
606
+ MODEL_DB.reset
511
607
  end
512
608
 
513
609
  it "should be true for a new instance" do
@@ -523,74 +619,65 @@ describe "Model#new?" do
523
619
  end
524
620
 
525
621
  describe Sequel::Model, "w/ primary key" do
526
-
527
622
  it "should default to ':id'" do
528
623
  model_a = Class.new Sequel::Model
529
- model_a.primary_key.should be_equal(:id)
624
+ model_a.primary_key.should == :id
530
625
  end
531
626
 
532
627
  it "should be changed through 'set_primary_key'" do
533
- model_a = Class.new(Sequel::Model) { set_primary_key :a }
534
- model_a.primary_key.should be_equal(:a)
628
+ model_a = Class.new(Sequel::Model){ set_primary_key :a }
629
+ model_a.primary_key.should == :a
535
630
  end
536
631
 
537
632
  it "should support multi argument composite keys" do
538
- model_a = Class.new(Sequel::Model) { set_primary_key :a, :b }
539
- model_a.primary_key.should be_eql([:a, :b])
633
+ model_a = Class.new(Sequel::Model){ set_primary_key :a, :b }
634
+ model_a.primary_key.should == [:a, :b]
540
635
  end
541
636
 
542
637
  it "should accept single argument composite keys" do
543
- model_a = Class.new(Sequel::Model) { set_primary_key [:a, :b] }
544
- model_a.primary_key.should be_eql([:a, :b])
638
+ model_a = Class.new(Sequel::Model){ set_primary_key [:a, :b] }
639
+ model_a.primary_key.should == [:a, :b]
545
640
  end
546
-
547
641
  end
548
642
 
549
643
  describe Sequel::Model, "w/o primary key" do
550
644
  it "should return nil for primary key" do
551
- Class.new(Sequel::Model) { no_primary_key }.primary_key.should be_nil
645
+ Class.new(Sequel::Model){no_primary_key}.primary_key.should be_nil
552
646
  end
553
647
 
554
648
  it "should raise a Sequel::Error on 'this'" do
555
- instance = Class.new(Sequel::Model) { no_primary_key }.new
556
- proc { instance.this }.should raise_error(Sequel::Error)
649
+ instance = Class.new(Sequel::Model){no_primary_key}.new
650
+ proc{instance.this}.should raise_error(Sequel::Error)
557
651
  end
558
652
  end
559
653
 
560
654
  describe Sequel::Model, "with this" do
561
-
562
- before { @example = Class.new Sequel::Model(:examples); @example.columns :id, :a, :x, :y }
655
+ before do
656
+ @example = Class.new(Sequel::Model(:examples))
657
+ @example.columns :id, :a, :x, :y
658
+ end
563
659
 
564
660
  it "should return a dataset identifying the record" do
565
- instance = @example.load :id => 3
566
- instance.this.sql.should be_eql("SELECT * FROM examples WHERE (id = 3) LIMIT 1")
661
+ instance = @example.load(:id => 3)
662
+ instance.this.sql.should == "SELECT * FROM examples WHERE (id = 3) LIMIT 1"
567
663
  end
568
664
 
569
665
  it "should support arbitary primary keys" do
570
666
  @example.set_primary_key :a
571
667
 
572
- instance = @example.load :a => 3
573
- instance.this.sql.should be_eql("SELECT * FROM examples WHERE (a = 3) LIMIT 1")
668
+ instance = @example.load(:a => 3)
669
+ instance.this.sql.should == "SELECT * FROM examples WHERE (a = 3) LIMIT 1"
574
670
  end
575
671
 
576
672
  it "should support composite primary keys" do
577
673
  @example.set_primary_key :x, :y
578
- instance = @example.load :x => 4, :y => 5
579
-
580
- parts = [
581
- 'SELECT * FROM examples WHERE %s LIMIT 1',
582
- '((x = 4) AND (y = 5))',
583
- '((y = 5) AND (x = 4))'
584
- ].map { |expr| Regexp.escape expr }
585
- regexp = Regexp.new parts.first % "(?:#{parts[1]}|#{parts[2]})"
586
-
587
- instance.this.sql.should match(regexp)
674
+ instance = @example.load(:x => 4, :y => 5)
675
+ instance.this.sql.should =~ /SELECT \* FROM examples WHERE \(\([xy] = [45]\) AND \([xy] = [45]\)\) LIMIT 1/
588
676
  end
589
-
590
677
  end
591
678
 
592
679
  describe "Model#pk" do
593
- before(:each) do
680
+ before do
594
681
  @m = Class.new(Sequel::Model)
595
682
  @m.columns :id, :x, :y
596
683
  end
@@ -624,7 +711,7 @@ describe "Model#pk" do
624
711
  end
625
712
 
626
713
  describe "Model#pk_hash" do
627
- before(:each) do
714
+ before do
628
715
  @m = Class.new(Sequel::Model)
629
716
  @m.columns :id, :x, :y
630
717
  end
@@ -659,16 +746,14 @@ end
659
746
 
660
747
  describe Sequel::Model, "#set" do
661
748
  before do
662
- MODEL_DB.reset
663
-
664
749
  @c = Class.new(Sequel::Model(:items)) do
665
750
  set_primary_key :id
666
751
  columns :x, :y, :id
667
752
  end
668
753
  @c.strict_param_setting = false
669
- @c.instance_variable_set(:@columns, true)
670
754
  @o1 = @c.new
671
755
  @o2 = @c.load(:id => 5)
756
+ MODEL_DB.reset
672
757
  end
673
758
 
674
759
  it "should filter the given params using the model columns" do
@@ -716,6 +801,29 @@ describe Sequel::Model, "#set" do
716
801
  MODEL_DB.sqls.should == []
717
802
  end
718
803
 
804
+ it "should raise error if strict_param_setting is true and method does not exist" do
805
+ @o1.strict_param_setting = true
806
+ proc{@o1.set('foo' => 1)}.should raise_error(Sequel::Error)
807
+ end
808
+
809
+ it "should raise error if strict_param_setting is true and column is a primary key" do
810
+ @o1.strict_param_setting = true
811
+ proc{@o1.set('id' => 1)}.should raise_error(Sequel::Error)
812
+ end
813
+
814
+ it "should raise error if strict_param_setting is true and column is restricted" do
815
+ @o1.strict_param_setting = true
816
+ @c.set_restricted_columns :x
817
+ proc{@o1.set('x' => 1)}.should raise_error(Sequel::Error)
818
+ end
819
+
820
+ it "should not create a symbol if strict_param_setting is true and string is given" do
821
+ @o1.strict_param_setting = true
822
+ l = Symbol.all_symbols.length
823
+ proc{@o1.set('sadojafdso' => 1)}.should raise_error(Sequel::Error)
824
+ Symbol.all_symbols.length.should == l
825
+ end
826
+
719
827
  it "#set should correctly handle cases where an instance method is added to the class" do
720
828
  @o1.set(:x => 1)
721
829
  @o1.values.should == {:x => 1}
@@ -739,51 +847,74 @@ describe Sequel::Model, "#set" do
739
847
  @o1.set(:x => 2, :z => 3)
740
848
  @o1.values.should == {:x => 2, :z=>3}
741
849
  end
850
+
851
+ it "#set should correctly handle cases where a module with a setter method is included in the class" do
852
+ @o1.set(:x => 1)
853
+ @o1.values.should == {:x => 1}
854
+
855
+ @c.send(:include, Module.new do
856
+ def z=(v)
857
+ self[:z] = v
858
+ end
859
+ end)
860
+ @o1.set(:x => 2, :z => 3)
861
+ @o1.values.should == {:x => 2, :z=>3}
862
+ end
863
+
864
+ it "#set should correctly handle cases where the object extends a module with a setter method " do
865
+ @o1.set(:x => 1)
866
+ @o1.values.should == {:x => 1}
867
+
868
+ @o1.extend(Module.new do
869
+ def z=(v)
870
+ self[:z] = v
871
+ end
872
+ end)
873
+ @o1.set(:x => 2, :z => 3)
874
+ @o1.values.should == {:x => 2, :z=>3}
875
+ end
742
876
  end
743
877
 
744
878
  describe Sequel::Model, "#update" do
745
879
  before do
746
- MODEL_DB.reset
747
-
748
880
  @c = Class.new(Sequel::Model(:items)) do
749
881
  set_primary_key :id
750
882
  columns :x, :y, :id
751
883
  end
752
884
  @c.strict_param_setting = false
753
- @c.instance_variable_set(:@columns, true)
754
885
  @o1 = @c.new
755
886
  @o2 = @c.load(:id => 5)
887
+ MODEL_DB.reset
756
888
  end
757
889
 
758
890
  it "should filter the given params using the model columns" do
759
891
  @o1.update(:x => 1, :z => 2)
760
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
892
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
761
893
 
762
894
  MODEL_DB.reset
763
895
  @o2.update(:y => 1, :abc => 2)
764
- MODEL_DB.sqls.first.should == "UPDATE items SET y = 1 WHERE (id = 5)"
896
+ MODEL_DB.sqls.should == ["UPDATE items SET y = 1 WHERE (id = 5)"]
765
897
  end
766
898
 
767
899
  it "should support virtual attributes" do
768
900
  @c.send(:define_method, :blah=){|v| self.x = v}
769
901
  @o1.update(:blah => 333)
770
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (333)"
902
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (333)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
771
903
  end
772
904
 
773
905
  it "should not modify the primary key" do
774
906
  @o1.update(:x => 1, :id => 2)
775
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
907
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
776
908
  MODEL_DB.reset
777
909
  @o2.update('y'=> 1, 'id'=> 2)
778
910
  @o2.values.should == {:y => 1, :id=> 5}
779
- MODEL_DB.sqls.first.should == "UPDATE items SET y = 1 WHERE (id = 5)"
911
+ MODEL_DB.sqls.should == ["UPDATE items SET y = 1 WHERE (id = 5)"]
780
912
  end
781
913
  end
782
914
 
783
915
  describe Sequel::Model, "#set_fields" do
784
916
  before do
785
- @c = Class.new(Sequel::Model(:items))
786
- @c.class_eval do
917
+ @c = Class.new(Sequel::Model(:items)) do
787
918
  set_primary_key :id
788
919
  columns :x, :y, :z, :id
789
920
  end
@@ -799,15 +930,50 @@ describe Sequel::Model, "#set_fields" do
799
930
  @o1.values.should == {:x => 9, :y => 8, :id=>7}
800
931
  MODEL_DB.sqls.should == []
801
932
  end
933
+
934
+ it "should lookup into the hash without checking if the entry exists" do
935
+ @o1.set_fields({:x => 1}, [:x, :y])
936
+ @o1.values.should == {:x => 1, :y => nil}
937
+ @o1.set_fields(Hash.new(2), [:x, :y])
938
+ @o1.values.should == {:x => 2, :y => 2}
939
+ end
940
+
941
+ it "should skip missing fields if :missing=>:skip option is used" do
942
+ @o1.set_fields({:x => 3}, [:x, :y], :missing=>:skip)
943
+ @o1.values.should == {:x => 3}
944
+ @o1.set_fields({"x" => 4}, [:x, :y], :missing=>:skip)
945
+ @o1.values.should == {:x => 4}
946
+ @o1.set_fields(Hash.new(2).merge(:x=>2), [:x, :y], :missing=>:skip)
947
+ @o1.values.should == {:x => 2}
948
+ @o1.set_fields({:x => 1, :y => 2, :z=>3, :id=>4}, [:x, :y], :missing=>:skip)
949
+ @o1.values.should == {:x => 1, :y => 2}
950
+ end
951
+
952
+ it "should raise for missing fields if :missing=>:raise option is used" do
953
+ proc{@o1.set_fields({:x => 1}, [:x, :y], :missing=>:raise)}.should raise_error(Sequel::Error)
954
+ proc{@o1.set_fields(Hash.new(2).merge(:x=>2), [:x, :y], :missing=>:raise)}.should raise_error(Sequel::Error)
955
+ proc{@o1.set_fields({"x" => 1}, [:x, :y], :missing=>:raise)}.should raise_error(Sequel::Error)
956
+ @o1.set_fields({:x => 5, "y"=>2}, [:x, :y], :missing=>:raise)
957
+ @o1.values.should == {:x => 5, :y => 2}
958
+ @o1.set_fields({:x => 1, :y => 3, :z=>3, :id=>4}, [:x, :y], :missing=>:raise)
959
+ @o1.values.should == {:x => 1, :y => 3}
960
+ end
961
+
962
+ it "should use default behavior for an unrecognized :missing option" do
963
+ @o1.set_fields({:x => 1, :y => 2, :z=>3, :id=>4}, [:x, :y], :missing=>:foo)
964
+ @o1.values.should == {:x => 1, :y => 2}
965
+ @o1.set_fields({:x => 9, :y => 8, :z=>6, :id=>7}, [:x, :y, :id], :missing=>:foo)
966
+ @o1.values.should == {:x => 9, :y => 8, :id=>7}
967
+ MODEL_DB.sqls.should == []
968
+ end
969
+
802
970
  end
803
971
 
804
972
  describe Sequel::Model, "#update_fields" do
805
973
  before do
806
- @c = Class.new(Sequel::Model(:items))
807
- @c.class_eval do
974
+ @c = Class.new(Sequel::Model(:items)) do
808
975
  set_primary_key :id
809
976
  columns :x, :y, :z, :id
810
- def _refresh(ds); end
811
977
  end
812
978
  @c.strict_param_setting = true
813
979
  @o1 = @c.load(:id=>1)
@@ -817,21 +983,28 @@ describe Sequel::Model, "#update_fields" do
817
983
  it "should set only the given fields, and then save the changes to the record" do
818
984
  @o1.update_fields({:x => 1, :y => 2, :z=>3, :id=>4}, [:x, :y])
819
985
  @o1.values.should == {:x => 1, :y => 2, :id=>1}
820
- MODEL_DB.sqls.first.should =~ /UPDATE items SET [xy] = [12], [xy] = [12] WHERE \(id = 1\)/
821
- MODEL_DB.sqls.length.should == 1
822
- MODEL_DB.reset
986
+ sqls = MODEL_DB.sqls
987
+ sqls.pop.should =~ /UPDATE items SET [xy] = [12], [xy] = [12] WHERE \(id = 1\)/
988
+ sqls.should == []
823
989
 
824
990
  @o1.update_fields({:x => 1, :y => 5, :z=>6, :id=>7}, [:x, :y])
825
991
  @o1.values.should == {:x => 1, :y => 5, :id=>1}
826
992
  MODEL_DB.sqls.should == ["UPDATE items SET y = 5 WHERE (id = 1)"]
827
- MODEL_DB.reset
993
+ end
994
+
995
+ it "should support :missing=>:skip option" do
996
+ @o1.update_fields({:x => 1, :z=>3, :id=>4}, [:x, :y], :missing=>:skip)
997
+ @o1.values.should == {:x => 1, :id=>1}
998
+ MODEL_DB.sqls.should == ["UPDATE items SET x = 1 WHERE (id = 1)"]
999
+ end
1000
+
1001
+ it "should support :missing=>:raise option" do
1002
+ proc{@o1.update_fields({:x => 1}, [:x, :y], :missing=>:raise)}.should raise_error(Sequel::Error)
828
1003
  end
829
1004
  end
830
1005
 
831
1006
  describe Sequel::Model, "#(set|update)_(all|except|only)" do
832
1007
  before do
833
- MODEL_DB.reset
834
-
835
1008
  @c = Class.new(Sequel::Model(:items)) do
836
1009
  set_primary_key :id
837
1010
  columns :x, :y, :z, :id
@@ -839,8 +1012,8 @@ describe Sequel::Model, "#(set|update)_(all|except|only)" do
839
1012
  set_restricted_columns :y
840
1013
  end
841
1014
  @c.strict_param_setting = false
842
- @c.instance_variable_set(:@columns, true)
843
1015
  @o1 = @c.new
1016
+ MODEL_DB.reset
844
1017
  end
845
1018
 
846
1019
  it "should raise errors if not all hash fields can be set and strict_param_setting is true" do
@@ -884,40 +1057,63 @@ describe Sequel::Model, "#(set|update)_(all|except|only)" do
884
1057
 
885
1058
  it "#update_all should update all attributes" do
886
1059
  @c.new.update_all(:x => 1, :id=>4)
887
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
888
- MODEL_DB.reset
1060
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
889
1061
  @c.new.update_all(:y => 1, :id=>4)
890
- MODEL_DB.sqls.first.should == "INSERT INTO items (y) VALUES (1)"
891
- MODEL_DB.reset
1062
+ MODEL_DB.sqls.should == ["INSERT INTO items (y) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
892
1063
  @c.new.update_all(:z => 1, :id=>4)
893
- MODEL_DB.sqls.first.should == "INSERT INTO items (z) VALUES (1)"
1064
+ MODEL_DB.sqls.should == ["INSERT INTO items (z) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
894
1065
  end
895
1066
 
896
1067
  it "#update_only should only update given attributes" do
897
1068
  @o1.update_only({:x => 1, :y => 2, :z=>3, :id=>4}, [:x])
898
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
899
- MODEL_DB.reset
1069
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
900
1070
  @c.new.update_only({:x => 1, :y => 2, :z=>3, :id=>4}, :x)
901
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
1071
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
902
1072
  end
903
1073
 
904
1074
  it "#update_except should not update given attributes" do
905
1075
  @o1.update_except({:x => 1, :y => 2, :z=>3, :id=>4}, [:y, :z])
906
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
907
- MODEL_DB.reset
1076
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
908
1077
  @c.new.update_except({:x => 1, :y => 2, :z=>3, :id=>4}, :y, :z)
909
- MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
1078
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
910
1079
  end
911
1080
  end
912
1081
 
913
- describe Sequel::Model, "#destroy" do
1082
+ describe Sequel::Model, "#destroy with filtered dataset" do
914
1083
  before do
1084
+ @model = Class.new(Sequel::Model(MODEL_DB[:items].where(:a=>1)))
1085
+ @model.columns :id, :a
1086
+ @instance = @model.load(:id => 1234)
915
1087
  MODEL_DB.reset
1088
+ end
1089
+
1090
+ it "should raise a NoExistingObject exception if the dataset delete call doesn't return 1" do
1091
+ @instance.this.meta_def(:execute_dui){|*a| 0}
1092
+ proc{@instance.delete}.should raise_error(Sequel::NoExistingObject)
1093
+ @instance.this.meta_def(:execute_dui){|*a| 2}
1094
+ proc{@instance.delete}.should raise_error(Sequel::NoExistingObject)
1095
+ @instance.this.meta_def(:execute_dui){|*a| 1}
1096
+ proc{@instance.delete}.should_not raise_error
1097
+
1098
+ @instance.require_modification = false
1099
+ @instance.this.meta_def(:execute_dui){|*a| 0}
1100
+ proc{@instance.delete}.should_not raise_error
1101
+ @instance.this.meta_def(:execute_dui){|*a| 2}
1102
+ proc{@instance.delete}.should_not raise_error
1103
+ end
1104
+
1105
+ it "should include WHERE clause when deleting" do
1106
+ @instance.destroy
1107
+ MODEL_DB.sqls.should == ["DELETE FROM items WHERE ((a = 1) AND (id = 1234))"]
1108
+ end
1109
+ end
1110
+
1111
+ describe Sequel::Model, "#destroy" do
1112
+ before do
916
1113
  @model = Class.new(Sequel::Model(:items))
917
1114
  @model.columns :id
918
- @model.dataset.meta_def(:delete){MODEL_DB.execute delete_sql;1}
919
-
920
1115
  @instance = @model.load(:id => 1234)
1116
+ MODEL_DB.reset
921
1117
  end
922
1118
 
923
1119
  it "should return self" do
@@ -926,65 +1122,56 @@ describe Sequel::Model, "#destroy" do
926
1122
  end
927
1123
 
928
1124
  it "should raise a NoExistingObject exception if the dataset delete call doesn't return 1" do
929
- @instance.this.meta_def(:delete){|*a| 0}
1125
+ @model.dataset.meta_def(:execute_dui){|*a| 0}
930
1126
  proc{@instance.delete}.should raise_error(Sequel::NoExistingObject)
931
- @instance.this.meta_def(:delete){|*a| 2}
1127
+ @model.dataset.meta_def(:execute_dui){|*a| 2}
932
1128
  proc{@instance.delete}.should raise_error(Sequel::NoExistingObject)
933
- @instance.this.meta_def(:delete){|*a| 1}
1129
+ @model.dataset.meta_def(:execute_dui){|*a| 1}
934
1130
  proc{@instance.delete}.should_not raise_error
935
1131
 
936
1132
  @instance.require_modification = false
937
- @instance.this.meta_def(:delete){|*a| 0}
1133
+ @model.dataset.meta_def(:execute_dui){|*a| 0}
938
1134
  proc{@instance.delete}.should_not raise_error
939
- @instance.this.meta_def(:delete){|*a| 2}
1135
+ @model.dataset.meta_def(:execute_dui){|*a| 2}
940
1136
  proc{@instance.delete}.should_not raise_error
941
1137
  end
942
1138
 
943
1139
  it "should run within a transaction if use_transactions is true" do
944
1140
  @instance.use_transactions = true
945
- @model.db.should_receive(:transaction)
946
1141
  @instance.destroy
1142
+ MODEL_DB.sqls.should == ["BEGIN", "DELETE FROM items WHERE id = 1234", "COMMIT"]
947
1143
  end
948
1144
 
949
1145
  it "should not run within a transaction if use_transactions is false" do
950
1146
  @instance.use_transactions = false
951
- @model.db.should_not_receive(:transaction)
952
1147
  @instance.destroy
1148
+ MODEL_DB.sqls.should == ["DELETE FROM items WHERE id = 1234"]
953
1149
  end
954
1150
 
955
1151
  it "should run within a transaction if :transaction option is true" do
956
1152
  @instance.use_transactions = false
957
- @model.db.should_receive(:transaction)
958
1153
  @instance.destroy(:transaction => true)
1154
+ MODEL_DB.sqls.should == ["BEGIN", "DELETE FROM items WHERE id = 1234", "COMMIT"]
959
1155
  end
960
1156
 
961
1157
  it "should not run within a transaction if :transaction option is false" do
962
1158
  @instance.use_transactions = true
963
- @model.db.should_not_receive(:transaction)
964
1159
  @instance.destroy(:transaction => false)
1160
+ MODEL_DB.sqls.should == ["DELETE FROM items WHERE id = 1234"]
965
1161
  end
966
1162
 
967
1163
  it "should run before_destroy and after_destroy hooks" do
968
1164
  @model.send(:define_method, :before_destroy){MODEL_DB.execute('before blah')}
969
1165
  @model.send(:define_method, :after_destroy){MODEL_DB.execute('after blah')}
970
1166
  @instance.destroy
971
-
972
- MODEL_DB.sqls.should == [
973
- "before blah",
974
- "DELETE FROM items WHERE (id = 1234)",
975
- "after blah"
976
- ]
1167
+ MODEL_DB.sqls.should == ["before blah", "DELETE FROM items WHERE id = 1234", "after blah"]
977
1168
  end
978
1169
  end
979
1170
 
980
1171
  describe Sequel::Model, "#exists?" do
981
- before(:each) do
1172
+ before do
982
1173
  @model = Class.new(Sequel::Model(:items))
983
- @ds = @model.dataset
984
- def @ds.fetch_rows(sql)
985
- db.execute(sql)
986
- yield(:x=>1) if sql =~ /id = 1/
987
- end
1174
+ @model.instance_dataset._fetch = @model.dataset._fetch = proc{|sql| {:x=>1} if sql =~ /id = 1/}
988
1175
  MODEL_DB.reset
989
1176
  end
990
1177
 
@@ -997,6 +1184,11 @@ describe Sequel::Model, "#exists?" do
997
1184
  @model.load(:id=>2).exists?.should be_false
998
1185
  MODEL_DB.sqls.should == ['SELECT 1 FROM items WHERE (id = 2) LIMIT 1']
999
1186
  end
1187
+
1188
+ it "should return false without issuing a query if the model object is new" do
1189
+ @model.new.exists?.should be_false
1190
+ MODEL_DB.sqls.should == []
1191
+ end
1000
1192
  end
1001
1193
 
1002
1194
  describe Sequel::Model, "#each" do
@@ -1008,7 +1200,7 @@ describe Sequel::Model, "#each" do
1008
1200
 
1009
1201
  specify "should iterate over the values" do
1010
1202
  h = {}
1011
- @m.each {|k, v| h[k] = v}
1203
+ @m.each{|k, v| h[k] = v}
1012
1204
  h.should == {:a => 1, :b => 2, :id => 4444}
1013
1205
  end
1014
1206
  end
@@ -1021,11 +1213,8 @@ describe Sequel::Model, "#keys" do
1021
1213
  end
1022
1214
 
1023
1215
  specify "should return the value keys" do
1024
- @m.keys.size.should == 3
1025
- @m.keys.should include(:a, :b, :id)
1026
-
1027
- @m = @model.new()
1028
- @m.keys.should == []
1216
+ @m.keys.sort_by{|k| k.to_s}.should == [:a, :b, :id]
1217
+ @model.new.keys.should == []
1029
1218
  end
1030
1219
  end
1031
1220
 
@@ -1094,13 +1283,10 @@ describe Sequel::Model, "#hash" do
1094
1283
  y = Class.new(Sequel::Model)
1095
1284
  y.columns :id, :x
1096
1285
  a = z.load(:id => 1, :x => 3)
1097
- b = z.load(:id => 1, :x => 4)
1098
- c = z.load(:id => 2, :x => 3)
1099
- d = y.load(:id => 1, :x => 3)
1100
1286
 
1101
- a.hash.should == b.hash
1102
- a.hash.should_not == c.hash
1103
- a.hash.should_not == d.hash
1287
+ a.hash.should == z.load(:id => 1, :x => 4).hash
1288
+ a.hash.should_not == z.load(:id => 2, :x => 3).hash
1289
+ a.hash.should_not == y.load(:id => 1, :x => 3).hash
1104
1290
  end
1105
1291
 
1106
1292
  specify "should be the same only for objects with the same class and values if the pk is nil" do
@@ -1109,14 +1295,71 @@ describe Sequel::Model, "#hash" do
1109
1295
  y = Class.new(Sequel::Model)
1110
1296
  y.columns :id, :x
1111
1297
  a = z.new(:x => 3)
1112
- b = z.new(:x => 4)
1113
- c = z.new(:x => 3)
1114
- d = y.new(:x => 3)
1115
1298
 
1116
- a.hash.should_not == b.hash
1117
- a.hash.should == c.hash
1118
- a.hash.should_not == d.hash
1299
+ a.hash.should_not == z.new(:x => 4).hash
1300
+ a.hash.should == z.new(:x => 3).hash
1301
+ a.hash.should_not == y.new(:x => 3).hash
1302
+ end
1303
+
1304
+ specify "should be the same only for objects with the same class and pk if pk is composite and all values are non-NULL" do
1305
+ z = Class.new(Sequel::Model)
1306
+ z.columns :id, :id2, :x
1307
+ z.set_primary_key(:id, :id2)
1308
+ y = Class.new(Sequel::Model)
1309
+ y.columns :id, :id2, :x
1310
+ y.set_primary_key(:id, :id2)
1311
+ a = z.load(:id => 1, :id2=>2, :x => 3)
1312
+
1313
+ a.hash.should == z.load(:id => 1, :id2=>2, :x => 4).hash
1314
+ a.hash.should_not == z.load(:id => 2, :id2=>1, :x => 3).hash
1315
+ a.hash.should_not == y.load(:id => 1, :id2=>1, :x => 3).hash
1316
+ end
1317
+
1318
+ specify "should be the same only for objects with the same class and value if pk is composite and one values is NULL" do
1319
+ z = Class.new(Sequel::Model)
1320
+ z.columns :id, :id2, :x
1321
+ z.set_primary_key(:id, :id2)
1322
+ y = Class.new(Sequel::Model)
1323
+ y.columns :id, :id2, :x
1324
+ y.set_primary_key(:id, :id2)
1325
+
1326
+ a = z.load(:id => 1, :id2 => nil, :x => 3)
1327
+ a.hash.should == z.load(:id => 1, :id2=>nil, :x => 3).hash
1328
+ a.hash.should_not == z.load(:id => 1, :id2=>nil, :x => 4).hash
1329
+ a.hash.should_not == y.load(:id => 1, :id2=>nil, :x => 3).hash
1330
+
1331
+ a = z.load(:id =>nil, :id2 => nil, :x => 3)
1332
+ a.hash.should == z.load(:id => nil, :id2=>nil, :x => 3).hash
1333
+ a.hash.should_not == z.load(:id => nil, :id2=>nil, :x => 4).hash
1334
+ a.hash.should_not == y.load(:id => nil, :id2=>nil, :x => 3).hash
1335
+
1336
+ a = z.load(:id => 1, :x => 3)
1337
+ a.hash.should == z.load(:id => 1, :x => 3).hash
1338
+ a.hash.should_not == z.load(:id => 1, :id2=>nil, :x => 3).hash
1339
+ a.hash.should_not == z.load(:id => 1, :x => 4).hash
1340
+ a.hash.should_not == y.load(:id => 1, :x => 3).hash
1341
+
1342
+ a = z.load(:x => 3)
1343
+ a.hash.should == z.load(:x => 3).hash
1344
+ a.hash.should_not == z.load(:id => nil, :id2=>nil, :x => 3).hash
1345
+ a.hash.should_not == z.load(:x => 4).hash
1346
+ a.hash.should_not == y.load(:x => 3).hash
1347
+ end
1348
+
1349
+ specify "should be the same only for objects with the same class and values if the no primary key" do
1350
+ z = Class.new(Sequel::Model)
1351
+ z.columns :id, :x
1352
+ z.no_primary_key
1353
+ y = Class.new(Sequel::Model)
1354
+ y.columns :id, :x
1355
+ y.no_primary_key
1356
+ a = z.new(:x => 3)
1357
+
1358
+ a.hash.should_not == z.new(:x => 4).hash
1359
+ a.hash.should == z.new(:x => 3).hash
1360
+ a.hash.should_not == y.new(:x => 3).hash
1119
1361
  end
1362
+
1120
1363
  end
1121
1364
 
1122
1365
  describe Sequel::Model, "#initialize" do
@@ -1161,10 +1404,32 @@ describe Sequel::Model, "#initialize" do
1161
1404
  m.values.should == {:x => 2}
1162
1405
  end
1163
1406
  end
1407
+
1408
+ describe Sequel::Model, "#initialize_set" do
1409
+ before do
1410
+ @c = Class.new(Sequel::Model){columns :id, :x, :y}
1411
+ end
1164
1412
 
1165
- describe Sequel::Model, ".create" do
1413
+ specify "should be called by initialize to set the column values" do
1414
+ @c.send(:define_method, :initialize_set){|h| set(:y => 3)}
1415
+ @c.new(:x => 2).values.should == {:y => 3}
1416
+ end
1417
+
1418
+ specify "should be called with the hash given to initialize " do
1419
+ x = nil
1420
+ @c.send(:define_method, :initialize_set){|y| x = y}
1421
+ @c.new(:x => 2)
1422
+ x.should == {:x => 2}
1423
+ end
1166
1424
 
1167
- before(:each) do
1425
+ specify "should not cause columns modified by the method to be considered as changed" do
1426
+ @c.send(:define_method, :initialize_set){|h| set(:y => 3)}
1427
+ @c.new(:x => 2).changed_columns.should == []
1428
+ end
1429
+ end
1430
+
1431
+ describe Sequel::Model, ".create" do
1432
+ before do
1168
1433
  MODEL_DB.reset
1169
1434
  @c = Class.new(Sequel::Model(:items)) do
1170
1435
  unrestrict_primary_key
@@ -1175,13 +1440,13 @@ describe Sequel::Model, ".create" do
1175
1440
  it "should be able to create rows in the associated table" do
1176
1441
  o = @c.create(:x => 1)
1177
1442
  o.class.should == @c
1178
- MODEL_DB.sqls.should == ['INSERT INTO items (x) VALUES (1)', "SELECT * FROM items WHERE (id IN ('INSERT INTO items (x) VALUES (1)')) LIMIT 1"]
1443
+ MODEL_DB.sqls.should == ['INSERT INTO items (x) VALUES (1)', "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
1179
1444
  end
1180
1445
 
1181
1446
  it "should be able to create rows without any values specified" do
1182
1447
  o = @c.create
1183
1448
  o.class.should == @c
1184
- MODEL_DB.sqls.should == ["INSERT INTO items DEFAULT VALUES", "SELECT * FROM items WHERE (id IN ('INSERT INTO items DEFAULT VALUES')) LIMIT 1"]
1449
+ MODEL_DB.sqls.should == ["INSERT INTO items DEFAULT VALUES", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
1185
1450
  end
1186
1451
 
1187
1452
  it "should accept a block and run it" do
@@ -1191,7 +1456,7 @@ describe Sequel::Model, ".create" do
1191
1456
  o1.should === o
1192
1457
  o3.should === o
1193
1458
  o2.should == :blah
1194
- MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (333)", "SELECT * FROM items WHERE (id IN ('INSERT INTO items (x) VALUES (333)')) LIMIT 1"]
1459
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (333)", "SELECT * FROM items WHERE (id = 10) LIMIT 1"]
1195
1460
  end
1196
1461
 
1197
1462
  it "should create a row for a model with custom primary key" do
@@ -1204,49 +1469,45 @@ end
1204
1469
 
1205
1470
  describe Sequel::Model, "#refresh" do
1206
1471
  before do
1207
- MODEL_DB.reset
1208
1472
  @c = Class.new(Sequel::Model(:items)) do
1209
1473
  unrestrict_primary_key
1210
1474
  columns :id, :x
1211
1475
  end
1476
+ MODEL_DB.reset
1212
1477
  end
1213
1478
 
1214
1479
  specify "should reload the instance values from the database" do
1215
1480
  @m = @c.new(:id => 555)
1216
1481
  @m[:x] = 'blah'
1217
- @m.this.should_receive(:first).and_return({:x => 'kaboom', :id => 555})
1482
+ @c.instance_dataset._fetch = @c.dataset._fetch = {:x => 'kaboom', :id => 555}
1218
1483
  @m.refresh
1219
1484
  @m[:x].should == 'kaboom'
1485
+ MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (id = 555) LIMIT 1"]
1220
1486
  end
1221
1487
 
1222
1488
  specify "should raise if the instance is not found" do
1223
1489
  @m = @c.new(:id => 555)
1224
- @m.this.should_receive(:first).and_return(nil)
1490
+ @c.instance_dataset._fetch =@c.dataset._fetch = []
1225
1491
  proc {@m.refresh}.should raise_error(Sequel::Error)
1492
+ MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (id = 555) LIMIT 1"]
1226
1493
  end
1227
1494
 
1228
1495
  specify "should be aliased by #reload" do
1229
1496
  @m = @c.new(:id => 555)
1230
- @m.this.should_receive(:first).and_return({:x => 'kaboom', :id => 555})
1497
+ @c.instance_dataset._fetch =@c.dataset._fetch = {:x => 'kaboom', :id => 555}
1231
1498
  @m.reload
1232
1499
  @m[:x].should == 'kaboom'
1233
- end
1234
-
1235
- specify "should remove cached associations" do
1236
- @c.many_to_one :node, :class=>@c
1237
- @m = @c.new(:id => 555)
1238
- @m.associations[:node] = 15
1239
- @m.reload
1240
- @m.associations.should == {}
1500
+ MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (id = 555) LIMIT 1"]
1241
1501
  end
1242
1502
  end
1243
1503
 
1244
1504
  describe Sequel::Model, "typecasting" do
1245
1505
  before do
1246
- MODEL_DB.reset
1247
1506
  @c = Class.new(Sequel::Model(:items)) do
1248
1507
  columns :x
1249
1508
  end
1509
+ @c.db_schema = {:x=>{:type=>:integer}}
1510
+ MODEL_DB.reset
1250
1511
  end
1251
1512
 
1252
1513
  after do
@@ -1255,14 +1516,13 @@ describe Sequel::Model, "typecasting" do
1255
1516
 
1256
1517
  specify "should not convert if typecasting is turned off" do
1257
1518
  @c.typecast_on_assignment = false
1258
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer}})
1259
1519
  m = @c.new
1260
1520
  m.x = '1'
1261
1521
  m.x.should == '1'
1262
1522
  end
1263
1523
 
1264
1524
  specify "should convert to integer for an integer field" do
1265
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer}})
1525
+ @c.db_schema = {:x=>{:type=>:integer}}
1266
1526
  m = @c.new
1267
1527
  m.x = '1'
1268
1528
  m.x.should == 1
@@ -1274,13 +1534,13 @@ describe Sequel::Model, "typecasting" do
1274
1534
 
1275
1535
  specify "should typecast '' to nil unless type is string or blob" do
1276
1536
  [:integer, :float, :decimal, :boolean, :date, :time, :datetime].each do |x|
1277
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>x}})
1537
+ @c.db_schema = {:x=>{:type=>x}}
1278
1538
  m = @c.new
1279
1539
  m.x = ''
1280
1540
  m.x.should == nil
1281
1541
  end
1282
1542
  [:string, :blob].each do |x|
1283
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>x}})
1543
+ @c.db_schema = {:x=>{:type=>x}}
1284
1544
  m = @c.new
1285
1545
  m.x = ''
1286
1546
  m.x.should == ''
@@ -1288,7 +1548,6 @@ describe Sequel::Model, "typecasting" do
1288
1548
  end
1289
1549
 
1290
1550
  specify "should not typecast '' to nil if typecast_empty_string_to_nil is false" do
1291
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer}})
1292
1551
  m = @c.new
1293
1552
  m.typecast_empty_string_to_nil = false
1294
1553
  proc{m.x = ''}.should raise_error
@@ -1296,22 +1555,31 @@ describe Sequel::Model, "typecasting" do
1296
1555
  proc{@c.new.x = ''}.should raise_error
1297
1556
  end
1298
1557
 
1558
+ specify "should handle typecasting where == raises an error on the object" do
1559
+ m = @c.new
1560
+ o = Object.new
1561
+ def o.==(v) raise ArgumentError end
1562
+ def o.to_i() 4 end
1563
+ m.x = o
1564
+ m.x.should == 4
1565
+ end
1566
+
1299
1567
  specify "should not typecast nil if NULLs are allowed" do
1300
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer,:allow_null=>true}})
1568
+ @c.db_schema[:x][:allow_null] = true
1301
1569
  m = @c.new
1302
1570
  m.x = nil
1303
1571
  m.x.should == nil
1304
1572
  end
1305
1573
 
1306
1574
  specify "should raise an error if attempting to typecast nil and NULLs are not allowed" do
1307
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer,:allow_null=>false}})
1575
+ @c.db_schema[:x][:allow_null] = false
1308
1576
  proc{@c.new.x = nil}.should raise_error(Sequel::Error)
1309
1577
  proc{@c.new.x = ''}.should raise_error(Sequel::Error)
1310
1578
  end
1311
1579
 
1312
1580
  specify "should not raise an error if NULLs are not allowed and typecasting is turned off" do
1313
1581
  @c.typecast_on_assignment = false
1314
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer,:allow_null=>false}})
1582
+ @c.db_schema[:x][:allow_null] = false
1315
1583
  m = @c.new
1316
1584
  m.x = nil
1317
1585
  m.x.should == nil
@@ -1320,7 +1588,6 @@ describe Sequel::Model, "typecasting" do
1320
1588
  specify "should not raise when typecasting nil to NOT NULL column but raise_on_typecast_failure is off" do
1321
1589
  @c.raise_on_typecast_failure = false
1322
1590
  @c.typecast_on_assignment = true
1323
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer,:allow_null=>false}})
1324
1591
  m = @c.new
1325
1592
  m.x = ''
1326
1593
  m.x.should == nil
@@ -1329,20 +1596,18 @@ describe Sequel::Model, "typecasting" do
1329
1596
  end
1330
1597
 
1331
1598
  specify "should raise an error if invalid data is used in an integer field" do
1332
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer}})
1333
1599
  proc{@c.new.x = 'a'}.should raise_error(Sequel::InvalidValue)
1334
1600
  end
1335
1601
 
1336
1602
  specify "should assign value if raise_on_typecast_failure is off and assigning invalid integer" do
1337
1603
  @c.raise_on_typecast_failure = false
1338
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:integer}})
1339
1604
  model = @c.new
1340
1605
  model.x = '1d'
1341
1606
  model.x.should == '1d'
1342
1607
  end
1343
1608
 
1344
1609
  specify "should convert to float for a float field" do
1345
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:float}})
1610
+ @c.db_schema = {:x=>{:type=>:float}}
1346
1611
  m = @c.new
1347
1612
  m.x = '1.3'
1348
1613
  m.x.should == 1.3
@@ -1353,20 +1618,20 @@ describe Sequel::Model, "typecasting" do
1353
1618
  end
1354
1619
 
1355
1620
  specify "should raise an error if invalid data is used in an float field" do
1356
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:float}})
1621
+ @c.db_schema = {:x=>{:type=>:float}}
1357
1622
  proc{@c.new.x = 'a'}.should raise_error(Sequel::InvalidValue)
1358
1623
  end
1359
1624
 
1360
1625
  specify "should assign value if raise_on_typecast_failure is off and assigning invalid float" do
1361
1626
  @c.raise_on_typecast_failure = false
1362
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:float}})
1627
+ @c.db_schema = {:x=>{:type=>:float}}
1363
1628
  model = @c.new
1364
1629
  model.x = '1d'
1365
1630
  model.x.should == '1d'
1366
1631
  end
1367
1632
 
1368
1633
  specify "should convert to BigDecimal for a decimal field" do
1369
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:decimal}})
1634
+ @c.db_schema = {:x=>{:type=>:decimal}}
1370
1635
  m = @c.new
1371
1636
  bd = BigDecimal.new('1.0')
1372
1637
  m.x = '1.0'
@@ -1380,13 +1645,13 @@ describe Sequel::Model, "typecasting" do
1380
1645
  end
1381
1646
 
1382
1647
  specify "should raise an error if invalid data is used in an decimal field" do
1383
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:decimal}})
1648
+ @c.db_schema = {:x=>{:type=>:decimal}}
1384
1649
  proc{@c.new.x = Date.today}.should raise_error(Sequel::InvalidValue)
1385
1650
  end
1386
1651
 
1387
1652
  specify "should assign value if raise_on_typecast_failure is off and assigning invalid decimal" do
1388
1653
  @c.raise_on_typecast_failure = false
1389
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:decimal}})
1654
+ @c.db_schema = {:x=>{:type=>:decimal}}
1390
1655
  model = @c.new
1391
1656
  time = Time.now
1392
1657
  model.x = time
@@ -1394,7 +1659,7 @@ describe Sequel::Model, "typecasting" do
1394
1659
  end
1395
1660
 
1396
1661
  specify "should convert to string for a string field" do
1397
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:string}})
1662
+ @c.db_schema = {:x=>{:type=>:string}}
1398
1663
  m = @c.new
1399
1664
  m.x = '1.3'
1400
1665
  m.x.should == '1.3'
@@ -1405,7 +1670,7 @@ describe Sequel::Model, "typecasting" do
1405
1670
  end
1406
1671
 
1407
1672
  specify "should convert to boolean for a boolean field" do
1408
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:boolean}})
1673
+ @c.db_schema = {:x=>{:type=>:boolean}}
1409
1674
  m = @c.new
1410
1675
  m.x = '1.3'
1411
1676
  m.x.should == true
@@ -1417,6 +1682,10 @@ describe Sequel::Model, "typecasting" do
1417
1682
  m.x.should == true
1418
1683
  m.x = 'T'
1419
1684
  m.x.should == true
1685
+ m.x = 'y'
1686
+ m.x.should == true
1687
+ m.x = 'Y'
1688
+ m.x.should == true
1420
1689
  m.x = true
1421
1690
  m.x.should == true
1422
1691
  m.x = nil
@@ -1433,6 +1702,14 @@ describe Sequel::Model, "typecasting" do
1433
1702
  m.x.should == false
1434
1703
  m.x = 'FALSE'
1435
1704
  m.x.should == false
1705
+ m.x = 'n'
1706
+ m.x.should == false
1707
+ m.x = 'N'
1708
+ m.x.should == false
1709
+ m.x = 'no'
1710
+ m.x.should == false
1711
+ m.x = 'NO'
1712
+ m.x.should == false
1436
1713
  m.x = '0'
1437
1714
  m.x.should == false
1438
1715
  m.x = 0
@@ -1442,7 +1719,7 @@ describe Sequel::Model, "typecasting" do
1442
1719
  end
1443
1720
 
1444
1721
  specify "should convert to date for a date field" do
1445
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:date}})
1722
+ @c.db_schema = {:x=>{:type=>:date}}
1446
1723
  m = @c.new
1447
1724
  y = Date.new(2007,10,21)
1448
1725
  m.x = '2007-10-21'
@@ -1456,7 +1733,7 @@ describe Sequel::Model, "typecasting" do
1456
1733
  end
1457
1734
 
1458
1735
  specify "should accept a hash with symbol or string keys for a date field" do
1459
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:date}})
1736
+ @c.db_schema = {:x=>{:type=>:date}}
1460
1737
  m = @c.new
1461
1738
  y = Date.new(2007,10,21)
1462
1739
  m.x = {:year=>2007, :month=>10, :day=>21}
@@ -1466,32 +1743,33 @@ describe Sequel::Model, "typecasting" do
1466
1743
  end
1467
1744
 
1468
1745
  specify "should raise an error if invalid data is used in a date field" do
1469
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:date}})
1746
+ @c.db_schema = {:x=>{:type=>:date}}
1470
1747
  proc{@c.new.x = 'a'}.should raise_error(Sequel::InvalidValue)
1471
1748
  proc{@c.new.x = 100}.should raise_error(Sequel::InvalidValue)
1472
1749
  end
1473
1750
 
1474
1751
  specify "should assign value if raise_on_typecast_failure is off and assigning invalid date" do
1475
1752
  @c.raise_on_typecast_failure = false
1476
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:date}})
1753
+ @c.db_schema = {:x=>{:type=>:date}}
1477
1754
  model = @c.new
1478
1755
  model.x = 4
1479
1756
  model.x.should == 4
1480
1757
  end
1481
1758
 
1482
- specify "should convert to time for a time field" do
1483
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:time}})
1759
+ specify "should convert to Sequel::SQLTime for a time field" do
1760
+ @c.db_schema = {:x=>{:type=>:time}}
1484
1761
  m = @c.new
1485
1762
  x = '10:20:30'
1486
- y = Time.parse(x)
1763
+ y = Sequel::SQLTime.parse(x)
1487
1764
  m.x = x
1488
1765
  m.x.should == y
1489
1766
  m.x = y
1490
1767
  m.x.should == y
1768
+ m.x.should be_a_kind_of(Sequel::SQLTime)
1491
1769
  end
1492
1770
 
1493
1771
  specify "should accept a hash with symbol or string keys for a time field" do
1494
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:time}})
1772
+ @c.db_schema = {:x=>{:type=>:time}}
1495
1773
  m = @c.new
1496
1774
  y = Time.parse('10:20:30')
1497
1775
  m.x = {:hour=>10, :minute=>20, :second=>30}
@@ -1501,7 +1779,7 @@ describe Sequel::Model, "typecasting" do
1501
1779
  end
1502
1780
 
1503
1781
  specify "should raise an error if invalid data is used in a time field" do
1504
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:time}})
1782
+ @c.db_schema = {:x=>{:type=>:time}}
1505
1783
  proc{@c.new.x = '0000'}.should raise_error
1506
1784
  proc{@c.new.x = Date.parse('2008-10-21')}.should raise_error(Sequel::InvalidValue)
1507
1785
  proc{@c.new.x = DateTime.parse('2008-10-21')}.should raise_error(Sequel::InvalidValue)
@@ -1509,14 +1787,14 @@ describe Sequel::Model, "typecasting" do
1509
1787
 
1510
1788
  specify "should assign value if raise_on_typecast_failure is off and assigning invalid time" do
1511
1789
  @c.raise_on_typecast_failure = false
1512
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:time}})
1790
+ @c.db_schema = {:x=>{:type=>:time}}
1513
1791
  model = @c.new
1514
1792
  model.x = '0000'
1515
1793
  model.x.should == '0000'
1516
1794
  end
1517
1795
 
1518
1796
  specify "should convert to the Sequel.datetime_class for a datetime field" do
1519
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:datetime}})
1797
+ @c.db_schema = {:x=>{:type=>:datetime}}
1520
1798
  m = @c.new
1521
1799
  x = '2007-10-21T10:20:30-07:00'
1522
1800
  y = Time.parse(x)
@@ -1541,7 +1819,7 @@ describe Sequel::Model, "typecasting" do
1541
1819
  end
1542
1820
 
1543
1821
  specify "should accept a hash with symbol or string keys for a datetime field" do
1544
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:datetime}})
1822
+ @c.db_schema = {:x=>{:type=>:datetime}}
1545
1823
  m = @c.new
1546
1824
  y = Time.parse('2007-10-21 10:20:30')
1547
1825
  m.x = {:year=>2007, :month=>10, :day=>21, :hour=>10, :minute=>20, :second=>30}
@@ -1557,7 +1835,7 @@ describe Sequel::Model, "typecasting" do
1557
1835
  end
1558
1836
 
1559
1837
  specify "should raise an error if invalid data is used in a datetime field" do
1560
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:datetime}})
1838
+ @c.db_schema = {:x=>{:type=>:datetime}}
1561
1839
  proc{@c.new.x = '0000'}.should raise_error(Sequel::InvalidValue)
1562
1840
  Sequel.datetime_class = DateTime
1563
1841
  proc{@c.new.x = '0000'}.should raise_error(Sequel::InvalidValue)
@@ -1566,7 +1844,7 @@ describe Sequel::Model, "typecasting" do
1566
1844
 
1567
1845
  specify "should assign value if raise_on_typecast_failure is off and assigning invalid datetime" do
1568
1846
  @c.raise_on_typecast_failure = false
1569
- @c.instance_variable_set(:@db_schema, {:x=>{:type=>:datetime}})
1847
+ @c.db_schema = {:x=>{:type=>:datetime}}
1570
1848
  model = @c.new
1571
1849
  model.x = '0000'
1572
1850
  model.x.should == '0000'
@@ -1584,11 +1862,7 @@ describe "Model#lock!" do
1584
1862
  @c = Class.new(Sequel::Model(:items)) do
1585
1863
  columns :id
1586
1864
  end
1587
- ds = @c.dataset
1588
- def ds.fetch_rows(sql)
1589
- db.execute(sql)
1590
- yield({:id=>1})
1591
- end
1865
+ @c.dataset._fetch = {:id=>1}
1592
1866
  MODEL_DB.reset
1593
1867
  end
1594
1868