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,14 +1,18 @@
1
1
  require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
2
 
3
3
  describe "Model attribute setters" do
4
-
5
- before(:each) do
6
- MODEL_DB.reset
7
-
4
+ before do
8
5
  @c = Class.new(Sequel::Model(:items)) do
9
6
  columns :id, :x, :y, :"x y"
10
7
  end
11
8
  @o = @c.new
9
+ MODEL_DB.reset
10
+ end
11
+
12
+ specify "refresh should return self" do
13
+ @o = @c[1]
14
+ @o.stub(:_refresh).and_return([])
15
+ @o.refresh.should == @o
12
16
  end
13
17
 
14
18
  it "should mark the column value as changed" do
@@ -37,22 +41,37 @@ describe "Model attribute setters" do
37
41
  end
38
42
  end
39
43
 
44
+ describe "Model.def_column_alias" do
45
+ before do
46
+ @o = Class.new(Sequel::Model(:items)) do
47
+ columns :id
48
+ def_column_alias(:id2, :id)
49
+ end.load(:id=>1)
50
+ MODEL_DB.reset
51
+ end
52
+
53
+ it "should create an getter alias for the column" do
54
+ @o.id2.should == 1
55
+ end
56
+
57
+ it "should create an setter alias for the column" do
58
+ @o.id2 = 2
59
+ @o.id2.should == 2
60
+ @o.values.should == {:id => 2}
61
+ end
62
+ end
63
+
40
64
  describe Sequel::Model, "dataset" do
41
65
  before do
42
66
  @a = Class.new(Sequel::Model(:items))
43
67
  @b = Class.new(Sequel::Model)
44
-
45
- class Elephant < Sequel::Model(:ele1)
46
- end
47
-
48
- class Maggot < Sequel::Model
49
- end
50
-
51
- class ShoeSize < Sequel::Model
52
- end
53
-
54
- class BootSize < ShoeSize
55
- end
68
+ class ::Elephant < Sequel::Model(:ele1); end
69
+ class ::Maggot < Sequel::Model; end
70
+ class ::ShoeSize < Sequel::Model; end
71
+ class ::BootSize < ShoeSize; end
72
+ end
73
+ after do
74
+ [:Elephant, :Maggot, :ShoeSize, :BootSize].each{|x| Object.send(:remove_const, x)}
56
75
  end
57
76
 
58
77
  specify "should default to the plural of the class name" do
@@ -74,33 +93,59 @@ describe Sequel::Model, "dataset" do
74
93
  end
75
94
 
76
95
  specify "should disregard namespaces for the table name" do
77
- module BlahBlah
78
- class MwaHaHa < Sequel::Model
96
+ begin
97
+ module ::BlahBlah
98
+ class MwaHaHa < Sequel::Model
99
+ end
79
100
  end
80
- end
81
101
 
82
- BlahBlah::MwaHaHa.dataset.sql.should == 'SELECT * FROM mwa_ha_has'
102
+ BlahBlah::MwaHaHa.dataset.sql.should == 'SELECT * FROM mwa_ha_has'
103
+ ensure
104
+ Object.send(:remove_const, :BlahBlah)
105
+ end
83
106
  end
84
107
  end
85
108
 
86
109
  describe Sequel::Model, ".def_dataset_method" do
87
110
  before do
88
- @c = Class.new(Sequel::Model(:items)) do
89
- end
111
+ @c = Class.new(Sequel::Model(:items))
90
112
  end
91
113
 
92
114
  it "should add a method to the dataset and model if called with a block argument" do
93
- @c.instance_eval do
94
- def_dataset_method(:return_3){3}
95
- end
115
+ @c.def_dataset_method(:return_3){3}
96
116
  @c.return_3.should == 3
97
117
  @c.dataset.return_3.should == 3
98
118
  end
99
119
 
