sequel 3.21.0 → 3.39.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 (352) hide show
  1. data/CHANGELOG +1061 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +103 -63
  4. data/Rakefile +59 -27
  5. data/bin/sequel +50 -26
  6. data/doc/active_record.rdoc +67 -51
  7. data/doc/advanced_associations.rdoc +189 -75
  8. data/doc/association_basics.rdoc +327 -79
  9. data/doc/cheat_sheet.rdoc +21 -21
  10. data/doc/core_extensions.rdoc +374 -0
  11. data/doc/dataset_basics.rdoc +10 -10
  12. data/doc/dataset_filtering.rdoc +54 -42
  13. data/doc/mass_assignment.rdoc +56 -0
  14. data/doc/migration.rdoc +89 -557
  15. data/doc/model_hooks.rdoc +80 -29
  16. data/doc/object_model.rdoc +547 -0
  17. data/doc/opening_databases.rdoc +114 -53
  18. data/doc/prepared_statements.rdoc +41 -15
  19. data/doc/querying.rdoc +137 -56
  20. data/doc/reflection.rdoc +36 -10
  21. data/doc/release_notes/3.22.0.txt +39 -0
  22. data/doc/release_notes/3.23.0.txt +172 -0
  23. data/doc/release_notes/3.24.0.txt +420 -0
  24. data/doc/release_notes/3.25.0.txt +88 -0
  25. data/doc/release_notes/3.26.0.txt +88 -0
  26. data/doc/release_notes/3.27.0.txt +82 -0
  27. data/doc/release_notes/3.28.0.txt +304 -0
  28. data/doc/release_notes/3.29.0.txt +459 -0
  29. data/doc/release_notes/3.30.0.txt +135 -0
  30. data/doc/release_notes/3.31.0.txt +146 -0
  31. data/doc/release_notes/3.32.0.txt +202 -0
  32. data/doc/release_notes/3.33.0.txt +157 -0
  33. data/doc/release_notes/3.34.0.txt +671 -0
  34. data/doc/release_notes/3.35.0.txt +144 -0
  35. data/doc/release_notes/3.36.0.txt +245 -0
  36. data/doc/release_notes/3.37.0.txt +338 -0
  37. data/doc/release_notes/3.38.0.txt +234 -0
  38. data/doc/release_notes/3.39.0.txt +237 -0
  39. data/doc/schema_modification.rdoc +585 -0
  40. data/doc/sharding.rdoc +99 -8
  41. data/doc/sql.rdoc +154 -112
  42. data/doc/testing.rdoc +169 -0
  43. data/doc/thread_safety.rdoc +17 -0
  44. data/doc/transactions.rdoc +137 -0
  45. data/doc/validations.rdoc +1 -1
  46. data/doc/virtual_rows.rdoc +78 -43
  47. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  48. data/lib/sequel/adapters/ado.rb +40 -18
  49. data/lib/sequel/adapters/amalgalite.rb +17 -9
  50. data/lib/sequel/adapters/db2.rb +175 -86
  51. data/lib/sequel/adapters/dbi.rb +15 -15
  52. data/lib/sequel/adapters/do/mysql.rb +17 -11
  53. data/lib/sequel/adapters/do/postgres.rb +2 -61
  54. data/lib/sequel/adapters/do/sqlite.rb +0 -10
  55. data/lib/sequel/adapters/do.rb +18 -36
  56. data/lib/sequel/adapters/firebird.rb +27 -208
  57. data/lib/sequel/adapters/ibmdb.rb +453 -0
  58. data/lib/sequel/adapters/informix.rb +6 -23
  59. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  60. data/lib/sequel/adapters/jdbc/db2.rb +56 -0
  61. data/lib/sequel/adapters/jdbc/derby.rb +325 -0
  62. data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
  63. data/lib/sequel/adapters/jdbc/h2.rb +73 -31
  64. data/lib/sequel/adapters/jdbc/hsqldb.rb +184 -0
  65. data/lib/sequel/adapters/jdbc/informix.rb +21 -0
  66. data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
  67. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  68. data/lib/sequel/adapters/jdbc/mysql.rb +7 -24
  69. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  70. data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
  71. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  72. data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
  73. data/lib/sequel/adapters/jdbc/sqlserver.rb +66 -0
  74. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  75. data/lib/sequel/adapters/jdbc.rb +279 -97
  76. data/lib/sequel/adapters/mock.rb +372 -0
  77. data/lib/sequel/adapters/mysql.rb +125 -222
  78. data/lib/sequel/adapters/mysql2.rb +65 -56
  79. data/lib/sequel/adapters/odbc/mssql.rb +17 -9
  80. data/lib/sequel/adapters/odbc.rb +28 -9
  81. data/lib/sequel/adapters/openbase.rb +3 -5
  82. data/lib/sequel/adapters/oracle.rb +349 -53
  83. data/lib/sequel/adapters/postgres.rb +368 -138
  84. data/lib/sequel/adapters/shared/access.rb +32 -9
  85. data/lib/sequel/adapters/shared/db2.rb +343 -0
  86. data/lib/sequel/adapters/shared/firebird.rb +221 -0
  87. data/lib/sequel/adapters/shared/informix.rb +53 -0
  88. data/lib/sequel/adapters/shared/mssql.rb +401 -116
  89. data/lib/sequel/adapters/shared/mysql.rb +424 -89
  90. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
  91. data/lib/sequel/adapters/shared/oracle.rb +257 -45
  92. data/lib/sequel/adapters/shared/postgres.rb +675 -279
  93. data/lib/sequel/adapters/shared/progress.rb +5 -8
  94. data/lib/sequel/adapters/shared/sqlite.rb +285 -96
  95. data/lib/sequel/adapters/sqlite.rb +101 -39
  96. data/lib/sequel/adapters/swift/mysql.rb +10 -12
  97. data/lib/sequel/adapters/swift/postgres.rb +13 -79
  98. data/lib/sequel/adapters/swift/sqlite.rb +9 -6
  99. data/lib/sequel/adapters/swift.rb +28 -19
  100. data/lib/sequel/adapters/tinytds.rb +174 -22
  101. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
  102. data/lib/sequel/adapters/utils/pg_types.rb +81 -0
  103. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  104. data/lib/sequel/ast_transformer.rb +194 -0
  105. data/lib/sequel/connection_pool/sharded_single.rb +11 -1
  106. data/lib/sequel/connection_pool/sharded_threaded.rb +33 -2
  107. data/lib/sequel/connection_pool/single.rb +5 -0
  108. data/lib/sequel/connection_pool/threaded.rb +43 -14
  109. data/lib/sequel/connection_pool.rb +10 -2
  110. data/lib/sequel/core.rb +143 -11
  111. data/lib/sequel/database/connecting.rb +38 -28
  112. data/lib/sequel/database/dataset.rb +4 -4
  113. data/lib/sequel/database/dataset_defaults.rb +63 -2
  114. data/lib/sequel/database/logging.rb +7 -2
  115. data/lib/sequel/database/misc.rb +190 -46
  116. data/lib/sequel/database/query.rb +272 -110
  117. data/lib/sequel/database/schema_generator.rb +103 -36
  118. data/lib/sequel/database/schema_methods.rb +300 -67
  119. data/lib/sequel/dataset/actions.rb +344 -90
  120. data/lib/sequel/dataset/features.rb +101 -8
  121. data/lib/sequel/dataset/graph.rb +42 -15
  122. data/lib/sequel/dataset/misc.rb +52 -25
  123. data/lib/sequel/dataset/mutation.rb +12 -7
  124. data/lib/sequel/dataset/prepared_statements.rb +68 -30
  125. data/lib/sequel/dataset/query.rb +305 -54
  126. data/lib/sequel/dataset/sql.rb +720 -292
  127. data/lib/sequel/dataset.rb +8 -0
  128. data/lib/sequel/exceptions.rb +4 -0
  129. data/lib/sequel/extensions/_pretty_table.rb +83 -0
  130. data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
  131. data/lib/sequel/extensions/blank.rb +4 -0
  132. data/lib/sequel/extensions/columns_introspection.rb +72 -0
  133. data/lib/sequel/extensions/constraint_validations.rb +451 -0
  134. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
  135. data/lib/sequel/extensions/eval_inspect.rb +173 -0
  136. data/lib/sequel/extensions/inflector.rb +4 -0
  137. data/lib/sequel/extensions/looser_typecasting.rb +5 -4
  138. data/lib/sequel/extensions/migration.rb +100 -11
  139. data/lib/sequel/extensions/named_timezones.rb +9 -0
  140. data/lib/sequel/extensions/null_dataset.rb +94 -0
  141. data/lib/sequel/extensions/pagination.rb +4 -0
  142. data/lib/sequel/extensions/pg_array.rb +537 -0
  143. data/lib/sequel/extensions/pg_array_ops.rb +263 -0
  144. data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
  145. data/lib/sequel/extensions/pg_hstore.rb +313 -0
  146. data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
  147. data/lib/sequel/extensions/pg_inet.rb +113 -0
  148. data/lib/sequel/extensions/pg_interval.rb +191 -0
  149. data/lib/sequel/extensions/pg_json.rb +208 -0
  150. data/lib/sequel/extensions/pg_range.rb +512 -0
  151. data/lib/sequel/extensions/pg_range_ops.rb +150 -0
  152. data/lib/sequel/extensions/pg_row.rb +572 -0
  153. data/lib/sequel/extensions/pg_row_ops.rb +182 -0
  154. data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
  155. data/lib/sequel/extensions/pretty_table.rb +17 -72
  156. data/lib/sequel/extensions/query.rb +8 -4
  157. data/lib/sequel/extensions/query_literals.rb +79 -0
  158. data/lib/sequel/extensions/schema_caching.rb +76 -0
  159. data/lib/sequel/extensions/schema_dumper.rb +282 -76
  160. data/lib/sequel/extensions/select_remove.rb +39 -0
  161. data/lib/sequel/extensions/server_block.rb +140 -0
  162. data/lib/sequel/extensions/split_array_nil.rb +65 -0
  163. data/lib/sequel/extensions/sql_expr.rb +8 -110
  164. data/lib/sequel/extensions/string_date_time.rb +4 -0
  165. data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
  166. data/lib/sequel/extensions/to_dot.rb +99 -83
  167. data/lib/sequel/model/associations.rb +1263 -409
  168. data/lib/sequel/model/base.rb +624 -171
  169. data/lib/sequel/model/errors.rb +1 -1
  170. data/lib/sequel/model/exceptions.rb +24 -2
  171. data/lib/sequel/model/inflections.rb +1 -1
  172. data/lib/sequel/model.rb +30 -11
  173. data/lib/sequel/no_core_ext.rb +2 -0
  174. data/lib/sequel/plugins/active_model.rb +13 -1
  175. data/lib/sequel/plugins/association_pks.rb +22 -4
  176. data/lib/sequel/plugins/caching.rb +25 -18
  177. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  178. data/lib/sequel/plugins/composition.rb +44 -12
  179. data/lib/sequel/plugins/constraint_validations.rb +198 -0
  180. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  181. data/lib/sequel/plugins/defaults_setter.rb +72 -0
  182. data/lib/sequel/plugins/dirty.rb +214 -0
  183. data/lib/sequel/plugins/eager_each.rb +59 -0
  184. data/lib/sequel/plugins/force_encoding.rb +6 -6
  185. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  186. data/lib/sequel/plugins/identity_map.rb +134 -15
  187. data/lib/sequel/plugins/instance_filters.rb +10 -0
  188. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  189. data/lib/sequel/plugins/json_serializer.rb +58 -6
  190. data/lib/sequel/plugins/list.rb +13 -2
  191. data/lib/sequel/plugins/many_through_many.rb +103 -51
  192. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  193. data/lib/sequel/plugins/nested_attributes.rb +150 -66
  194. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  195. data/lib/sequel/plugins/pg_row.rb +121 -0
  196. data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
  197. data/lib/sequel/plugins/prepared_statements.rb +167 -0
  198. data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
  199. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  200. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  201. data/lib/sequel/plugins/rcte_tree.rb +31 -17
  202. data/lib/sequel/plugins/schema.rb +8 -3
  203. data/lib/sequel/plugins/serialization.rb +98 -49
  204. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  205. data/lib/sequel/plugins/sharding.rb +21 -54
  206. data/lib/sequel/plugins/single_table_inheritance.rb +5 -3
  207. data/lib/sequel/plugins/static_cache.rb +99 -0
  208. data/lib/sequel/plugins/subclasses.rb +29 -3
  209. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  210. data/lib/sequel/plugins/timestamps.rb +1 -1
  211. data/lib/sequel/plugins/tree.rb +3 -3
  212. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  213. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  214. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  215. data/lib/sequel/plugins/validation_helpers.rb +55 -4
  216. data/lib/sequel/plugins/xml_serializer.rb +15 -4
  217. data/lib/sequel/sql.rb +649 -122
  218. data/lib/sequel/timezones.rb +67 -40
  219. data/lib/sequel/version.rb +1 -1
  220. data/spec/adapters/db2_spec.rb +146 -0
  221. data/spec/adapters/firebird_spec.rb +1 -1
  222. data/spec/adapters/mssql_spec.rb +194 -66
  223. data/spec/adapters/mysql_spec.rb +475 -306
  224. data/spec/adapters/oracle_spec.rb +92 -117
  225. data/spec/adapters/postgres_spec.rb +1982 -325
  226. data/spec/adapters/spec_helper.rb +9 -6
  227. data/spec/adapters/sqlite_spec.rb +203 -75
  228. data/spec/core/connection_pool_spec.rb +218 -93
  229. data/spec/core/database_spec.rb +956 -522
  230. data/spec/core/dataset_spec.rb +1631 -1242
  231. data/spec/core/expression_filters_spec.rb +690 -334
  232. data/spec/core/mock_adapter_spec.rb +453 -0
  233. data/spec/core/object_graph_spec.rb +88 -129
  234. data/spec/core/schema_generator_spec.rb +4 -4
  235. data/spec/core/schema_spec.rb +556 -53
  236. data/spec/core/spec_helper.rb +7 -48
  237. data/spec/core_extensions_spec.rb +626 -0
  238. data/spec/extensions/active_model_spec.rb +13 -0
  239. data/spec/extensions/arbitrary_servers_spec.rb +110 -0
  240. data/spec/extensions/association_autoreloading_spec.rb +18 -10
  241. data/spec/extensions/association_dependencies_spec.rb +15 -25
  242. data/spec/extensions/association_pks_spec.rb +66 -32
  243. data/spec/extensions/association_proxies_spec.rb +4 -4
  244. data/spec/extensions/boolean_readers_spec.rb +25 -25
  245. data/spec/extensions/caching_spec.rb +47 -51
  246. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  247. data/spec/extensions/columns_introspection_spec.rb +91 -0
  248. data/spec/extensions/composition_spec.rb +18 -13
  249. data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
  250. data/spec/extensions/constraint_validations_spec.rb +316 -0
  251. data/spec/extensions/dataset_associations_spec.rb +199 -0
  252. data/spec/extensions/defaults_setter_spec.rb +88 -0
  253. data/spec/extensions/dirty_spec.rb +155 -0
  254. data/spec/extensions/eager_each_spec.rb +34 -0
  255. data/spec/extensions/eval_inspect_spec.rb +67 -0
  256. data/spec/extensions/force_encoding_spec.rb +4 -2
  257. data/spec/extensions/hook_class_methods_spec.rb +97 -128
  258. data/spec/extensions/identity_map_spec.rb +142 -24
  259. data/spec/extensions/inflector_spec.rb +0 -4
  260. data/spec/extensions/instance_filters_spec.rb +11 -21
  261. data/spec/extensions/instance_hooks_spec.rb +72 -0
  262. data/spec/extensions/json_serializer_spec.rb +49 -12
  263. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  264. data/spec/extensions/list_spec.rb +49 -40
  265. data/spec/extensions/looser_typecasting_spec.rb +7 -7
  266. data/spec/extensions/many_through_many_spec.rb +368 -254
  267. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  268. data/spec/extensions/migration_spec.rb +140 -35
  269. data/spec/extensions/named_timezones_spec.rb +29 -11
  270. data/spec/extensions/nested_attributes_spec.rb +268 -89
  271. data/spec/extensions/null_dataset_spec.rb +85 -0
  272. data/spec/extensions/optimistic_locking_spec.rb +24 -21
  273. data/spec/extensions/pg_array_ops_spec.rb +112 -0
  274. data/spec/extensions/pg_array_spec.rb +320 -0
  275. data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
  276. data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
  277. data/spec/extensions/pg_hstore_spec.rb +194 -0
  278. data/spec/extensions/pg_inet_spec.rb +47 -0
  279. data/spec/extensions/pg_interval_spec.rb +72 -0
  280. data/spec/extensions/pg_json_spec.rb +99 -0
  281. data/spec/extensions/pg_range_ops_spec.rb +56 -0
  282. data/spec/extensions/pg_range_spec.rb +395 -0
  283. data/spec/extensions/pg_row_ops_spec.rb +58 -0
  284. data/spec/extensions/pg_row_plugin_spec.rb +49 -0
  285. data/spec/extensions/pg_row_spec.rb +323 -0
  286. data/spec/extensions/pg_statement_cache_spec.rb +208 -0
  287. data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
  288. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  289. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  290. data/spec/extensions/prepared_statements_spec.rb +87 -0
  291. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  292. data/spec/extensions/pretty_table_spec.rb +7 -6
  293. data/spec/extensions/query_literals_spec.rb +167 -0
  294. data/spec/extensions/query_spec.rb +9 -3
  295. data/spec/extensions/rcte_tree_spec.rb +50 -43
  296. data/spec/extensions/schema_caching_spec.rb +41 -0
  297. data/spec/extensions/schema_dumper_spec.rb +434 -49
  298. data/spec/extensions/schema_spec.rb +30 -49
  299. data/spec/extensions/select_remove_spec.rb +38 -0
  300. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  301. data/spec/extensions/serialization_spec.rb +86 -48
  302. data/spec/extensions/server_block_spec.rb +90 -0
  303. data/spec/extensions/sharding_spec.rb +69 -143
  304. data/spec/extensions/single_table_inheritance_spec.rb +23 -29
  305. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  306. data/spec/extensions/spec_helper.rb +34 -67
  307. data/spec/extensions/split_array_nil_spec.rb +24 -0
  308. data/spec/extensions/sql_expr_spec.rb +29 -60
  309. data/spec/extensions/static_cache_spec.rb +145 -0
  310. data/spec/extensions/subclasses_spec.rb +14 -0
  311. data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
  312. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  313. data/spec/extensions/timestamps_spec.rb +6 -6
  314. data/spec/extensions/to_dot_spec.rb +8 -11
  315. data/spec/extensions/touch_spec.rb +13 -14
  316. data/spec/extensions/tree_spec.rb +11 -26
  317. data/spec/extensions/typecast_on_load_spec.rb +9 -6
  318. data/spec/extensions/update_primary_key_spec.rb +30 -24
  319. data/spec/extensions/validation_class_methods_spec.rb +58 -67
  320. data/spec/extensions/validation_helpers_spec.rb +31 -37
  321. data/spec/extensions/xml_serializer_spec.rb +29 -4
  322. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
  323. data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
  324. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
  325. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
  326. data/spec/integration/associations_test.rb +659 -21
  327. data/spec/integration/database_test.rb +11 -5
  328. data/spec/integration/dataset_test.rb +717 -129
  329. data/spec/integration/eager_loader_test.rb +38 -54
  330. data/spec/integration/migrator_test.rb +2 -3
  331. data/spec/integration/model_test.rb +81 -2
  332. data/spec/integration/plugin_test.rb +604 -147
  333. data/spec/integration/prepared_statement_test.rb +272 -128
  334. data/spec/integration/schema_test.rb +367 -57
  335. data/spec/integration/spec_helper.rb +42 -32
  336. data/spec/integration/timezone_test.rb +38 -12
  337. data/spec/integration/transaction_test.rb +183 -8
  338. data/spec/integration/type_test.rb +31 -8
  339. data/spec/model/association_reflection_spec.rb +207 -8
  340. data/spec/model/associations_spec.rb +1206 -693
  341. data/spec/model/base_spec.rb +334 -100
  342. data/spec/model/dataset_methods_spec.rb +45 -27
  343. data/spec/model/eager_loading_spec.rb +828 -692
  344. data/spec/model/hooks_spec.rb +355 -67
  345. data/spec/model/model_spec.rb +251 -179
  346. data/spec/model/plugins_spec.rb +24 -13
  347. data/spec/model/record_spec.rb +506 -232
  348. data/spec/model/spec_helper.rb +16 -77
  349. data/spec/model/validations_spec.rb +38 -2
  350. data/spec/rcov.opts +2 -0
  351. metadata +209 -80
  352. data/spec/core/core_sql_spec.rb +0 -451
