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
@@ -0,0 +1,198 @@
1
+ module Sequel
2
+ module Plugins
3
+ # The constraint_validations plugin is designed to be used with databases
4
+ # that used the constraint_validations extension when creating their
5
+ # tables. The extension adds validation metadata for constraints created,
6
+ # and this plugin reads that metadata and automatically creates validations
7
+ # for all of the constraints. For example, if you used the extension
8
+ # and created your albums table like this:
9
+ #
10
+ # DB.create_table(:albums) do
11
+ # primary_key :id
12
+ # String :name
13
+ # validate do
14
+ # min_length 5, :name
15
+ # end
16
+ # end
17
+ #
18
+ # Then when you went to save an album that uses this plugin:
19
+ #
20
+ # Album.create(:name=>'abc')
21
+ # # raises Sequel::ValidationFailed: name is shorter than 5 characters
22
+ #
23
+ # Usage:
24
+ #
25
+ # # Make all model subclasses use constraint validations (called before loading subclasses)
26
+ # Sequel::Model.plugin :constraint_validations
27
+ #
28
+ # # Make the Album class use constraint validations
29
+ # Album.plugin :constraint_validations
30
+ module ConstraintValidations
31
+ # The default constraint validation metadata table name.
32
+ DEFAULT_CONSTRAINT_VALIDATIONS_TABLE = :sequel_constraint_validations
33
+
34
+ # Automatically load the validation_helpers plugin to run the actual validations.
35
+ def self.apply(model, opts={})
36
+ model.plugin :validation_helpers
37
+ end
38
+
39
+ # Parse the constraint validations metadata from the database. Options:
40
+ # :constraint_validations_table :: Override the name of the constraint validations
41
+ # metadata table. Should only be used if the table
42
+ # name was overridden when creating the constraint
43
+ # validations.
44
+ def self.configure(model, opts={})
45
+ model.instance_variable_set(:@constraint_validations_table, opts[:constraint_validations_table] || DEFAULT_CONSTRAINT_VALIDATIONS_TABLE)
46
+ model.send(:parse_constraint_validations)
47
+ end
48
+
49
+ module DatabaseMethods
50
+ # A hash of validation method call metadata for all tables in the database.
51
+ # The hash is keyed by table name string and contains arrays of validation
52
+ # method call arrays.
53
+ attr_accessor :constraint_validations
54
+ end
55
+
56
+ module ClassMethods
57
+ # An array of validation method call arrays. Each array is an array that
58
+ # is splatted to send to perform a validation via validation_helpers.
59
+ attr_reader :constraint_validations
60
+
61
+ # The name of the table containing the constraint validations metadata.
62
+ attr_reader :constraint_validations_table
63
+
64
+ # Copy the name of the constraint validations metadata table into the subclass.
65
+ def inherited(subclass)
66
+ super
67
+ subclass.instance_variable_set(:@constraint_validations_table, @constraint_validations_table)
68
+ end
69
+
70
+ # Parse the constraint validations from the database whenever the dataset
71
+ # changes.
72
+ def set_dataset(*)
73
+ r = super
74
+ parse_constraint_validations
75
+ r
76
+ end
77
+
78
+ private
79
+
80
+ # If the database has not already parsed constraint validation
81
+ # metadata, then run a query to get the metadata data and transform it
82
+ # into arrays of validation method calls.
83
+ #
84
+ # If this model has associated dataset, use the model's table name
85
+ # to get the validations for just this model.
86
+ def parse_constraint_validations
87
+ db.extend(DatabaseMethods)
88
+
89
+ unless hash = Sequel.synchronize{db.constraint_validations}
90
+ hash = {}
91
+ db.from(constraint_validations_table).each do |r|
92
+ (hash[r[:table]] ||= []) << constraint_validation_array(r)
93
+ end
94
+ Sequel.synchronize{db.constraint_validations = hash}
95
+ end
96
+
97
+ if @dataset
98
+ ds = @dataset.clone
99
+ ds.quote_identifiers = false
100
+ table_name = ds.literal(model.table_name)
101
+ @constraint_validations = Sequel.synchronize{hash[table_name]} || []
102
+ end
103
+ end
104
+
105
+ # Given a specific database constraint validation metadata row hash, transform
106
+ # it in an validation method call array suitable for splatting to send.
107
+ def constraint_validation_array(r)
108
+ opts = {}
109
+ opts[:message] = r[:message] if r[:message]
110
+ opts[:allow_nil] = true if db.typecast_value(:boolean, r[:allow_nil])
111
+ type = r[:validation_type].to_sym
112
+ arg = r[:argument]
113
+ column = r[:column]
114
+
115
+ case type
116
+ when :like, :ilike
117
+ arg = constraint_validation_like_to_regexp(arg, type == :ilike)
118
+ type = :format
119
+ when :exact_length, :min_length, :max_length
120
+ arg = arg.to_i
121
+ when :length_range
122
+ arg = constraint_validation_int_range(arg)
123
+ when :format
124
+ arg = Regexp.new(arg)
125
+ when :iformat
126
+ arg = Regexp.new(arg, Regexp::IGNORECASE)
127
+ type = :format
128
+ when :includes_str_array
129
+ arg = arg.split(',')
130
+ type = :includes
131
+ when :includes_int_array
132
+ arg = arg.split(',').map{|x| x.to_i}
133
+ type = :includes
134
+ when :includes_int_range
135
+ arg = constraint_validation_int_range(arg)
136
+ type = :includes
137
+ end
138
+
139
+ column = if type == :unique
140
+ column.split(',').map{|c| c.to_sym}
141
+ else
142
+ column.to_sym
143
+ end
144
+
145
+ a = [:"validates_#{type}"]
146
+ if arg
147
+ a << arg
148
+ end
149
+ a << column
150
+ unless opts.empty?
151
+ a << opts
152
+ end
153
+ a
154
+ end
155
+
156
+ # Return a range of integers assuming the argument is in
157
+ # 1..2 or 1...2 format.
158
+ def constraint_validation_int_range(arg)
159
+ arg =~ /(\d+)\.\.(\.)?(\d+)/
160
+ Range.new($1.to_i, $3.to_i, $2 == '.')
161
+ end
162
+
163
+ # Transform the LIKE pattern string argument into a
164
+ # Regexp argument suitable for use with validates_format.
165
+ def constraint_validation_like_to_regexp(arg, case_insensitive)
166
+ arg = Regexp.escape(arg).gsub(/%%|%|_/) do |s|
167
+ case s
168
+ when '%%'
169
+ '%'
170
+ when '%'
171
+ '.*'
172
+ when '_'
173
+ '.'
174
+ end
175
+ end
176
+ arg = "\\A#{arg}\\z"
177
+
178
+ if case_insensitive
179
+ Regexp.new(arg, Regexp::IGNORECASE)
180
+ else
181
+ Regexp.new(arg)
182
+ end
183
+ end
184
+ end
185
+
186
+ module InstanceMethods
187
+ # Run all of the constraint validations parsed from the database
188
+ # when validating the instance.
189
+ def validate
190
+ super
191
+ model.constraint_validations.each do |v|
192
+ send(*v)
193
+ end
194
+ end
195
+ end
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,100 @@
1
+ module Sequel
2
+ module Plugins
3
+ # DatasetAssociations allows you to easily use your model associations
4
+ # via datasets. For each association you define, it creates a dataset
5
+ # method for that association that returns a dataset of all objects
6
+ # that are associated to objects in the current dataset. Here's a simple
7
+ # example:
8
+ #
9
+ # class Artist < Sequel::Model
10
+ # plugin :dataset_associations
11
+ # one_to_many :albums
12
+ # end
13
+ # Artist.filter(id=>1..100).albums
14
+ # # SELECT * FROM albums
15
+ # # WHERE (albums.artist_id IN (
16
+ # # SELECT id FROM artists
17
+ # # WHERE ((id >= 1) AND (id <= 100))))
18
+ #
19
+ # This works for all of the association types that ship with Sequel,
20
+ # including the many_through_many type. Most association options that
21
+ # are supported when eager loading are supported when using a
22
+ # dataset association. However, associations that use :limit or
23
+ # one_to_one associations that are really one_to_many relationships
24
+ # in the database will not work correctly, returning all associated
25
+ # objects.
26
+ #
27
+ # As the dataset methods return datasets, you can easily chain the
28
+ # methods to get associated datasets of associated datasets:
29
+ #
30
+ # Artist.filter(id=>1..100).albums.filter{name < 'M'}.tags
31
+ # # SELECT tags.* FROM tags
32
+ # # WHERE (tags.id IN (
33
+ # # SELECT albums_tags.tag_id FROM albums
34
+ # # INNER JOIN albums_tags
35
+ # # ON (albums_tags.album_id = albums.id)
36
+ # # WHERE
37
+ # # ((albums.artist_id IN (
38
+ # # SELECT id FROM artists
39
+ # # WHERE ((id >= 1) AND (id <= 100)))
40
+ # # AND
41
+ # # (name < 'M')))))
42
+ #
43
+ # Usage:
44
+ #
45
+ # # Make all model subclasses create association methods for datasets
46
+ # Sequel::Model.plugin :dataset_associations
47
+ #
48
+ # # Make the Album class create association methods for datasets
49
+ # Album.plugin :dataset_associations
50
+ module DatasetAssociations
51
+ module ClassMethods
52
+ # Set up a dataset method for each association to return an associated dataset
53
+ def associate(type, name, *)
54
+ ret = super
55
+ r = association_reflection(name)
56
+ meth = r.returns_array? ? name : pluralize(name).to_sym
57
+ def_dataset_method(meth){associated(name)}
58
+ ret
59
+ end
60
+ end
61
+
62
+ module DatasetMethods
63
+ # For the association given by +name+, return a dataset of associated objects
64
+ # such that it would return the union of calling the association method on
65
+ # all objects returned by the current dataset.
66
+ #
67
+ # This supports most options that are supported when eager loading. It doesn't
68
+ # support limits on the associations, or one_to_one associations that are really
69
+ # one_to_many and use an order to select the first matching object. In both of
70
+ # those cases, this will return an array of all matching objects.
71
+ def associated(name)
72
+ raise Error, "unrecognized association name: #{name.inspect}" unless r = model.association_reflection(name)
73
+ ds = r.associated_class.dataset
74
+ sds = opts[:limit] ? self : unordered
75
+ ds = case r[:type]
76
+ when :many_to_one
77
+ ds.filter(r.qualified_primary_key=>sds.select(*Array(r[:qualified_key])))
78
+ when :one_to_one, :one_to_many
79
+ ds.filter(r.qualified_key=>sds.select(*Array(r.qualified_primary_key)))
80
+ when :many_to_many
81
+ ds.filter(r.qualified_right_primary_key=>sds.select(*Array(r.qualified_right_key)).
82
+ join(r[:join_table], r[:left_keys].zip(r[:left_primary_keys]), :implicit_qualifier=>model.table_name))
83
+ when :many_through_many
84
+ fre = r.reverse_edges.first
85
+ fe, *edges = r.edges
86
+ sds = sds.select(*Array(r.qualify(fre[:table], fre[:left]))).
87
+ join(fe[:table], Array(fe[:right]).zip(Array(fe[:left])), :implicit_qualifier=>model.table_name)
88
+ edges.each{|e| sds = sds.join(e[:table], Array(e[:right]).zip(Array(e[:left])))}
89
+ ds.filter(r.qualified_right_primary_key=>sds)
90
+ else
91
+ raise Error, "unrecognized association type for association #{name.inspect}: #{r[:type].inspect}"
92
+ end
93
+ ds = model.apply_association_dataset_opts(r, ds)
94
+ r[:extend].each{|m| ds.extend(m)}
95
+ ds
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,72 @@
1
+ module Sequel
2
+ module Plugins
3
+ # DefaultsSetter is a simple plugin that sets non-nil/NULL default values upon
4
+ # initialize:
5
+ #
6
+ # # column a default NULL
7
+ # # column b default 2
8
+ # album = Album.new.values # {:b => 2}
9
+ # album = Album.new(:a=>1, :b=>3).values # {:a => 1, :b => 3}
10
+ #
11
+ # Usage:
12
+ #
13
+ # # Make all model subclass instances set defaults (called before loading subclasses)
14
+ # Sequel::Model.plugin :defaults_setter
15
+ #
16
+ # # Make the Album class set defaults
17
+ # Album.plugin :defaults_setter
18
+ module DefaultsSetter
19
+ # Set the default values based on the model schema
20
+ def self.configure(model)
21
+ model.send(:set_default_values)
22
+ end
23
+
24
+ module ClassMethods
25
+ # The default values to set in initialize for this model. A hash with column symbol
26
+ # keys and default values. If the default values respond to +call+, it will be called
27
+ # to get the value, otherwise the value will be used directly. You can manually modify
28
+ # this hash to set specific default values, by default the ones will be parsed from the database.
29
+ attr_reader :default_values
30
+
31
+ # Set the default values when loading the dataset.
32
+ def set_dataset(*)
33
+ x = super
34
+ set_default_values
35
+ x
36
+ end
37
+
38
+ private
39
+
40
+ # Parse the cached database schema for this model and set the default values appropriately.
41
+ def set_default_values
42
+ h = {}
43
+ @db_schema.each{|k, v| h[k] = convert_default_value(v[:ruby_default]) unless v[:ruby_default].nil?} if @db_schema
44
+ @default_values = h
45
+ end
46
+
47
+ # Handle the CURRENT_DATE and CURRENT_TIMESTAMP values specially by returning an appropriate Date or
48
+ # Time/DateTime value.
49
+ def convert_default_value(v)
50
+ case v
51
+ when Sequel::CURRENT_DATE
52
+ lambda{Date.today}
53
+ when Sequel::CURRENT_TIMESTAMP
54
+ lambda{Sequel.datetime_class.now}
55
+ else
56
+ v
57
+ end
58
+ end
59
+ end
60
+
61
+ module InstanceMethods
62
+ private
63
+
64
+ # Set default values if they are not already set by the hash provided to initialize.
65
+ def initialize_set(h)
66
+ super
67
+ model.default_values.each{|k,v| self[k] = (v.respond_to?(:call) ? v.call : v) unless values.has_key?(k)}
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,214 @@
1
+ module Sequel
2
+ module Plugins
3
+ # The dirty plugin makes Sequel save the initial value of
4
+ # a column when setting a new value for the column. This
5
+ # makes it easier to see what changes were made to the object:
6
+ #
7
+ # artist.name # => 'Foo'
8
+ # artist.name = 'Bar'
9
+ # artist.initial_value(:name) # 'Foo'
10
+ # artist.column_change(:name) # ['Foo', 'Bar']
11
+ # artist.column_changes # {:name => ['Foo', 'Bar']}
12
+ # artist.column_changed?(:name) # true
13
+ # artist.reset_column(:name)
14
+ # artist.name # => 'Foo'
15
+ # artist.column_changed?(:name) # false
16
+ #
17
+ # It also makes changed_columns more accurate in that it
18
+ # can detect when a the column value is changed and then
19
+ # changed back:
20
+ #
21
+ # artist.name # => 'Foo'
22
+ # artist.name = 'Bar'
23
+ # artist.changed_columns # => [:name]
24
+ # artist.name = 'Foo'
25
+ # artist.changed_columns # => []
26
+ #
27
+ # It can handle situations where a column value is
28
+ # modified in place:
29
+ #
30
+ # artist.will_change_column(:name)
31
+ # artist.name.gsub!(/o/, 'u')
32
+ # artist.changed_columns # => [:name]
33
+ # artist.initial_value(:name) # => 'Foo'
34
+ # artist.column_change(:name) # => ['Foo', 'Fuu']
35
+ #
36
+ # It also saves the previously changed values after an update:
37
+ #
38
+ # artist.update(:name=>'Bar')
39
+ # artist.column_changes # => {}
40
+ # artist.previous_changes # => {:name=>['Foo', 'Bar']}
41
+ #
42
+ # Usage:
43
+ #
44
+ # # Make all model subclass instances record previous values (called before loading subclasses)
45
+ # Sequel::Model.plugin :dirty
46
+ #
47
+ # # Make the Album class record previous values
48
+ # Album.plugin :dirty
49
+ module Dirty
50
+ module InstanceMethods
51
+ # A hash of previous changes before the object was
52
+ # saved, in the same format as #column_changes.
53
+ # Note that this is not necessarily the same as the columns
54
+ # that were used in the update statement.
55
+ attr_reader :previous_changes
56
+
57
+ # An array with the initial value and the current value
58
+ # of the column, if the column has been changed. If the
59
+ # column has not been changed, returns nil.
60
+ #
61
+ # column_change(:name) # => ['Initial', 'Current']
62
+ def column_change(column)
63
+ [initial_value(column), send(column)] if column_changed?(column)
64
+ end
65
+
66
+ # A hash with column symbol keys and pairs of initial and
67
+ # current values for all changed columns.
68
+ #
69
+ # column_changes # => {:name => ['Initial', 'Current']}
70
+ def column_changes
71
+ h = {}
72
+ initial_values.each do |column, value|
73
+ h[column] = [value, send(column)]
74
+ end
75
+ h
76
+ end
77
+
78
+ # Either true or false depending on whether the column has
79
+ # changed. Note that this is not exactly the same as checking if
80
+ # the column is in changed_columns, if the column was not set
81
+ # initially.
82
+ #
83
+ # column_changed?(:name) # => true
84
+ def column_changed?(column)
85
+ initial_values.has_key?(column)
86
+ end
87
+
88
+ # The initial value of the given column. If the column value has
89
+ # not changed, this will be the same as the current value of the
90
+ # column.
91
+ #
92
+ # initial_value(:name) # => 'Initial'
93
+ def initial_value(column)
94
+ initial_values.fetch(column){send(column)}
95
+ end
96
+
97
+ # A hash with column symbol keys and initial values.
98
+ #
99
+ # initial_values # {:name => 'Initial'}
100
+ def initial_values
101
+ @initial_values ||= {}
102
+ end
103
+
104
+ # Reset the column to its initial value. If the column was not set
105
+ # initial, removes it from the values.
106
+ #
107
+ # reset_column(:name)
108
+ # name # => 'Initial'
109
+ def reset_column(column)
110
+ if initial_values.has_key?(column)
111
+ send(:"#{column}=", initial_values[column])
112
+ end
113
+ if missing_initial_values.include?(column)
114
+ values.delete(column)
115
+ end
116
+ end
117
+
118
+ # Manually specify that a column will change. This should only be used
119
+ # if you plan to modify a column value in place, which is not recommended.
120
+ #
121
+ # will_change_column(:name)
122
+ # name.gsub(/i/i, 'o')
123
+ # column_change(:name) # => ['Initial', 'onotoal']
124
+ def will_change_column(column)
125
+ changed_columns << column unless changed_columns.include?(column)
126
+ check_missing_initial_value(column)
127
+
128
+ value = if initial_values.has_key?(column)
129
+ initial_values[column]
130
+ else
131
+ send(column)
132
+ end
133
+
134
+ initial_values[column] = if value && value != true && value.respond_to?(:clone)
135
+ begin
136
+ value.clone
137
+ rescue TypeError
138
+ value
139
+ end
140
+ else
141
+ value
142
+ end
143
+ end
144
+
145
+ private
146
+
147
+ # Reset the initial values after saving.
148
+ def after_save
149
+ super
150
+ reset_initial_values
151
+ end
152
+
153
+ # Save the current changes so they are available after updating. This happens
154
+ # before after_save resets them.
155
+ def after_update
156
+ super
157
+ @previous_changes = column_changes
158
+ end
159
+
160
+ # Reset the initial values when refreshing.
161
+ def _refresh(dataset)
162
+ super
163
+ reset_initial_values
164
+ end
165
+
166
+ # When changing the column value, save the initial column value. If the column
167
+ # value is changed back to the initial value, update changed columns to remove
168
+ # the column.
169
+ def change_column_value(column, value)
170
+ if (iv = initial_values).has_key?(column)
171
+ initial = iv[column]
172
+ super
173
+ if value == initial
174
+ changed_columns.delete(column) unless missing_initial_values.include?(column)
175
+ iv.delete(column)
176
+ end
177
+ else
178
+ check_missing_initial_value(column)
179
+ iv[column] = send(column)
180
+ super
181
+ end
182
+ end
183
+
184
+ # If the values hash does not contain the column, make sure missing_initial_values
185
+ # does so that it doesn't get deleted from changed_columns if changed back,
186
+ # and so that resetting the column value can be handled correctly.
187
+ def check_missing_initial_value(column)
188
+ unless values.has_key?(column) || (miv = missing_initial_values).include?(column)
189
+ miv << column
190
+ end
191
+ end
192
+
193
+ # Reset the initial values when initializing.
194
+ def initialize_set(h)
195
+ super
196
+ reset_initial_values
197
+ end
198
+
199
+ # Array holding column symbols that were not present initially. This is necessary
200
+ # to differentiate between values that were not present and values that were
201
+ # present but equal to nil.
202
+ def missing_initial_values
203
+ @missing_initial_values ||= []
204
+ end
205
+
206
+ # Clear the data structures that store the initial values.
207
+ def reset_initial_values
208
+ @initial_values.clear if @initial_values
209
+ @missing_initial_values.clear if @missing_initial_values
210
+ end
211
+ end
212
+ end
213
+ end
214
+ end
@@ -0,0 +1,59 @@
1
+ module Sequel
2
+ module Plugins
3
+ # The eager_each plugin makes calling each on an eager loaded dataset do eager loading.
4
+ # By default, each does not work on an eager loaded dataset, because each iterates
5
+ # over rows of the dataset as they come in, and to eagerly load you need to have all
6
+ # values up front. With the default associations code, you must call #all on an eagerly
7
+ # loaded dataset, as calling #each on an #eager dataset skips the eager loading, and calling
8
+ # #each on an #eager_graph dataset makes it yield plain hashes with columns from all
9
+ # tables, instead of yielding the instances of the main model.
10
+ #
11
+ # This plugin makes #each call #all for eagerly loaded datasets. As #all usually calls
12
+ # #each, this is a bit of issue, but this plugin resolves the issue by cloning the dataset
13
+ # and setting a new flag in the cloned dataset, so that each can check with the flag to
14
+ # determine whether it should call all.
15
+ #
16
+ # Usage:
17
+ #
18
+ # # Make all model subclass instances eagerly load for each (called before loading subclasses)
19
+ # Sequel::Model.plugin :eager_each
20
+ #
21
+ # # Make the Album class eagerly load for each
22
+ # Album.plugin :eager_each
23
+ module EagerEach
24
+ # Methods added to eagerly loaded datasets when the eager_each plugin is in use.
25
+ module EagerDatasetMethods
26
+ # Call #all instead of #each unless #each is being called by #all.
27
+ def each(&block)
28
+ if opts[:all_called]
29
+ super
30
+ else
31
+ all(&block)
32
+ end
33
+ end
34
+
35
+ # Clone the dataset and set a flag to let #each know not to call #all,
36
+ # to avoid the infinite loop.
37
+ def all(&block)
38
+ if opts[:all_called]
39
+ super
40
+ else
41
+ clone(:all_called=>true).all(&block)
42
+ end
43
+ end
44
+ end
45
+
46
+ module DatasetMethods
47
+ # Make sure calling each on this dataset will eagerly load the dataset.
48
+ def eager(*)
49
+ super.extend(EagerDatasetMethods)
50
+ end
51
+
52
+ # Make sure calling each on this dataset will eagerly load the dataset.
53
+ def eager_graph(*)
54
+ super.extend(EagerDatasetMethods)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -8,7 +8,7 @@ module Sequel
8
8
  # attribute, the resulting value is forced to a given encoding if the