100
- it "should add all passed methods to the model if called without a block argument" do
120
+ it "should handle weird method names" do
121
+ @c.def_dataset_method(:"return 3"){3}
122
+ @c.send(:"return 3").should == 3
123
+ @c.dataset.send(:"return 3").should == 3
124
+ end
125
+
126
+ it "should not add a model method if the model already responds to the method" do
101
127
  @c.instance_eval do
102
- def_dataset_method(:return_3, :return_4)
128
+ def foo
129
+ 1
130
+ end
131
+
132
+ private
133
+
134
+ def bar
135
+ 2
136
+ end
137
+
138
+ def_dataset_method(:foo){3}
139
+ def_dataset_method(:bar){4}
103
140
  end
141
+ @c.foo.should == 1
142
+ @c.dataset.foo.should == 3
143
+ @c.send(:bar).should == 2
144
+ @c.dataset.bar.should == 4
145
+ end
146
+
147
+ it "should add all passed methods to the model if called without a block argument" do
148
+ @c.def_dataset_method(:return_3, :return_4)
104
149
  proc{@c.return_3}.should raise_error(NoMethodError)
105
150
  proc{@c.return_4}.should raise_error(NoMethodError)
106
151
  @c.dataset.instance_eval do
@@ -112,18 +157,14 @@ describe Sequel::Model, ".def_dataset_method" do
112
157
  end
113
158
 
114
159
  it "should cache calls and readd methods if set_dataset is used" do
115
- @c.instance_eval do
116
- def_dataset_method(:return_3){3}
117
- end
160
+ @c.def_dataset_method(:return_3){3}
118
161
  @c.set_dataset :items
119
162
  @c.return_3.should == 3
120
163
  @c.dataset.return_3.should == 3
121
164
  end
122
165
 
123
166
  it "should readd methods to subclasses, if set_dataset is used in a subclass" do
124
- @c.instance_eval do
125
- def_dataset_method(:return_3){3}
126
- end
167
+ @c.def_dataset_method(:return_3){3}
127
168
  c = Class.new(@c)
128
169
  c.set_dataset :items
129
170
  c.return_3.should == 3
@@ -131,11 +172,98 @@ describe Sequel::Model, ".def_dataset_method" do
131
172
  end
132
173
  end
133
174
 