@@ -12,13 +12,48 @@ describe "Sequel::Model()" do
12
12
  c.dataset.should == ds
13
13
  end
14
14
 
15
- it "should return a model subclass with a dataset with the default database and given table name if given a symbol" do
15
+ it "should return a model subclass with a dataset with the default database and given table name if given a Symbol" do
16
16
  c = Sequel::Model(:blah)
17
17
  c.superclass.should == Sequel::Model
18
18
  c.db.should == @db
19
19
  c.table_name.should == :blah
20
20
  end
21
21
 
22
+ it "should return a model subclass with a dataset with the default database and given table name if given a LiteralString" do
23
+ c = Sequel::Model(Sequel.lit('blah'))
24
+ c.superclass.should == Sequel::Model
25
+ c.db.should == @db
26
+ c.table_name.should == Sequel.lit('blah')
27
+ end
28
+
29
+ it "should return a model subclass with a dataset with the default database and given table name if given an SQL::Identifier" do
30
+ c = Sequel::Model(Sequel.identifier(:blah))
31
+ c.superclass.should == Sequel::Model
32
+ c.db.should == @db
33
+ c.table_name.should == Sequel.identifier(:blah)
34
+ end
35
+
36
+ it "should return a model subclass with a dataset with the default database and given table name if given an SQL::QualifiedIdentifier" do
37
+ c = Sequel::Model(Sequel.qualify(:boo, :blah))
38
+ c.superclass.should == Sequel::Model
39
+ c.db.should == @db
40
+ c.table_name.should == Sequel.qualify(:boo, :blah)
41
+ end
42
+
43
+ it "should return a model subclass with a dataset with the default database and given table name if given an SQL::AliasedExpression" do
44
+ c = Sequel::Model(Sequel.as(:blah, :boo))
45
+ c.superclass.should == Sequel::Model
46
+ c.db.should == @db
47
+ c.table_name.should == :boo
48
+ end
49
+
50
+ it "should return a model subclass with the given dataset if given a dataset using an SQL::Identifier" do
51
+ ds = @db[Sequel.identifier(:blah)]
52
+ c = Sequel::Model(ds)
53
+ c.superclass.should == Sequel::Model
54
+ c.dataset.should == ds
55
+ end
56
+
22
57
  it "should return a model subclass associated to the given database if given a database" do