9
9
  # value is a string. There are two ways to specify the encoding. You
10
10
  # can either do so in the plugin call itself, or via the
11
- # forced_encoding class accessor:
11
+ # forced_encoding class accessor.
12
12
  #
13
13
  # Usage:
14
14
  #
@@ -46,6 +46,11 @@ module Sequel
46
46
  super(force_hash_encoding(row))
47
47
  end
48
48
 
49
+ # Force the encoding of all string values when setting the instance's values.
50
+ def set_values(row)
51
+ super(force_hash_encoding(row))
52
+ end
53
+
49
54
  private
50
55
 
51
56
  # Force the encoding for all string values in the given row hash.
@@ -55,11 +60,6 @@ module Sequel
55
60
  row
56
61
  end
57
62
 
58
- # Force the encoding of all string values when setting the instance's values.
59
- def set_values(row)
60
- super(force_hash_encoding(row))
61
- end
62
-
63
63
  # Force the encoding of all returned strings to the model's forced_encoding.
64
64
  def typecast_value(column, value)
65
65
  s = super
@@ -90,9 +90,9 @@ module Sequel
90
90
 
91
91
  # Make a copy of the current class's hooks for the subclass.
92
92
  def inherited(subclass)
93
- super
94
93
  hooks = subclass.instance_variable_set(:@hooks, {})
95
94
  instance_variable_get(:@hooks).each{|k,v| hooks[k] = v.dup}
95
+ super
96
96
  end
97
97
 
98
98
  private