175
+ describe Sequel::Model, ".dataset_module" do
176
+ before do
177
+ @c = Class.new(Sequel::Model(:items))
178
+ end
179
+
180
+ it "should extend the dataset with the module if the model has a dataset" do
181
+ @c.dataset_module{def return_3() 3 end}
182
+ @c.dataset.return_3.should == 3
183
+ end
184
+
185
+ it "should add methods defined in the module to the class" do
186
+ @c.dataset_module{def return_3() 3 end}
187
+ @c.return_3.should == 3
188
+ end
189
+
190
+ it "should cache calls and readd methods if set_dataset is used" do
191
+ @c.dataset_module{def return_3() 3 end}
192
+ @c.set_dataset :items
193
+ @c.return_3.should == 3
194
+ @c.dataset.return_3.should == 3
195
+ end
196
+
197
+ it "should readd methods to subclasses, if set_dataset is used in a subclass" do
198
+ @c.dataset_module{def return_3() 3 end}
199
+ c = Class.new(@c)
200
+ c.set_dataset :items
201
+ c.return_3.should == 3
202
+ c.dataset.return_3.should == 3
203
+ end
204
+
205
+ it "should only have a single dataset_module per class" do
206
+ @c.dataset_module{def return_3() 3 end}
207
+ @c.dataset_module{def return_3() 3 + (begin; super; rescue NoMethodError; 1; end) end}
208
+ @c.return_3.should == 4
209
+ end
210
+
211
+ it "should not have subclasses share the dataset_module" do
212
+ @c.dataset_module{def return_3() 3 end}
213
+ c = Class.new(@c)
214
+ c.dataset_module{def return_3() 3 + (begin; super; rescue NoMethodError; 1; end) end}
215
+ c.return_3.should == 6
216
+ end
217
+
218
+ it "should accept a module object and extend the dataset with it" do
219
+ @c.dataset_module Module.new{def return_3() 3 end}
220
+ @c.dataset.return_3.should == 3
221
+ end
222
+
223
+ it "should be able to call dataset_module with a module multiple times" do
224
+ @c.dataset_module Module.new{def return_3() 3 end}
225
+ @c.dataset_module Module.new{def return_4() 4 end}
226
+ @c.dataset.return_3.should == 3
227
+ @c.dataset.return_4.should == 4
228
+ end
229
+
230
+ it "should be able mix dataset_module calls with and without arguments" do
231
+ @c.dataset_module{def return_3() 3 end}
232
+ @c.dataset_module Module.new{def return_4() 4 end}
233
+ @c.dataset.return_3.should == 3
234
+ @c.dataset.return_4.should == 4
235
+ end
236
+
237
+ it "should have modules provided to dataset_module extend subclass datasets" do
238
+ @c.dataset_module{def return_3() 3 end}
239
+ @c.dataset_module Module.new{def return_4() 4 end}
240
+ c = Class.new(@c)
241
+ c.set_dataset :a
242
+ c.dataset.return_3.should == 3
243
+ c.dataset.return_4.should == 4
244
+ end
245
+
246
+ it "should return the dataset module if given a block" do
247
+ Object.new.extend(@c.dataset_module{def return_3() 3 end}).return_3.should == 3
248
+ end
249
+
250
+ it "should return the argument if given one" do
251
+ Object.new.extend(@c.dataset_module Module.new{def return_3() 3 end}).return_3.should == 3
252
+ end
253
+
254
+ it "should raise error if called with both an argument and ablock" do
255
+ proc{@c.dataset_module(Module.new{def return_3() 3 end}){}}.should raise_error(Sequel::Error)
256
+ end
257
+ end
258
+
134
259
  describe "A model class with implicit table name" do
135
260
  before do
136
- class Donkey < Sequel::Model
261
+ class ::Donkey < Sequel::Model
137
262
  end
138
263
  end
264
+ after do
265
+ Object.send(:remove_const, :Donkey)
266
+ end
139
267
 
140
268
  specify "should have a dataset associated with the model class" do
141
269
  Donkey.dataset.model.should == Donkey
@@ -144,11 +272,12 @@ end
144
272
 
145
273
  describe "A model inheriting from a model" do
146
274
  before do
147
- class Feline < Sequel::Model
148
- end
149
-
150
- class Leopard < Feline
151
- end
275
+ class ::Feline < Sequel::Model; end
276
+ class ::Leopard < Feline; end
277
+ end
278
+ after do
279
+ Object.send(:remove_const, :Leopard)
280
+ Object.send(:remove_const, :Feline)
152
281
  end
153
282
 
154
283
  specify "should have a dataset associated with itself" do
@@ -206,12 +335,12 @@ describe "Model.qualified_primary_key_hash" do
206
335
  end
207
336
 
208
337
  specify "should handle a single primary key" do
209
- @c.qualified_primary_key_hash(1).should == {:id.qualify(:items)=>1}
338
+ @c.qualified_primary_key_hash(1).should == {Sequel.qualify(:items, :id)=>1}
210
339
  end
211
340
 
212
341
  specify "should handle a composite primary key" do
213
342
  @c.set_primary_key([:id1, :id2])
214
- @c.qualified_primary_key_hash([1, 2]).should == {:id1.qualify(:items)=>1, :id2.qualify(:items)=>2}
343
+ @c.qualified_primary_key_hash([1, 2]).should == {Sequel.qualify(:items, :id1)=>1, Sequel.qualify(:items, :id2)=>2}
215
344
  end
216
345
 
217
346
  specify "should raise an error for no primary key" do