23
58
  db = Sequel::Database.new
24
59
  c = Sequel::Model(db)
@@ -32,7 +67,11 @@ describe "Sequel::Model()" do
32
67
  end
33
68
 
34
69
  describe "reloading" do
70
+ before do
71
+ Sequel::Model.cache_anonymous_models = true
72
+ end
35
73
  after do
74
+ Sequel::Model.cache_anonymous_models = false
36
75
  Object.send(:remove_const, :Album) if defined?(::Album)
37
76
  end
38
77
 
@@ -43,6 +82,34 @@ describe "Sequel::Model()" do
43
82
  end.should_not raise_error
44
83
  end
45
84
 
85
+ it "should work without raising an exception with an SQL::Identifier " do
86
+ proc do
87
+ class ::Album < Sequel::Model(Sequel.identifier(:table)); end
88
+ class ::Album < Sequel::Model(Sequel.identifier(:table)); end
89
+ end.should_not raise_error
90
+ end
91
+
92
+ it "should work without raising an exception with an SQL::QualifiedIdentifier " do
93
+ proc do
94
+ class ::Album < Sequel::Model(Sequel.qualify(:schema, :table)); end
95
+ class ::Album < Sequel::Model(Sequel.qualify(:schema, :table)); end
96
+ end.should_not raise_error
97
+ end
98
+
99
+ it "should work without raising an exception with an SQL::AliasedExpression" do
100
+ proc do
101
+ class ::Album < Sequel::Model(Sequel.as(:table, :alias)); end
102
+ class ::Album < Sequel::Model(Sequel.as(:table, :alias)); end
103
+ end.should_not raise_error
104
+ end
105
+
106
+ it "should work without raising an exception with an LiteralString" do
107
+ proc do
108
+ class ::Album < Sequel::Model(Sequel.lit('table')); end
109
+ class ::Album < Sequel::Model(Sequel.lit('table')); end
110
+ end.should_not raise_error
111
+ end
112
+
46
113
  it "should work without raising an exception with a database" do
47
114
  proc do
48
115
  class ::Album < Sequel::Model(@db); end
@@ -56,6 +123,21 @@ describe "Sequel::Model()" do
56
123
  class ::Album < Sequel::Model(@db[:table]); end
57
124
  end.should_not raise_error
58
125
  end
126
+
127
+ it "should work without raising an exception with a dataset with an SQL::Identifier" do
128
+ proc do
129
+ class ::Album < Sequel::Model(@db[Sequel.identifier(:table)]); end
130
+ class ::Album < Sequel::Model(@db[Sequel.identifier(:table)]); end
131
+ end.should_not raise_error
132
+ end
133
+
134
+ it "should raise an exception if anonymous model caching is disabled" do
135
+ Sequel::Model.cache_anonymous_models = false
136
+ proc do
137
+ class ::Album < Sequel::Model(@db[Sequel.identifier(:table)]); end
138
+ class ::Album < Sequel::Model(@db[Sequel.identifier(:table)]); end
139
+ end.should raise_error
140
+ end
59
141
  end
60
142
  end
61
143
 
@@ -70,17 +152,16 @@ describe Sequel::Model do
70
152
  it "should be associated with a dataset" do
71
153
  model_a = Class.new(Sequel::Model) { set_dataset MODEL_DB[:as] }