@@ -220,37 +349,83 @@ describe "Model.qualified_primary_key_hash" do
220
349
  end
221
350
 
222
351
  specify "should allow specifying a different qualifier" do
223
- @c.qualified_primary_key_hash(1, :apple).should == {:id.qualify(:apple)=>1}
352
+ @c.qualified_primary_key_hash(1, :apple).should == {Sequel.qualify(:apple, :id)=>1}
224
353
  @c.set_primary_key([:id1, :id2])
225
- @c.qualified_primary_key_hash([1, 2], :bear).should == {:id1.qualify(:bear)=>1, :id2.qualify(:bear)=>2}
354
+ @c.qualified_primary_key_hash([1, 2], :bear).should == {Sequel.qualify(:bear, :id1)=>1, Sequel.qualify(:bear, :id2)=>2}
355
+ end
356
+ end
357
+
358
+ describe "Model.db" do
359
+ before do
360
+ @db = Sequel.mock
361
+ @databases = Sequel::DATABASES.dup
362
+ @model_db = Sequel::Model.db
363
+ Sequel::Model.db = nil
364
+ Sequel::DATABASES.clear
365
+ end
366
+ after do
367
+ Sequel::Model.instance_variable_get(:@db).should == nil
368
+ Sequel::DATABASES.replace(@databases)
369
+ Sequel::Model.db = @model_db
370
+ end
371
+
372
+ specify "should be required when create named model classes" do
373
+ begin
374
+ proc{class ModelTest < Sequel::Model; end}.should raise_error(Sequel::Error)
375
+ ensure
376
+ Object.send(:remove_const, :ModelTest)
377
+ end
378
+ end
379
+
380
+ specify "should be required when creating anonymous model classes without a database" do
381
+ proc{Sequel::Model(:foo)}.should raise_error(Sequel::Error)
382
+ end
383
+
384
+ specify "should not be required when creating anonymous model classes with a database" do
385
+ Sequel::Model(@db).db.should == @db
386
+ Sequel::Model(@db[:foo]).db.should == @db
387
+ end
388
+
389
+ specify "should work correctly when subclassing anonymous model classes with a database" do
390
+ begin
391
+ Class.new(Sequel::Model(@db)).db.should == @db
392
+ Class.new(Sequel::Model(@db[:foo])).db.should == @db
393
+ class ModelTest < Sequel::Model(@db)
394
+ db.should == @db
395
+ end
396
+ class ModelTest2 < Sequel::Model(@db[:foo])
397
+ db.should == @db
398
+ end
399
+ ensure
400
+ Object.send(:remove_const, :ModelTest)
401
+ Object.send(:remove_const, :ModelTest2)
402
+ end
226
403
  end
227
404
  end
228
405
 
229
406
  describe "Model.db=" do
230
407
  before do
231
- $db1 = MockDatabase.new
232
- $db2 = MockDatabase.new
408
+ @db1 = Sequel.mock
409
+ @db2 = Sequel.mock
233
410
 
234
- class BlueBlue < Sequel::Model(:items)
235
- set_dataset $db1[:blue].filter(:x=>1)
236
- end
411
+ @m = Class.new(Sequel::Model(@db1[:blue].filter(:x=>1)))
237
412
  end
238
413
 
239
414
  specify "should affect the underlying dataset" do
240
- BlueBlue.db = $db2
415
+ @m.db = @db2
241
416
 
242
- BlueBlue.dataset.db.should === $db2
243
- BlueBlue.dataset.db.should_not === $db1
417
+ @m.dataset.db.should === @db2
418
+ @m.dataset.db.should_not === @db1
244
419
  end
245
420
 
246
421
  specify "should keep the same dataset options" do
247
- BlueBlue.db = $db2
248
- BlueBlue.dataset.sql.should == 'SELECT * FROM blue WHERE (x = 1)'
422
+ @m.db = @db2
423
+ @m.dataset.sql.should == 'SELECT * FROM blue WHERE (x = 1)'
249
424
  end