72
154
 
73
- model_a.dataset.should be_a_kind_of(MockDataset)
155
+ model_a.dataset.should be_a_kind_of(Sequel::Mock::Dataset)
74
156
  model_a.dataset.opts[:from].should == [:as]
75
157
 
76
158
  model_b = Class.new(Sequel::Model) { set_dataset MODEL_DB[:bs] }
77
159
 
78
- model_b.dataset.should be_a_kind_of(MockDataset)
160
+ model_b.dataset.should be_a_kind_of(Sequel::Mock::Dataset)
79
161
  model_b.dataset.opts[:from].should == [:bs]
80
162
 
81
163
  model_a.dataset.opts[:from].should == [:as]
82
164
  end
83
-
84
165
  end
85
166
 
86
167
  describe Sequel::Model, "dataset & schema" do
@@ -106,12 +187,36 @@ describe Sequel::Model, "dataset & schema" do
106
187
  @model.table_name.should == :foo
107
188
  end
108
189
 
109
- it "set_dataset should take a symbol" do
190
+ it "set_dataset should take a Symbol" do
110
191
  @model.db = MODEL_DB
111
192
  @model.set_dataset(:foo)
112
193
  @model.table_name.should == :foo
113
194
  end
114
195
 
196
+ it "set_dataset should take a LiteralString" do
197
+ @model.db = MODEL_DB
198
+ @model.set_dataset(Sequel.lit('foo'))
199
+ @model.table_name.should == Sequel.lit('foo')
200
+ end
201
+
202
+ it "set_dataset should take an SQL::Identifier" do
203
+ @model.db = MODEL_DB
204
+ @model.set_dataset(Sequel.identifier(:foo))
205
+ @model.table_name.should == Sequel.identifier(:foo)
206
+ end
207
+
208
+ it "set_dataset should take an SQL::QualifiedIdentifier" do
209
+ @model.db = MODEL_DB
210
+ @model.set_dataset(Sequel.qualify(:bar, :foo))
211
+ @model.table_name.should == Sequel.qualify(:bar, :foo)
212
+ end
213
+
214
+ it "set_dataset should take an SQL::AliasedExpression" do
215
+ @model.db = MODEL_DB
216
+ @model.set_dataset(Sequel.as(:foo, :bar))
217
+ @model.table_name.should == :bar
218
+ end
219
+
115
220
  it "table_name should respect table aliases" do
116
221
  @model.set_dataset(:foo___x)
117
222
  @model.table_name.should == :x
@@ -121,16 +226,30 @@ describe Sequel::Model, "dataset & schema" do
121
226
  proc{@model.set_dataset(Object.new)}.should raise_error(Sequel::Error)
122
227
  end
123
228
 
124
- it "set_dataset should add the destroy method to the dataset" do
229
+ it "set_dataset should add the destroy method to the dataset that destroys each object" do
125
230
  ds = MODEL_DB[:foo]
126
231
  ds.should_not respond_to(:destroy)
127
232
  @model.set_dataset(ds)
128
233
  ds.should respond_to(:destroy)
234
+ MODEL_DB.sqls
235
+ ds._fetch = [{:id=>1}, {:id=>2}]
236
+ ds.destroy.should == 2
237
+ MODEL_DB.sqls.should == ["SELECT * FROM foo", "DELETE FROM foo WHERE id = 1", "DELETE FROM foo WHERE id = 2"]
238
+ end
239
+
240
+ it "set_dataset should add the destroy method that respects sharding with transactions" do
241
+ db = Sequel.mock(:servers=>{:s1=>{}})
242
+ ds = db[:foo].server(:s1)
243
+ @model.use_transactions = true
244
+ @model.set_dataset(ds)
245
+ db.sqls
246
+ ds.destroy.should == 0
247
+ db.sqls.should == ["BEGIN -- s1", "SELECT * FROM foo -- s1", "COMMIT -- s1"]
129
248
  end
130
249
 
131
250
  it "should raise an error on set_dataset if there is an error connecting to the database" do
132
251
  @model.meta_def(:columns){raise Sequel::DatabaseConnectionError}
133
- proc{@model.set_dataset(MODEL_DB[:foo].join(:blah))}.should raise_error
252
+ proc{@model.set_dataset(Sequel::Database.new[:foo].join(:blah))}.should raise_error
134
253
  end
135
254
 
136
255
  it "should not raise an error if there is a problem getting the columns for a dataset" do
@@ -149,9 +268,8 @@ describe Sequel::Model, "dataset & schema" do
149
268
  end
150
269
  end
151
270
 
152
- describe Sequel::Model, "constructor" do
153
-
154
- before(:each) do
271
+ describe Sequel::Model, "constructors" do
272
+ before do
155
273
  @m = Class.new(Sequel::Model)
156
274
  @m.columns :a, :b
157
275
  end
@@ -170,11 +288,38 @@ describe Sequel::Model, "constructor" do
170
288
  m.values[:a].should == 1
171
289
  end
172
290
 
291
+ it "should have dataset row_proc create an existing object" do
292
+ @m.dataset = Sequel::Dataset.new(nil)
293
+ o = @m.dataset.row_proc.call(:a=>1)
294
+ o.should be_a_kind_of(@m)
295
+ o.values.should == {:a=>1}
296
+ o.new?.should be_false
297
+ end
298
+
299
+ it "should have .call create an existing object" do
300
+ o = @m.call(:a=>1)
301
+ o.should be_a_kind_of(@m)
302
+ o.values.should == {:a=>1}
303
+ o.new?.should be_false
304
+ end
305
+
306
+ it "should have .load create an existing object" do
307
+ o = @m.load(:a=>1)
308
+ o.should be_a_kind_of(@m)
309
+ o.values.should == {:a=>1}
310
+ o.new?.should be_false
311
+ end
312
+
313
+ it "should have .new with a second true argument create an existing object" do
314
+ o = @m.new({:a=>1}, true)
315
+ o.should be_a_kind_of(@m)
316
+ o.values.should == {:a=>1}
317
+ o.new?.should be_false
318
+ end
173
319
  end
174
320
 
175
321
  describe Sequel::Model, "new" do
176
-
177
- before(:each) do
322
+ before do
178
323
  @m = Class.new(Sequel::Model) do
179
324
  set_dataset MODEL_DB[:items]
180
325
  columns :x, :id
@@ -194,15 +339,8 @@ describe Sequel::Model, "new" do
194
339
  end
195
340
 
196
341
  it "should use the last inserted id as primary key if not in values" do
197
- d = @m.dataset
198
- def d.insert(*args)
199
- super
200
- 1234
201
- end
202
-
203
- def d.first
204
- {:x => 1, :id => 1234}
205
- end
342
+ @m.instance_dataset._fetch = @m.dataset._fetch = {:x => 1, :id => 1234}
343
+ @m.instance_dataset.autoid = @m.dataset.autoid = 1234
206
344
 
207
345
  o = @m.new(:x => 1)
208
346
  o.save
@@ -212,25 +350,23 @@ describe Sequel::Model, "new" do
212
350
  o.save
213
351
  o.id.should == 333
214
352
  end
215
-
216
353
  end
217
354
 
218
355
  describe Sequel::Model, ".subset" do
219
356
  before do
220
- MODEL_DB.reset
221
-
222
357
  @c = Class.new(Sequel::Model(:items))
358
+ MODEL_DB.reset
223
359
  end
224
360
 
225
361
  specify "should create a filter on the underlying dataset" do
226
362
  proc {@c.new_only}.should raise_error(NoMethodError)
227
363
 
228
- @c.subset(:new_only) {:age.sql_number < 'new'}
364
+ @c.subset(:new_only){age < 'new'}
229
365
 
230
366
  @c.new_only.sql.should == "SELECT * FROM items WHERE (age < 'new')"
231
367
  @c.dataset.new_only.sql.should == "SELECT * FROM items WHERE (age < 'new')"
232
368
 
233
- @c.subset(:pricey) {:price.sql_number > 100}
369
+ @c.subset(:pricey){price > 100}
234
370
 
235
371
  @c.pricey.sql.should == "SELECT * FROM items WHERE (price > 100)"
236
372
  @c.dataset.pricey.sql.should == "SELECT * FROM items WHERE (price > 100)"
@@ -247,44 +383,31 @@ describe Sequel::Model, ".subset" do
247
383
  end
248
384
 
249
385
  describe Sequel::Model, ".find" do
250
-
251
- before(:each) do
252
- MODEL_DB.reset
253
-
386
+ before do
254
387
  @c = Class.new(Sequel::Model(:items))
255
-
256
- $cache_dataset_row = {:name => 'sharon', :id => 1}
257
- @dataset = @c.dataset
258
- $sqls = []
259
- @dataset.extend(Module.new {
260
- def fetch_rows(sql)
261
- $sqls << sql
262
- yield $cache_dataset_row
263
- end
264
- })
388
+ @c.dataset._fetch = {:name => 'sharon', :id => 1}
389
+ MODEL_DB.reset
265
390
  end
266
391
 
267
392
  it "should return the first record matching the given filter" do
268
393
  @c.find(:name => 'sharon').should be_a_kind_of(@c)
269
- $sqls.last.should == "SELECT * FROM items WHERE (name = 'sharon') LIMIT 1"
394
+ MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (name = 'sharon') LIMIT 1"]
270
395
 
271
- @c.find(:name.like('abc%')).should be_a_kind_of(@c)
272
- $sqls.last.should == "SELECT * FROM items WHERE (name LIKE 'abc%') LIMIT 1"
396
+ @c.find(Sequel.expr(:name).like('abc%')).should be_a_kind_of(@c)
397
+ MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (name LIKE 'abc%') LIMIT 1"]
273
398
  end
274
399
 
275
400
  specify "should accept filter blocks" do
276
- @c.find{:id.sql_number > 1}.should be_a_kind_of(@c)
277
- $sqls.last.should == "SELECT * FROM items WHERE (id > 1) LIMIT 1"
401
+ @c.find{id > 1}.should be_a_kind_of(@c)
402
+ MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (id > 1) LIMIT 1"]
278
403
 
279
- @c.find {(:x.sql_number > 1) & (:y.sql_number < 2)}.should be_a_kind_of(@c)
280
- $sqls.last.should == "SELECT * FROM items WHERE ((x > 1) AND (y < 2)) LIMIT 1"
404
+ @c.find{(x > 1) & (y < 2)}.should be_a_kind_of(@c)
405
+ MODEL_DB.sqls.should == ["SELECT * FROM items WHERE ((x > 1) AND (y < 2)) LIMIT 1"]
281
406
  end
282
-
283
407
  end
284
408
 
285
409
  describe Sequel::Model, ".fetch" do
286
-
287
- before(:each) do
410
+ before do
288
411
  MODEL_DB.reset
289
412
  @c = Class.new(Sequel::Model(:items))
290
413
  end
@@ -301,80 +424,53 @@ describe Sequel::Model, ".fetch" do
301
424
  end
302
425
 
303
426
  describe Sequel::Model, ".find_or_create" do
304
-
305
- before(:each) do
306
- MODEL_DB.reset
427
+ before do
307
428
  @c = Class.new(Sequel::Model(:items)) do
308
- no_primary_key
429
+ set_primary_key :id
309
430
  columns :x
310
431
  end
432
+ MODEL_DB.reset
311
433
  end
312
434
 
313
435
  it "should find the record" do
314
- @c.find_or_create(:x => 1)
436
+ @c.find_or_create(:x => 1).should == @c.load(:x=>1, :id=>1)
315
437
  MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (x = 1) LIMIT 1"]
316
-
317
- MODEL_DB.reset
318
438
  end
319
439
 
320
440
  it "should create the record if not found" do
321
- @c.meta_def(:find) do |*args|
322
- dataset.filter(*args).first
323
- nil
324
- end
325
-
326
- @c.find_or_create(:x => 1)
327
- MODEL_DB.sqls.should == [
328
- "SELECT * FROM items WHERE (x = 1) LIMIT 1",
329
- "INSERT INTO items (x) VALUES (1)"
330
- ]
441
+ @c.instance_dataset._fetch = @c.dataset._fetch = [[], {:x=>1, :id=>1}]
442
+ @c.instance_dataset.autoid = @c.dataset.autoid = 1
443
+ @c.find_or_create(:x => 1).should == @c.load(:x=>1, :id=>1)
444
+ MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (x = 1) LIMIT 1",
445
+ "INSERT INTO items (x) VALUES (1)",
446
+ "SELECT * FROM items WHERE (id = 1) LIMIT 1"]
331
447
  end
332
448
 
333
449
  it "should pass the new record to be created to the block if no record is found" do