250
425
 
251
426
  specify "should use the database for subclasses" do
252
- BlueBlue.db = $db2
253
- Class.new(BlueBlue).db.should === $db2
427
+ @m.db = @db2
428
+ Class.new(@m).db.should === @db2
254
429
  end
255
430
  end
256
431
 
@@ -258,9 +433,6 @@ describe Sequel::Model, ".(allowed|restricted)_columns " do
258
433
  before do
259
434
  @c = Class.new(Sequel::Model(:blahblah)) do
260
435
  columns :x, :y, :z
261
- def _refresh(ds)
262
- self
263
- end
264
436
  end
265
437
  @c.strict_param_setting = false
266
438
  @c.instance_variable_set(:@columns, [:x, :y, :z])
@@ -288,9 +460,12 @@ describe Sequel::Model, ".(allowed|restricted)_columns " do
288
460
  i.values.should == {:x => 1, :y => 2}
289
461
  i.set(:x => 4, :y => 5, :z => 6)
290
462
  i.values.should == {:x => 4, :y => 5}
291
- i.update(:x => 7, :y => 8, :z => 9)
292
- i.values.delete(:id) # stupid specs
293
- i.values.should == {:x => 7, :y => 8}
463
+
464
+ @c.instance_dataset._fetch = @c.dataset._fetch = {:x => 7}
465
+ i = @c.new
466
+ i.update(:x => 7, :z => 9)
467
+ i.values.should == {:x => 7}
468
+ MODEL_DB.sqls.should == ["INSERT INTO blahblah (x) VALUES (7)", "SELECT * FROM blahblah WHERE (id = 10) LIMIT 1"]
294
469
  end
295
470
 
296
471
  it "should not set restricted columns by default" do
@@ -299,9 +474,12 @@ describe Sequel::Model, ".(allowed|restricted)_columns " do
299
474
  i.values.should == {:x => 1, :y => 2}
300
475
  i.set(:x => 4, :y => 5, :z => 6)
301
476
  i.values.should == {:x => 4, :y => 5}
302
- i.update(:x => 7, :y => 8, :z => 9)
303
- i.values.delete(:id) # stupid specs
304
- i.values.should == {:x => 7, :y => 8}
477
+
478
+ @c.instance_dataset._fetch = @c.dataset._fetch = {:x => 7}
479
+ i = @c.new
480
+ i.update(:x => 7, :z => 9)
481
+ i.values.should == {:x => 7}
482
+ MODEL_DB.sqls.should == ["INSERT INTO blahblah (x) VALUES (7)", "SELECT * FROM blahblah WHERE (id = 10) LIMIT 1"]
305
483
  end
306
484
 
307
485
  it "should have allowed take precedence over restricted" do
@@ -311,9 +489,12 @@ describe Sequel::Model, ".(allowed|restricted)_columns " do
311
489
  i.values.should == {:x => 1, :y => 2}
312
490
  i.set(:x => 4, :y => 5, :z => 6)
313
491
  i.values.should == {:x => 4, :y => 5}
314
- i.update(:x => 7, :y => 8, :z => 9)
315
- i.values.delete(:id) # stupid specs
316
- i.values.should == {:x => 7, :y => 8}
492
+
493
+ @c.instance_dataset._fetch = @c.dataset._fetch = {:y => 7}
494
+ i = @c.new
495
+ i.update(:y => 7, :z => 9)
496
+ i.values.should == {:y => 7}
497
+ MODEL_DB.sqls.should == ["INSERT INTO blahblah (y) VALUES (7)", "SELECT * FROM blahblah WHERE (id = 10) LIMIT 1"]
317
498
  end
318
499
  end
319
500
 
@@ -322,12 +503,8 @@ describe Sequel::Model, ".(un)?restrict_primary_key\\??" do
322
503
  @c = Class.new(Sequel::Model(:blahblah)) do
323
504
  set_primary_key :id
324
505
  columns :x, :y, :z, :id
325
- def refresh
326
- self
327
- end
328
506
  end
329
507
  @c.strict_param_setting = false
330
- @c.instance_variable_set(:@columns, [:x, :y, :z])
331
508
  end
332
509
 
333
510
  it "should restrict updates to primary key by default" do
@@ -364,11 +541,7 @@ describe Sequel::Model, ".strict_param_setting" do
364
541
  @c = Class.new(Sequel::Model(:blahblah)) do
365
542
  columns :x, :y, :z, :id
366
543
  set_restricted_columns :z
367
- def refresh
368
- self
369
- end
370
544
  end
371
- @c.instance_variable_set(:@columns, [:x, :y, :z])
372
545
  end
373
546
 
374
547
  it "should be enabled by default" do
@@ -425,20 +598,18 @@ end
425
598
 
426
599
  describe Sequel::Model, ".[] optimization" do
427
600
  before do
428
- @c = Class.new(Sequel::Model(:a))
429
- @c.instance_eval do
430
- def simple_table
431
- @simple_table
432
- end
433
- end
601
+ @db = MODEL_DB.clone
602
+ @db.quote_identifiers = true
603
+ @c = Class.new(Sequel::Model(@db))
434
604
  end
435
605
 
436
606
  it "should set simple_pk to the literalized primary key column name if a single primary key" do
437
- @c.simple_pk.should == 'id'
607
+ @c.set_primary_key :id
608
+ @c.simple_pk.should == '"id"'
438
609
  @c.set_primary_key :b
439
- @c.simple_pk.should == 'b'
440
- @c.set_primary_key :b__a.identifier
441
- @c.simple_pk.should == 'b__a'
610
+ @c.simple_pk.should == '"b"'
611
+ @c.set_primary_key Sequel.identifier(:b__a)
612
+ @c.simple_pk.should == '"b__a"'
442
613
  end
443
614
 
444
615
  it "should have simple_pk be blank if compound or no primary key" do
@@ -452,36 +623,99 @@ describe Sequel::Model, ".[] optimization" do
452
623
 
453
624
  it "should have simple table set if passed a Symbol to set_dataset" do
454
625
  @c.set_dataset :a
455
- @c.simple_table.should == 'a'
626
+ @c.simple_table.should == '"a"'
456
627
  @c.set_dataset :b
457
- @c.simple_table.should == 'b'
628
+ @c.simple_table.should == '"b"'
458
629
  @c.set_dataset :b__a
459
- @c.simple_table.should == 'b.a'
630
+ @c.simple_table.should == '"b"."a"'
631
+ end
632
+
633
+ it "should have simple_table set if passed a simple select all dataset to set_dataset" do
634
+ @c.set_dataset @db[:a]
635
+ @c.simple_table.should == '"a"'
636
+ @c.set_dataset @db[:b]
637
+ @c.simple_table.should == '"b"'
638
+ @c.set_dataset @db[:b__a]
639
+ @c.simple_table.should == '"b"."a"'
460
640
  end
461
641
 
462
- it "should have simple_table = nil if passed a dataset to set_dataset" do
463
- @c.set_dataset @c.db[:a]
642
+ it "should simple_pk and simple_table respect dataset's identifier input methods" do
643
+ ds = @db[:ab]
644
+ ds.identifier_input_method = :reverse
645
+ @c.set_dataset ds
646
+ @c.simple_table.should == '"ba"'
647
+ @c.set_primary_key :cd
648
+ @c.simple_pk.should == '"dc"'
649
+
650
+ @c.set_dataset ds.from(:ef__gh)
651
+ @c.simple_table.should == '"fe"."hg"'
652
+ end
653
+
654
+ it "should have simple_table = nil if passed a non-simple select all dataset to set_dataset" do
655
+ @c.set_dataset @c.db[:a].filter(:active)
464
656
  @c.simple_table.should == nil