334
- @c.meta_def(:find){|*|}
335
- @c.find_or_create(:x => 1){|x| x[:y] = 2}
336
- ["INSERT INTO items (x, y) VALUES (1, 2)", "INSERT INTO items (y, x) VALUES (2, 1)"].should include(MODEL_DB.sqls.first)
450
+ @c.instance_dataset._fetch = @c.dataset._fetch = [[], {:x=>1, :id=>1}]
451
+ @c.instance_dataset.autoid = @c.dataset.autoid = 1
452
+ @c.find_or_create(:x => 1){|x| x[:y] = 2}.should == @c.load(:x=>1, :id=>1)
453
+ sqls = MODEL_DB.sqls
454
+ sqls.first.should == "SELECT * FROM items WHERE (x = 1) LIMIT 1"
455
+ ["INSERT INTO items (x, y) VALUES (1, 2)", "INSERT INTO items (y, x) VALUES (2, 1)"].should include(sqls[1])
456
+ sqls.last.should == "SELECT * FROM items WHERE (id = 1) LIMIT 1"
337
457
  end
338
458
  end
339
459
 
340
460
  describe Sequel::Model, ".all" do
341
-
342
- before(:each) do
343
- MODEL_DB.reset
344
- @c = Class.new(Sequel::Model(:items)) do
345
- no_primary_key
346
- end
347
-
348
- @c.dataset.meta_def(:all) {1234}
349
- end
350
-
351
461
  it "should return all records in the dataset" do
352
- @c.all.should == 1234
462
+ c = Class.new(Sequel::Model(:items))
463
+ c.all.should == [c.load(:x=>1, :id=>1)]
353
464
  end
354
-
355
- end
356
-
357
- class DummyModelBased < Sequel::Model(:blog)
358
- end
359
-
360
- describe Sequel::Model, "(:tablename)" do
361
-
362
- it "should allow reopening of descendant classes" do
363
- proc do
364
- eval "class DummyModelBased < Sequel::Model(:blog); end"
365
- end.should_not raise_error
366
- end
367
-
368
465
  end
369
466
 
370
467
  describe Sequel::Model, "A model class without a primary key" do
371
-
372
- before(:each) do
373
- MODEL_DB.reset
468
+ before do
374
469
  @c = Class.new(Sequel::Model(:items)) do
375
470
  columns :x
376
471
  no_primary_key
377
472
  end
473
+ MODEL_DB.reset
378
474
  end
379
475
 
380
476
  it "should be able to insert records without selecting them back" do
@@ -387,8 +483,11 @@ describe Sequel::Model, "A model class without a primary key" do
387
483
  end
388
484
 
389
485
  it "should raise when deleting" do
390
- o = @c.new
391
- proc {o.delete}.should raise_error
486
+ proc{@c.load(:x=>1).delete}.should raise_error
487
+ end
488
+
489
+ it "should raise when updating" do
490
+ proc{@c.load(:x=>1).update(:x=>2)}.should raise_error
392
491
  end
393
492
 
394
493
  it "should insert a record when saving" do
@@ -397,37 +496,30 @@ describe Sequel::Model, "A model class without a primary key" do
397
496
  o.save
398
497
  MODEL_DB.sqls.should == ['INSERT INTO items (x) VALUES (2)']
399
498
  end
400
-
401
499
  end
402
500
 
403
501
  describe Sequel::Model, "attribute accessors" do
404
502
  before do
405
- MODEL_DB.reset
406
- @dataset = Sequel::Dataset.new(MODEL_DB)
407
- def @dataset.columns; [:x, :y]; end
408
- @c = Class.new(Sequel::Model) do
409
- def self.db_schema
410
- set_columns(Array(@columns))
411
- @db_schema = {:x=>{:type=>:integer}, :y=>{:type=>:integer}}
412
- end
413
- def self.set_dataset(ds, opts={})
414
- @columns = ds.columns
415
- db_schema
416
- end
503
+ db = Sequel.mock
504
+ def db.schema(*)
505
+ [[:x, {:type=>:integer}], [:z, {:type=>:integer}]]
417
506
  end
507
+ @dataset = db[:items].columns(:x, :z)
508
+ @c = Class.new(Sequel::Model)
509
+ MODEL_DB.reset
418
510
  end
419
511
 
420
512
  it "should be created on set_dataset" do
421
- %w'x y x= y='.each do |x|
422
- @c.instance_methods.collect{|y| y.to_s}.should_not include(x)
513
+ %w'x z x= z='.each do |x|
514
+ @c.instance_methods.collect{|z| z.to_s}.should_not include(x)
423
515
  end
424
516
  @c.set_dataset(@dataset)
425
- %w'x y x= y='.each do |x|
426
- @c.instance_methods.collect{|y| y.to_s}.should include(x)
517
+ %w'x z x= z='.each do |x|
518
+ @c.instance_methods.collect{|z| z.to_s}.should include(x)
427
519
  end
428
520
  o = @c.new
429
- %w'x y x= y='.each do |x|
430
- o.methods.collect{|y| y.to_s}.should include(x)
521
+ %w'x z x= z='.each do |x|
522
+ o.methods.collect{|z| z.to_s}.should include(x)
431
523
  end
432
524
 
433
525
  o.x.should be_nil
@@ -446,7 +538,7 @@ describe Sequel::Model, "attribute accessors" do
446
538
  end
447
539
 
448
540
  it "should have a working typecasting setter even if the column is not selected" do
449
- @c.set_dataset(@dataset.select(:y))
541
+ @c.set_dataset(@dataset.select(:z).columns(:z))
450
542
  o = @c.new
451
543
 
452
544
  o.x = '34'
@@ -454,7 +546,7 @@ describe Sequel::Model, "attribute accessors" do
454
546
  end
455
547
 
456
548
  it "should typecast if the new value is the same as the existing but has a different class" do
457
- @c.set_dataset(@dataset.select(:y))
549
+ @c.set_dataset(@dataset.select(:z).columns(:z))
458
550
  o = @c.new
459
551
 
460
552
  o.x = 34
@@ -466,58 +558,57 @@ describe Sequel::Model, "attribute accessors" do
466
558
  end
467
559
 
468
560
  describe Sequel::Model, ".[]" do
469
-
470
- before(:each) do
471
- MODEL_DB.reset
472
-
561
+ before do
473
562
  @c = Class.new(Sequel::Model(:items))
474
-
475
- $cache_dataset_row = {:name => 'sharon', :id => 1}
476
- @dataset = @c.dataset
477
- $sqls = []
478
- @dataset.extend(Module.new {
479
- def fetch_rows(sql)
480
- $sqls << sql
481
- yield $cache_dataset_row
482
- end
483
- })
563
+ @c.dataset._fetch = {:name => 'sharon', :id => 1}
564
+ MODEL_DB.reset
484
565
  end
485
566
 
486
567
  it "should return the first record for the given pk" do