465
657
  end
466
658
 
467
659
  it "should have simple_table superclasses setting if inheriting" do
468
- @c.set_dataset :a
469
- Class.new(@c).simple_table.should == 'a'
470
- @c.instance_variable_set(:@simple_table, nil)
471
660
  Class.new(@c).simple_table.should == nil
472
- @c.instance_variable_set(:@simple_table, "'b'")
473
- Class.new(@c).simple_table.should == "'b'"
661
+ @c.set_dataset :a
662
+ Class.new(@c).simple_table.should == '"a"'
474
663
  end
475
664
 
476
665
  it "should use Dataset#with_sql if simple_table and simple_pk are true" do
477
666
  @c.set_dataset :a
478
- @c.dataset.should_receive(:with_sql).and_return(@c.dataset)
479
- @c[1]
667
+ @c.instance_dataset._fetch = @c.dataset._fetch = {:id => 1}
668
+ @c[1].should == @c.load(:id=>1)
669
+ @db.sqls.should == ['SELECT * FROM "a" WHERE "id" = 1']
480
670
  end
481
671
 
482
672
  it "should not use Dataset#with_sql if either simple_table or simple_pk is nil" do
483
- @c.set_dataset @c.dataset
484
- @c.dataset.should_not_receive(:with_sql)
485
- @c[1]
673
+ @c.set_dataset @db[:a].filter(:active)
674
+ @c.dataset._fetch = {:id => 1}
675
+ @c[1].should == @c.load(:id=>1)
676
+ @db.sqls.should == ['SELECT * FROM "a" WHERE ("active" AND ("id" = 1)) LIMIT 1']
677
+ end
678
+ end
679
+
680
+ describe "Model datasets #with_pk" do
681
+ before do
682
+ @c = Class.new(Sequel::Model(:a))
683
+ @ds = @c.dataset
684
+ @ds._fetch = {:id=>1}
685
+ MODEL_DB.reset
686
+ end
687
+
688
+ it "should return the first record where the primary key matches" do
689
+ @ds.with_pk(1).should == @c.load(:id=>1)
690
+ MODEL_DB.sqls.should == ["SELECT * FROM a WHERE (a.id = 1) LIMIT 1"]
691
+ end
692
+
693
+ it "should handle existing filters" do
694
+ @ds.filter(:a=>2).with_pk(1)
695
+ MODEL_DB.sqls.should == ["SELECT * FROM a WHERE ((a = 2) AND (a.id = 1)) LIMIT 1"]
696
+ end
697
+
698
+ it "should work with string values" do
699
+ @ds.with_pk("foo")
700
+ MODEL_DB.sqls.should == ["SELECT * FROM a WHERE (a.id = 'foo') LIMIT 1"]
701
+ end
702
+
703
+ it "should handle an array for composite primary keys" do
704
+ @c.set_primary_key :id1, :id2
705
+ @ds.with_pk([1, 2])
706
+ sqls = MODEL_DB.sqls
707
+ ["SELECT * FROM a WHERE ((a.id1 = 1) AND (a.id2 = 2)) LIMIT 1",
708
+ "SELECT * FROM a WHERE ((a.id2 = 2) AND (a.id1 = 1)) LIMIT 1"].should include(sqls.pop)
709
+ sqls.should == []
710
+ end
711
+
712
+ it "should have #[] consider an integer as a primary key lookup" do
713
+ @ds[1].should == @c.load(:id=>1)
714
+ MODEL_DB.sqls.should == ["SELECT * FROM a WHERE (a.id = 1) LIMIT 1"]
715
+ end
716
+
717
+ it "should not have #[] consider a string as a primary key lookup" do
718
+ @ds['foo'].should == @c.load(:id=>1)
719
+ MODEL_DB.sqls.should == ["SELECT * FROM a WHERE (foo) LIMIT 1"]
486
720
  end
487
721
  end