487
- @c[1].should be_a_kind_of(@c)
488
- $sqls.last.should == "SELECT * FROM items WHERE (id = 1) LIMIT 1"
489
- @c[9999].should be_a_kind_of(@c)
490
- $sqls.last.should == "SELECT * FROM items WHERE (id = 9999) LIMIT 1"
568
+ @c[1].should == @c.load(:name => 'sharon', :id => 1)
569
+ MODEL_DB.sqls.should == ["SELECT * FROM items WHERE id = 1"]
570
+ @c[9999].should == @c.load(:name => 'sharon', :id => 1)
571
+ MODEL_DB.sqls.should == ["SELECT * FROM items WHERE id = 9999"]
572
+ end
573
+
574
+ it "should have #[] return nil if no rows match" do
575
+ @c.dataset._fetch = []
576
+ @c[1].should == nil
577
+ MODEL_DB.sqls.should == ["SELECT * FROM items WHERE id = 1"]
491
578
  end
492
579
 
493
580
  it "should work correctly for custom primary key" do
494
581
  @c.set_primary_key :name
495
- @c['sharon'].should be_a_kind_of(@c)
496
- $sqls.last.should == "SELECT * FROM items WHERE (name = 'sharon') LIMIT 1"
582
+ @c['sharon'].should == @c.load(:name => 'sharon', :id => 1)
583
+ MODEL_DB.sqls.should == ["SELECT * FROM items WHERE name = 'sharon'"]
584
+ end
585
+
586
+ it "should return the first record for the given pk for a filtered dataset" do
587
+ @c.dataset = @c.dataset.filter(:active=>true)
588
+ @c[1].should == @c.load(:name => 'sharon', :id => 1)
589
+ MODEL_DB.sqls.should == ["SELECT * FROM items WHERE ((active IS TRUE) AND (id = 1)) LIMIT 1"]
497
590
  end
498
591
 
499
592
  it "should work correctly for composite primary key specified as array" do
500
593
  @c.set_primary_key [:node_id, :kind]
501
594
  @c[3921, 201].should be_a_kind_of(@c)
502
- $sqls.last.should =~ \
503
- /^SELECT \* FROM items WHERE \((\(node_id = 3921\) AND \(kind = 201\))|(\(kind = 201\) AND \(node_id = 3921\))\) LIMIT 1$/
595
+ sqls = MODEL_DB.sqls
596
+ sqls.length.should == 1
597
+ sqls.first.should =~ /^SELECT \* FROM items WHERE \((\(node_id = 3921\) AND \(kind = 201\))|(\(kind = 201\) AND \(node_id = 3921\))\) LIMIT 1$/
504
598
  end
505
599
 
506
600
  it "should work correctly for composite primary key specified as separate arguments" do
507
601
  @c.set_primary_key :node_id, :kind
508
602
  @c[3921, 201].should be_a_kind_of(@c)
509
- $sqls.last.should =~ \
510
- /^SELECT \* FROM items WHERE \((\(node_id = 3921\) AND \(kind = 201\))|(\(kind = 201\) AND \(node_id = 3921\))\) LIMIT 1$/
603
+ sqls = MODEL_DB.sqls
604
+ sqls.length.should == 1
605
+ sqls.first.should =~ /^SELECT \* FROM items WHERE \((\(node_id = 3921\) AND \(kind = 201\))|(\(kind = 201\) AND \(node_id = 3921\))\) LIMIT 1$/
511
606
  end
512
607
  end
513
608
 
514
609
  describe "Model#inspect" do
515
- before do
516
- @o = Sequel::Model.load(:x => 333)
517
- end
518
-
519
610
  specify "should include the class name and the values" do
520
- @o.inspect.should == '#<Sequel::Model @values={:x=>333}>'
611
+ Sequel::Model.load(:x => 333).inspect.should == '#<Sequel::Model @values={:x=>333}>'
521
612
  end
522
613
  end
523
614
 
@@ -526,16 +617,13 @@ describe "Model.db_schema" do
526
617
  @c = Class.new(Sequel::Model(:items)) do
527
618
  def self.columns; orig_columns; end
528
619
  end
529
- @dataset = Sequel::Dataset.new(nil).from(:items)
530
- @dataset.meta_def(:db){@db ||= Sequel::Database.new}
531
- def @dataset.naked; self; end
532
- def @dataset.columns; []; end
533
- def @dataset.def_mutation_method(*names); end
620
+ @db = Sequel.mock
621
+ @dataset = @db[:items]
534
622
  end
535
623
 
536
624
  specify "should use the database's schema_for_table and set the columns and dataset columns" do
537
625
  d = @dataset.db
538
- def d.schema(table, opts = {})
626
+ def @db.schema(table, opts = {})
539
627
  [[:x, {:type=>:integer}], [:y, {:type=>:string}]]
540
628
  end
541
629
  @c.dataset = @dataset
@@ -545,36 +633,20 @@ describe "Model.db_schema" do
545
633
  end
546
634
 
547
635
  specify "should not restrict the schema for datasets with a :select option" do
548
- ds = @dataset.select(:x, :y___z)
549
- d = ds.db
550
- def d.schema(table, opts = {})
636
+ def @c.columns; [:x, :z]; end
637
+ def @db.schema(table, opts = {})
551
638
  [[:x, {:type=>:integer}], [:y, {:type=>:string}]]
552
639
  end
553
- def @c.columns; [:x, :z]; end
554
- @c.dataset = ds
640
+ @c.dataset = @dataset.select(:x, :y___z)
555
641
  @c.db_schema.should == {:x=>{:type=>:integer}, :z=>{}, :y=>{:type=>:string}}
556
642
  end
557
643
 
558
- specify "should not use schema if the dataset uses multiple tables or custom sql" do
559
- ds = @dataset.join(:x, :id)
560
- d = ds.db
561
- e = false
562
- d.meta_def(:schema){|table, *opts| e = true}
563
- def @c.columns; [:x]; end
564
- @c.dataset = ds
565
- @c.db_schema.should == {:x=>{}}
566
- e.should == false
567
- end
568
-
569
644
  specify "should fallback to fetching records if schema raises an error" do
570
- ds = @dataset.join(:x, :id)
571
- d = ds.db
572
- def d.schema(table, opts={})
573
- raise StandardError
645
+ def @db.schema(table, opts={})
646
+ raise Sequel::Error
574
647
  end
575
- def @c.columns; [:x]; end
576
- @c.dataset = ds
577
- @c.db_schema.should == {:x=>{}}
648
+ @c.dataset = @dataset.join(:x, :id).columns(:id, :x)
649
+ @c.db_schema.should == {:x=>{}, :id=>{}}
578
650
  end
579
651
 
580
652
  specify "should automatically set a singular primary key based on the schema" do