sequel 4.49.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (477) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +70 -0
  3. data/README.rdoc +195 -136
  4. data/Rakefile +26 -42
  5. data/bin/sequel +3 -5
  6. data/doc/advanced_associations.rdoc +86 -163
  7. data/doc/association_basics.rdoc +197 -274
  8. data/doc/bin_sequel.rdoc +5 -3
  9. data/doc/cheat_sheet.rdoc +66 -43
  10. data/doc/code_order.rdoc +1 -8
  11. data/doc/core_extensions.rdoc +81 -56
  12. data/doc/dataset_basics.rdoc +8 -17
  13. data/doc/dataset_filtering.rdoc +81 -86
  14. data/doc/extensions.rdoc +3 -10
  15. data/doc/mass_assignment.rdoc +73 -30
  16. data/doc/migration.rdoc +19 -36
  17. data/doc/model_dataset_method_design.rdoc +14 -17
  18. data/doc/model_hooks.rdoc +15 -25
  19. data/doc/model_plugins.rdoc +10 -10
  20. data/doc/mssql_stored_procedures.rdoc +3 -3
  21. data/doc/object_model.rdoc +52 -70
  22. data/doc/opening_databases.rdoc +39 -32
  23. data/doc/postgresql.rdoc +48 -38
  24. data/doc/prepared_statements.rdoc +27 -22
  25. data/doc/querying.rdoc +173 -150
  26. data/doc/reflection.rdoc +5 -6
  27. data/doc/release_notes/5.0.0.txt +159 -0
  28. data/doc/schema_modification.rdoc +63 -60
  29. data/doc/security.rdoc +97 -88
  30. data/doc/sharding.rdoc +43 -30
  31. data/doc/sql.rdoc +53 -65
  32. data/doc/testing.rdoc +3 -5
  33. data/doc/thread_safety.rdoc +2 -4
  34. data/doc/transactions.rdoc +18 -17
  35. data/doc/validations.rdoc +48 -45
  36. data/doc/virtual_rows.rdoc +87 -115
  37. data/lib/sequel.rb +1 -1
  38. data/lib/sequel/adapters/ado.rb +9 -25
  39. data/lib/sequel/adapters/ado/access.rb +7 -13
  40. data/lib/sequel/adapters/ado/mssql.rb +2 -9
  41. data/lib/sequel/adapters/amalgalite.rb +3 -18
  42. data/lib/sequel/adapters/ibmdb.rb +9 -45
  43. data/lib/sequel/adapters/jdbc.rb +13 -73
  44. data/lib/sequel/adapters/jdbc/db2.rb +8 -37
  45. data/lib/sequel/adapters/jdbc/derby.rb +4 -50
  46. data/lib/sequel/adapters/jdbc/h2.rb +4 -25
  47. data/lib/sequel/adapters/jdbc/hsqldb.rb +1 -26
  48. data/lib/sequel/adapters/jdbc/jtds.rb +2 -9
  49. data/lib/sequel/adapters/jdbc/mssql.rb +1 -11
  50. data/lib/sequel/adapters/jdbc/mysql.rb +1 -15
  51. data/lib/sequel/adapters/jdbc/oracle.rb +4 -26
  52. data/lib/sequel/adapters/jdbc/postgresql.rb +2 -31
  53. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +4 -17
  54. data/lib/sequel/adapters/jdbc/sqlite.rb +1 -7
  55. data/lib/sequel/adapters/jdbc/sqlserver.rb +1 -13
  56. data/lib/sequel/adapters/jdbc/transactions.rb +1 -14
  57. data/lib/sequel/adapters/mock.rb +4 -30
  58. data/lib/sequel/adapters/mysql.rb +7 -44
  59. data/lib/sequel/adapters/mysql2.rb +5 -23
  60. data/lib/sequel/adapters/odbc.rb +0 -19
  61. data/lib/sequel/adapters/odbc/db2.rb +1 -1
  62. data/lib/sequel/adapters/odbc/mssql.rb +4 -12
  63. data/lib/sequel/adapters/odbc/oracle.rb +1 -1
  64. data/lib/sequel/adapters/oracle.rb +7 -13
  65. data/lib/sequel/adapters/postgres.rb +13 -57
  66. data/lib/sequel/adapters/postgresql.rb +1 -1
  67. data/lib/sequel/adapters/shared/access.rb +11 -51
  68. data/lib/sequel/adapters/shared/db2.rb +3 -61
  69. data/lib/sequel/adapters/shared/mssql.rb +21 -157
  70. data/lib/sequel/adapters/shared/mysql.rb +23 -224
  71. data/lib/sequel/adapters/shared/oracle.rb +13 -41
  72. data/lib/sequel/adapters/shared/postgres.rb +44 -259
  73. data/lib/sequel/adapters/shared/sqlanywhere.rb +4 -96
  74. data/lib/sequel/adapters/shared/sqlite.rb +12 -101
  75. data/lib/sequel/adapters/sqlanywhere.rb +4 -23
  76. data/lib/sequel/adapters/sqlite.rb +2 -19
  77. data/lib/sequel/adapters/tinytds.rb +5 -15
  78. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +1 -1
  79. data/lib/sequel/adapters/utils/mysql_mysql2.rb +2 -4
  80. data/lib/sequel/adapters/utils/mysql_prepared_statements.rb +3 -6
  81. data/lib/sequel/adapters/utils/replace.rb +0 -5
  82. data/lib/sequel/adapters/utils/stored_procedures.rb +0 -2
  83. data/lib/sequel/adapters/utils/unmodified_identifiers.rb +2 -0
  84. data/lib/sequel/ast_transformer.rb +3 -94
  85. data/lib/sequel/connection_pool.rb +26 -28
  86. data/lib/sequel/connection_pool/sharded_single.rb +1 -4
  87. data/lib/sequel/connection_pool/sharded_threaded.rb +97 -95
  88. data/lib/sequel/connection_pool/single.rb +0 -2
  89. data/lib/sequel/connection_pool/threaded.rb +94 -110
  90. data/lib/sequel/core.rb +42 -101
  91. data/lib/sequel/database.rb +12 -2
  92. data/lib/sequel/database/connecting.rb +23 -60
  93. data/lib/sequel/database/dataset.rb +6 -9
  94. data/lib/sequel/database/dataset_defaults.rb +4 -48
  95. data/lib/sequel/database/features.rb +5 -4
  96. data/lib/sequel/database/logging.rb +2 -9
  97. data/lib/sequel/database/misc.rb +23 -55
  98. data/lib/sequel/database/query.rb +8 -13
  99. data/lib/sequel/database/schema_generator.rb +89 -64
  100. data/lib/sequel/database/schema_methods.rb +61 -79
  101. data/lib/sequel/database/transactions.rb +4 -24
  102. data/lib/sequel/dataset.rb +18 -10
  103. data/lib/sequel/dataset/actions.rb +53 -107
  104. data/lib/sequel/dataset/dataset_module.rb +3 -15
  105. data/lib/sequel/dataset/features.rb +30 -30
  106. data/lib/sequel/dataset/graph.rb +40 -49
  107. data/lib/sequel/dataset/misc.rb +12 -37
  108. data/lib/sequel/dataset/placeholder_literalizer.rb +4 -4
  109. data/lib/sequel/dataset/prepared_statements.rb +23 -51
  110. data/lib/sequel/dataset/query.rb +71 -155
  111. data/lib/sequel/dataset/sql.rb +30 -225
  112. data/lib/sequel/deprecated.rb +18 -27
  113. data/lib/sequel/exceptions.rb +1 -17
  114. data/lib/sequel/extensions/_model_pg_row.rb +0 -7
  115. data/lib/sequel/extensions/_pretty_table.rb +1 -3
  116. data/lib/sequel/extensions/arbitrary_servers.rb +10 -10
  117. data/lib/sequel/extensions/connection_expiration.rb +1 -1
  118. data/lib/sequel/extensions/connection_validator.rb +1 -1
  119. data/lib/sequel/extensions/constraint_validations.rb +11 -11
  120. data/lib/sequel/extensions/core_extensions.rb +39 -49
  121. data/lib/sequel/extensions/core_refinements.rb +39 -45
  122. data/lib/sequel/extensions/current_datetime_timestamp.rb +0 -4
  123. data/lib/sequel/extensions/date_arithmetic.rb +7 -7
  124. data/lib/sequel/extensions/duplicate_columns_handler.rb +12 -9
  125. data/lib/sequel/extensions/empty_array_consider_nulls.rb +2 -2
  126. data/lib/sequel/extensions/eval_inspect.rb +4 -11
  127. data/lib/sequel/extensions/freeze_datasets.rb +1 -69
  128. data/lib/sequel/extensions/from_block.rb +1 -35
  129. data/lib/sequel/extensions/graph_each.rb +2 -2
  130. data/lib/sequel/extensions/identifier_mangling.rb +9 -19
  131. data/lib/sequel/extensions/implicit_subquery.rb +2 -2
  132. data/lib/sequel/extensions/inflector.rb +4 -4
  133. data/lib/sequel/extensions/migration.rb +23 -40
  134. data/lib/sequel/extensions/no_auto_literal_strings.rb +2 -84
  135. data/lib/sequel/extensions/null_dataset.rb +2 -8
  136. data/lib/sequel/extensions/pagination.rb +1 -17
  137. data/lib/sequel/extensions/pg_array.rb +20 -189
  138. data/lib/sequel/extensions/pg_hstore.rb +11 -50
  139. data/lib/sequel/extensions/pg_hstore_ops.rb +2 -2
  140. data/lib/sequel/extensions/pg_inet.rb +2 -15
  141. data/lib/sequel/extensions/pg_interval.rb +1 -20
  142. data/lib/sequel/extensions/pg_json.rb +7 -27
  143. data/lib/sequel/extensions/pg_loose_count.rb +1 -1
  144. data/lib/sequel/extensions/pg_range.rb +6 -121
  145. data/lib/sequel/extensions/pg_range_ops.rb +1 -3
  146. data/lib/sequel/extensions/pg_row.rb +5 -77
  147. data/lib/sequel/extensions/pg_row_ops.rb +2 -13
  148. data/lib/sequel/extensions/query.rb +3 -4
  149. data/lib/sequel/extensions/round_timestamps.rb +0 -6
  150. data/lib/sequel/extensions/schema_dumper.rb +13 -13
  151. data/lib/sequel/extensions/select_remove.rb +3 -3
  152. data/lib/sequel/extensions/split_array_nil.rb +2 -2
  153. data/lib/sequel/extensions/sql_comments.rb +2 -2
  154. data/lib/sequel/extensions/string_agg.rb +11 -8
  155. data/lib/sequel/extensions/symbol_aref.rb +6 -20
  156. data/lib/sequel/model.rb +27 -62
  157. data/lib/sequel/model/associations.rb +128 -131
  158. data/lib/sequel/model/base.rb +171 -711
  159. data/lib/sequel/model/default_inflections.rb +1 -1
  160. data/lib/sequel/model/errors.rb +0 -3
  161. data/lib/sequel/model/exceptions.rb +2 -6
  162. data/lib/sequel/model/inflections.rb +1 -26
  163. data/lib/sequel/model/plugins.rb +1 -0
  164. data/lib/sequel/plugins/active_model.rb +2 -5
  165. data/lib/sequel/plugins/association_dependencies.rb +15 -15
  166. data/lib/sequel/plugins/association_pks.rb +14 -28
  167. data/lib/sequel/plugins/association_proxies.rb +6 -7
  168. data/lib/sequel/plugins/auto_validations.rb +4 -4
  169. data/lib/sequel/plugins/before_after_save.rb +0 -43
  170. data/lib/sequel/plugins/blacklist_security.rb +9 -8
  171. data/lib/sequel/plugins/boolean_readers.rb +3 -3
  172. data/lib/sequel/plugins/boolean_subsets.rb +2 -2
  173. data/lib/sequel/plugins/caching.rb +5 -5
  174. data/lib/sequel/plugins/class_table_inheritance.rb +71 -102
  175. data/lib/sequel/plugins/column_conflicts.rb +2 -2
  176. data/lib/sequel/plugins/column_select.rb +2 -2
  177. data/lib/sequel/plugins/composition.rb +15 -24
  178. data/lib/sequel/plugins/constraint_validations.rb +4 -3
  179. data/lib/sequel/plugins/csv_serializer.rb +13 -20
  180. data/lib/sequel/plugins/dataset_associations.rb +2 -2
  181. data/lib/sequel/plugins/def_dataset_method.rb +5 -5
  182. data/lib/sequel/plugins/defaults_setter.rb +1 -1
  183. data/lib/sequel/plugins/delay_add_association.rb +1 -1
  184. data/lib/sequel/plugins/finder.rb +16 -10
  185. data/lib/sequel/plugins/force_encoding.rb +1 -7
  186. data/lib/sequel/plugins/hook_class_methods.rb +4 -106
  187. data/lib/sequel/plugins/input_transformer.rb +10 -11
  188. data/lib/sequel/plugins/insert_returning_select.rb +1 -9
  189. data/lib/sequel/plugins/instance_filters.rb +5 -5
  190. data/lib/sequel/plugins/instance_hooks.rb +7 -52
  191. data/lib/sequel/plugins/inverted_subsets.rb +3 -1
  192. data/lib/sequel/plugins/json_serializer.rb +19 -19
  193. data/lib/sequel/plugins/lazy_attributes.rb +1 -10
  194. data/lib/sequel/plugins/list.rb +6 -6
  195. data/lib/sequel/plugins/many_through_many.rb +11 -8
  196. data/lib/sequel/plugins/mssql_optimistic_locking.rb +3 -3
  197. data/lib/sequel/plugins/nested_attributes.rb +18 -31
  198. data/lib/sequel/plugins/optimistic_locking.rb +3 -3
  199. data/lib/sequel/plugins/pg_array_associations.rb +8 -2
  200. data/lib/sequel/plugins/pg_row.rb +2 -11
  201. data/lib/sequel/plugins/prepared_statements.rb +13 -66
  202. data/lib/sequel/plugins/prepared_statements_safe.rb +1 -1
  203. data/lib/sequel/plugins/rcte_tree.rb +7 -7
  204. data/lib/sequel/plugins/serialization.rb +15 -33
  205. data/lib/sequel/plugins/serialization_modification_detection.rb +1 -1
  206. data/lib/sequel/plugins/sharding.rb +2 -8
  207. data/lib/sequel/plugins/single_table_inheritance.rb +10 -13
  208. data/lib/sequel/plugins/skip_create_refresh.rb +3 -3
  209. data/lib/sequel/plugins/static_cache.rb +8 -9
  210. data/lib/sequel/plugins/string_stripper.rb +3 -3
  211. data/lib/sequel/plugins/subclasses.rb +1 -1
  212. data/lib/sequel/plugins/subset_conditions.rb +2 -2
  213. data/lib/sequel/plugins/table_select.rb +2 -2
  214. data/lib/sequel/plugins/tactical_eager_loading.rb +4 -4
  215. data/lib/sequel/plugins/timestamps.rb +6 -7
  216. data/lib/sequel/plugins/touch.rb +4 -8
  217. data/lib/sequel/plugins/tree.rb +3 -3
  218. data/lib/sequel/plugins/typecast_on_load.rb +2 -2
  219. data/lib/sequel/plugins/unlimited_update.rb +1 -7
  220. data/lib/sequel/plugins/update_or_create.rb +3 -3
  221. data/lib/sequel/plugins/update_refresh.rb +3 -3
  222. data/lib/sequel/plugins/uuid.rb +7 -11
  223. data/lib/sequel/plugins/validation_class_methods.rb +10 -9
  224. data/lib/sequel/plugins/validation_contexts.rb +4 -4
  225. data/lib/sequel/plugins/validation_helpers.rb +26 -25
  226. data/lib/sequel/plugins/whitelist_security.rb +13 -9
  227. data/lib/sequel/plugins/xml_serializer.rb +24 -25
  228. data/lib/sequel/sql.rb +145 -276
  229. data/lib/sequel/timezones.rb +8 -22
  230. data/lib/sequel/version.rb +2 -2
  231. data/spec/adapter_spec.rb +1 -1
  232. data/spec/adapters/db2_spec.rb +2 -103
  233. data/spec/adapters/mssql_spec.rb +89 -68
  234. data/spec/adapters/mysql_spec.rb +101 -480
  235. data/spec/adapters/oracle_spec.rb +1 -9
  236. data/spec/adapters/postgres_spec.rb +312 -565
  237. data/spec/adapters/spec_helper.rb +12 -31
  238. data/spec/adapters/sqlanywhere_spec.rb +2 -77
  239. data/spec/adapters/sqlite_spec.rb +8 -146
  240. data/spec/bin_spec.rb +11 -16
  241. data/spec/core/connection_pool_spec.rb +173 -74
  242. data/spec/core/database_spec.rb +64 -244
  243. data/spec/core/dataset_spec.rb +81 -415
  244. data/spec/core/deprecated_spec.rb +3 -3
  245. data/spec/core/expression_filters_spec.rb +37 -144
  246. data/spec/core/mock_adapter_spec.rb +176 -4
  247. data/spec/core/object_graph_spec.rb +11 -60
  248. data/spec/core/placeholder_literalizer_spec.rb +1 -14
  249. data/spec/core/schema_generator_spec.rb +51 -40
  250. data/spec/core/schema_spec.rb +74 -77
  251. data/spec/core/spec_helper.rb +6 -24
  252. data/spec/core/version_spec.rb +1 -1
  253. data/spec/core_extensions_spec.rb +7 -83
  254. data/spec/core_model_spec.rb +2 -2
  255. data/spec/deprecation_helper.rb +2 -14
  256. data/spec/extensions/accessed_columns_spec.rb +1 -1
  257. data/spec/extensions/active_model_spec.rb +3 -3
  258. data/spec/extensions/after_initialize_spec.rb +1 -1
  259. data/spec/extensions/arbitrary_servers_spec.rb +2 -2
  260. data/spec/extensions/association_dependencies_spec.rb +1 -1
  261. data/spec/extensions/association_pks_spec.rb +4 -59
  262. data/spec/extensions/association_proxies_spec.rb +1 -1
  263. data/spec/extensions/auto_literal_strings_spec.rb +1 -12
  264. data/spec/extensions/auto_validations_spec.rb +1 -1
  265. data/spec/extensions/blacklist_security_spec.rb +1 -1
  266. data/spec/extensions/blank_spec.rb +1 -1
  267. data/spec/extensions/boolean_readers_spec.rb +1 -1
  268. data/spec/extensions/boolean_subsets_spec.rb +1 -1
  269. data/spec/extensions/caching_spec.rb +1 -1
  270. data/spec/extensions/class_table_inheritance_spec.rb +35 -1086
  271. data/spec/extensions/column_conflicts_spec.rb +1 -1
  272. data/spec/extensions/column_select_spec.rb +4 -4
  273. data/spec/extensions/columns_introspection_spec.rb +1 -1
  274. data/spec/extensions/columns_updated_spec.rb +1 -1
  275. data/spec/extensions/composition_spec.rb +1 -7
  276. data/spec/extensions/connection_expiration_spec.rb +3 -3
  277. data/spec/extensions/connection_validator_spec.rb +3 -3
  278. data/spec/extensions/constraint_validations_plugin_spec.rb +1 -1
  279. data/spec/extensions/constraint_validations_spec.rb +1 -1
  280. data/spec/extensions/core_refinements_spec.rb +1 -3
  281. data/spec/extensions/csv_serializer_spec.rb +4 -9
  282. data/spec/extensions/current_datetime_timestamp_spec.rb +1 -1
  283. data/spec/extensions/dataset_associations_spec.rb +2 -1
  284. data/spec/extensions/dataset_source_alias_spec.rb +1 -1
  285. data/spec/extensions/date_arithmetic_spec.rb +3 -3
  286. data/spec/extensions/def_dataset_method_spec.rb +1 -1
  287. data/spec/extensions/defaults_setter_spec.rb +2 -2
  288. data/spec/extensions/delay_add_association_spec.rb +8 -9
  289. data/spec/extensions/dirty_spec.rb +1 -1
  290. data/spec/extensions/duplicate_columns_handler_spec.rb +1 -1
  291. data/spec/extensions/eager_each_spec.rb +2 -2
  292. data/spec/extensions/empty_array_consider_nulls_spec.rb +1 -1
  293. data/spec/extensions/error_splitter_spec.rb +1 -1
  294. data/spec/extensions/error_sql_spec.rb +1 -1
  295. data/spec/extensions/eval_inspect_spec.rb +1 -1
  296. data/spec/extensions/finder_spec.rb +1 -1
  297. data/spec/extensions/force_encoding_spec.rb +2 -5
  298. data/spec/extensions/freeze_datasets_spec.rb +1 -1
  299. data/spec/extensions/graph_each_spec.rb +5 -5
  300. data/spec/extensions/hook_class_methods_spec.rb +1 -194
  301. data/spec/extensions/identifier_mangling_spec.rb +17 -170
  302. data/spec/extensions/implicit_subquery_spec.rb +1 -5
  303. data/spec/extensions/inflector_spec.rb +1 -1
  304. data/spec/extensions/input_transformer_spec.rb +7 -2
  305. data/spec/extensions/insert_returning_select_spec.rb +1 -1
  306. data/spec/extensions/instance_filters_spec.rb +1 -1
  307. data/spec/extensions/instance_hooks_spec.rb +1 -95
  308. data/spec/extensions/inverted_subsets_spec.rb +1 -1
  309. data/spec/extensions/json_serializer_spec.rb +1 -1
  310. data/spec/extensions/lazy_attributes_spec.rb +1 -7
  311. data/spec/extensions/list_spec.rb +1 -1
  312. data/spec/extensions/looser_typecasting_spec.rb +1 -1
  313. data/spec/extensions/many_through_many_spec.rb +1 -1
  314. data/spec/extensions/migration_spec.rb +2 -2
  315. data/spec/extensions/modification_detection_spec.rb +1 -1
  316. data/spec/extensions/mssql_optimistic_locking_spec.rb +1 -1
  317. data/spec/extensions/named_timezones_spec.rb +3 -3
  318. data/spec/extensions/nested_attributes_spec.rb +1 -29
  319. data/spec/extensions/null_dataset_spec.rb +1 -11
  320. data/spec/extensions/optimistic_locking_spec.rb +1 -1
  321. data/spec/extensions/pagination_spec.rb +1 -1
  322. data/spec/extensions/pg_array_associations_spec.rb +4 -1
  323. data/spec/extensions/pg_array_ops_spec.rb +1 -1
  324. data/spec/extensions/pg_array_spec.rb +3 -48
  325. data/spec/extensions/pg_enum_spec.rb +1 -1
  326. data/spec/extensions/pg_hstore_ops_spec.rb +1 -1
  327. data/spec/extensions/pg_hstore_spec.rb +23 -32
  328. data/spec/extensions/pg_inet_ops_spec.rb +1 -1
  329. data/spec/extensions/pg_inet_spec.rb +1 -14
  330. data/spec/extensions/pg_interval_spec.rb +3 -13
  331. data/spec/extensions/pg_json_ops_spec.rb +1 -1
  332. data/spec/extensions/pg_json_spec.rb +1 -13
  333. data/spec/extensions/pg_loose_count_spec.rb +1 -1
  334. data/spec/extensions/pg_range_ops_spec.rb +1 -1
  335. data/spec/extensions/pg_range_spec.rb +3 -88
  336. data/spec/extensions/pg_row_ops_spec.rb +1 -1
  337. data/spec/extensions/pg_row_plugin_spec.rb +1 -1
  338. data/spec/extensions/pg_row_spec.rb +1 -44
  339. data/spec/extensions/pg_static_cache_updater_spec.rb +1 -1
  340. data/spec/extensions/prepared_statements_safe_spec.rb +1 -1
  341. data/spec/extensions/prepared_statements_spec.rb +13 -48
  342. data/spec/extensions/pretty_table_spec.rb +1 -1
  343. data/spec/extensions/query_spec.rb +1 -12
  344. data/spec/extensions/rcte_tree_spec.rb +1 -1
  345. data/spec/extensions/round_timestamps_spec.rb +1 -5
  346. data/spec/extensions/s_spec.rb +1 -1
  347. data/spec/extensions/schema_caching_spec.rb +1 -1
  348. data/spec/extensions/schema_dumper_spec.rb +1 -1
  349. data/spec/extensions/select_remove_spec.rb +1 -1
  350. data/spec/extensions/sequel_4_dataset_methods_spec.rb +1 -1
  351. data/spec/extensions/serialization_modification_detection_spec.rb +1 -1
  352. data/spec/extensions/serialization_spec.rb +2 -14
  353. data/spec/extensions/server_block_spec.rb +1 -1
  354. data/spec/extensions/server_logging_spec.rb +2 -2
  355. data/spec/extensions/sharding_spec.rb +1 -1
  356. data/spec/extensions/shared_caching_spec.rb +1 -28
  357. data/spec/extensions/single_table_inheritance_spec.rb +2 -5
  358. data/spec/extensions/singular_table_names_spec.rb +1 -1
  359. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  360. data/spec/extensions/spec_helper.rb +5 -27
  361. data/spec/extensions/split_array_nil_spec.rb +1 -1
  362. data/spec/extensions/split_values_spec.rb +1 -1
  363. data/spec/extensions/sql_comments_spec.rb +1 -1
  364. data/spec/extensions/sql_expr_spec.rb +1 -1
  365. data/spec/extensions/static_cache_spec.rb +1 -1
  366. data/spec/extensions/string_agg_spec.rb +2 -2
  367. data/spec/extensions/string_date_time_spec.rb +1 -1
  368. data/spec/extensions/string_stripper_spec.rb +1 -1
  369. data/spec/extensions/subclasses_spec.rb +1 -1
  370. data/spec/extensions/subset_conditions_spec.rb +1 -1
  371. data/spec/extensions/symbol_aref_refinement_spec.rb +1 -1
  372. data/spec/extensions/symbol_as_refinement_spec.rb +1 -1
  373. data/spec/extensions/table_select_spec.rb +4 -4
  374. data/spec/extensions/tactical_eager_loading_spec.rb +1 -6
  375. data/spec/extensions/thread_local_timezones_spec.rb +1 -1
  376. data/spec/extensions/timestamps_spec.rb +3 -3
  377. data/spec/extensions/to_dot_spec.rb +1 -1
  378. data/spec/extensions/touch_spec.rb +1 -1
  379. data/spec/extensions/tree_spec.rb +1 -1
  380. data/spec/extensions/typecast_on_load_spec.rb +1 -1
  381. data/spec/extensions/unlimited_update_spec.rb +1 -1
  382. data/spec/extensions/update_or_create_spec.rb +1 -1
  383. data/spec/extensions/update_primary_key_spec.rb +4 -3
  384. data/spec/extensions/update_refresh_spec.rb +1 -1
  385. data/spec/extensions/uuid_spec.rb +10 -12
  386. data/spec/extensions/validate_associated_spec.rb +1 -1
  387. data/spec/extensions/validation_class_methods_spec.rb +3 -3
  388. data/spec/extensions/validation_contexts_spec.rb +1 -1
  389. data/spec/extensions/validation_helpers_spec.rb +10 -44
  390. data/spec/extensions/whitelist_security_spec.rb +5 -5
  391. data/spec/extensions/xml_serializer_spec.rb +3 -3
  392. data/spec/guards_helper.rb +2 -1
  393. data/spec/integration/associations_test.rb +1 -23
  394. data/spec/integration/database_test.rb +7 -7
  395. data/spec/integration/dataset_test.rb +5 -47
  396. data/spec/integration/eager_loader_test.rb +1 -1
  397. data/spec/integration/migrator_test.rb +1 -1
  398. data/spec/integration/model_test.rb +4 -82
  399. data/spec/integration/plugin_test.rb +6 -22
  400. data/spec/integration/prepared_statement_test.rb +8 -88
  401. data/spec/integration/schema_test.rb +6 -6
  402. data/spec/integration/spec_helper.rb +13 -21
  403. data/spec/integration/timezone_test.rb +5 -5
  404. data/spec/integration/transaction_test.rb +3 -55
  405. data/spec/integration/type_test.rb +9 -9
  406. data/spec/model/association_reflection_spec.rb +24 -9
  407. data/spec/model/associations_spec.rb +124 -303
  408. data/spec/model/base_spec.rb +18 -137
  409. data/spec/model/class_dataset_methods_spec.rb +2 -20
  410. data/spec/model/dataset_methods_spec.rb +1 -20
  411. data/spec/model/eager_loading_spec.rb +17 -11
  412. data/spec/model/hooks_spec.rb +5 -300
  413. data/spec/model/inflector_spec.rb +1 -1
  414. data/spec/model/model_spec.rb +15 -320
  415. data/spec/model/plugins_spec.rb +2 -16
  416. data/spec/model/record_spec.rb +29 -121
  417. data/spec/model/spec_helper.rb +5 -15
  418. data/spec/model/validations_spec.rb +1 -1
  419. data/spec/sequel_warning.rb +1 -12
  420. metadata +8 -64
  421. data/doc/active_record.rdoc +0 -927
  422. data/lib/sequel/adapters/cubrid.rb +0 -160
  423. data/lib/sequel/adapters/do.rb +0 -166
  424. data/lib/sequel/adapters/do/mysql.rb +0 -69
  425. data/lib/sequel/adapters/do/postgres.rb +0 -46
  426. data/lib/sequel/adapters/do/sqlite3.rb +0 -41
  427. data/lib/sequel/adapters/jdbc/as400.rb +0 -92
  428. data/lib/sequel/adapters/jdbc/cubrid.rb +0 -65
  429. data/lib/sequel/adapters/jdbc/firebirdsql.rb +0 -37
  430. data/lib/sequel/adapters/jdbc/informix-sqli.rb +0 -34
  431. data/lib/sequel/adapters/jdbc/jdbcprogress.rb +0 -34
  432. data/lib/sequel/adapters/odbc/progress.rb +0 -12
  433. data/lib/sequel/adapters/shared/cubrid.rb +0 -245
  434. data/lib/sequel/adapters/shared/firebird.rb +0 -261
  435. data/lib/sequel/adapters/shared/informix.rb +0 -63
  436. data/lib/sequel/adapters/shared/progress.rb +0 -40
  437. data/lib/sequel/adapters/swift.rb +0 -169
  438. data/lib/sequel/adapters/swift/mysql.rb +0 -50
  439. data/lib/sequel/adapters/swift/postgres.rb +0 -49
  440. data/lib/sequel/adapters/swift/sqlite.rb +0 -48
  441. data/lib/sequel/adapters/utils/pg_types.rb +0 -4
  442. data/lib/sequel/dataset/mutation.rb +0 -98
  443. data/lib/sequel/extensions/_deprecated_identifier_mangling.rb +0 -117
  444. data/lib/sequel/extensions/empty_array_ignore_nulls.rb +0 -8
  445. data/lib/sequel/extensions/filter_having.rb +0 -65
  446. data/lib/sequel/extensions/hash_aliases.rb +0 -51
  447. data/lib/sequel/extensions/meta_def.rb +0 -37
  448. data/lib/sequel/extensions/query_literals.rb +0 -86
  449. data/lib/sequel/extensions/ruby18_symbol_extensions.rb +0 -26
  450. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +0 -133
  451. data/lib/sequel/extensions/set_overrides.rb +0 -82
  452. data/lib/sequel/no_core_ext.rb +0 -4
  453. data/lib/sequel/plugins/association_autoreloading.rb +0 -11
  454. data/lib/sequel/plugins/identifier_columns.rb +0 -49
  455. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +0 -11
  456. data/lib/sequel/plugins/pg_typecast_on_load.rb +0 -90
  457. data/lib/sequel/plugins/prepared_statements_associations.rb +0 -137
  458. data/lib/sequel/plugins/prepared_statements_with_pk.rb +0 -71
  459. data/lib/sequel/plugins/schema.rb +0 -84
  460. data/lib/sequel/plugins/scissors.rb +0 -37
  461. data/spec/core/dataset_mutation_spec.rb +0 -253
  462. data/spec/extensions/_deprecated_identifier_mangling_spec.rb +0 -314
  463. data/spec/extensions/before_after_save_spec.rb +0 -40
  464. data/spec/extensions/filter_having_spec.rb +0 -42
  465. data/spec/extensions/from_block_spec.rb +0 -21
  466. data/spec/extensions/hash_aliases_spec.rb +0 -26
  467. data/spec/extensions/identifier_columns_spec.rb +0 -19
  468. data/spec/extensions/meta_def_spec.rb +0 -35
  469. data/spec/extensions/no_auto_literal_strings_spec.rb +0 -69
  470. data/spec/extensions/pg_typecast_on_load_spec.rb +0 -70
  471. data/spec/extensions/prepared_statements_associations_spec.rb +0 -212
  472. data/spec/extensions/prepared_statements_with_pk_spec.rb +0 -40
  473. data/spec/extensions/query_literals_spec.rb +0 -185
  474. data/spec/extensions/schema_spec.rb +0 -123
  475. data/spec/extensions/scissors_spec.rb +0 -27
  476. data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -118
  477. data/spec/extensions/set_overrides_spec.rb +0 -75
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 272cf6bec70bfd569e735839c6e7dce242527188
4
- data.tar.gz: 8fac2b669b6d97264ef870f601a882a833d2abeb
3
+ metadata.gz: d494778be10a685dadd0181b0f35d8976ad80de5
4
+ data.tar.gz: 3de435547bc07c151e6511915b034c4c70909b28
5
5
  SHA512:
6
- metadata.gz: 5d1fffb914a7352c99aceb0d0ae222a36a6a48c3fef47aa9b10d1ffc494ae625e53f1f0435d009aa050e13fbf8e1296b6bb15110e19e1762bce0f8f77ce4621e
7
- data.tar.gz: f79ce483f64c7fbf4df674c374e2bac0009b6f1b479b8bb6e008921dd08ae2b88b16226427b26ce7bb3241c96ad0c2bbb55c6b66202efe4fa01e8813662a644e
6
+ metadata.gz: 71e23a94e737525c4bcf0ad0e16376a8ec933bf6962dce7c5032971ec3f8b7cb140c194ad51a41e818c4597025c3403b5f3777941ecf247595f8b7294ac9804f
7
+ data.tar.gz: d57c4092428f1ca13fb1fce70e9f26dae1f53e5c04f75aef5c5ad2ea5d0ac664c06443b86f7881a7abe7c499b977476fddb3155c9856290eb573b3a6d810b7a4
data/CHANGELOG CHANGED
@@ -1,3 +1,73 @@
1
+ === 5.0.0 (2017-09-01)
2
+
3
+ * Make bin/sequel -M option always use base 10 (jeremyevans)
4
+
5
+ * Don't use savepoints when creating indexes inside a transaction on databases that don't support transactional schema modifications (jeremyevans) (#1407)
6
+
7
+ * Support :if_not_exists option when creating indexes on PostgreSQL 9.5+ (DyegoCosta) (#1405)
8
+
9
+ * Make threaded connection pools not block while connections are being made (jeremyevans)
10
+
11
+ * SQL::Expression#clone and #dup now return self, since all expressions should be frozen value objects (jeremyevans)
12
+
13
+ * Don't create empty arrays for unused association callbacks (jeremyevans)
14
+
15
+ * Cache association method name symbols instead of recomputing them everytime (jeremyevans)
16
+
17
+ * Raise an exception if attempting to create a prepared statement using a dataset with a delayed evaluation (jeremyevans)
18
+
19
+ * Make ConnectionPool#size thread safe by using the pool mutex (jeremyevans)
20
+
21
+ * Use instance_exec instead of instance_eval when passing a block, to work with lambdas that accept no arguments (jeremyevans)
22
+
23
+ * Freeze SQL::StringAgg instances in string_agg extension (jeremyevans)
24
+
25
+ * Freeze SQL::DateAdd instances in date_arithmetic extension (jeremyevans)
26
+
27
+ * Freeze SQL::Expression.comparison_attrs (jeremyevans)
28
+
29
+ * Rename SQL::Subscript#f to #expression, keeping #f as an alias (jeremyevans)
30
+
31
+ * Require the :pool_class Database option be a class to use a custom connection pool (jeremyevans)
32
+
33
+ * Make the class_table_inheritance plugin raise an Error during update if any UPDATE query does not affect a single row (jeremyevans)
34
+
35
+ * Change most send calls to public_send unless calling private methods is expected (jeremyevans)
36
+
37
+ * Database schema and schema generator methods now return nil (jeremyevans)
38
+
39
+ * Model#validates_unique in the validation helpers plugin now defaults to only checking on new or modified values (jeremyevans)
40
+
41
+ * Deprecate Model#_before_validation (private_method), use Model#before_validation now (jeremyevans)
42
+
43
+ * Always run before/after/around validation hooks when saving, even when not validating the object (jeremyevans)
44
+
45
+ * Deprecate Model use_after_commit_rollback class and instance accessors (jeremyevans)
46
+
47
+ * Deprecate Model.allowed_columns reader (jeremyevans)
48
+
49
+ * Freeze internal constants that shouldn't be modified at runtime (jeremyevans)
50
+
51
+ * Attempt to connect to the database immediately when creating the Database instance (jeremyevans)
52
+
53
+ * Make association_pks plugin delay the setting of associated objects until the current object is saved by default (jeremyevans)
54
+
55
+ * Joined datasets used as model datasets are now automatically wrapped in a subquery (jeremyevans)
56
+
57
+ * Setting an invalid dataset for a model class now raises an exception by default (jeremyevans)
58
+
59
+ * Getting all values for newly created models now happens before calling after_create, instead of after (jeremyevans)
60
+
61
+ * Remove use of @was_new/@columns_updated instance variables when saving model objects (jeremyevans)
62
+
63
+ * Disable symbol splitting by default (jeremyevans)
64
+
65
+ * Make datasets frozen by default (jeremyevans)
66
+
67
+ * Drop support for ruby 1.8.7, minimum now is 1.9.2 (jeremyevans)
68
+
69
+ * Remove deprecated adapters, extensions, plugins, constants, and features (jeremyevans)
70
+
1
71
  === 4.49.0 (2017-08-01)
2
72
 
3
73
  * Make dataset_associations plugin automatically alias tables when using many_through_many associations that join the same table multiple times (jeremyevans)
@@ -8,9 +8,9 @@ toolkit for Ruby.
8
8
  * Sequel includes a comprehensive ORM layer for mapping
9
9
  records to Ruby objects and handling associated records.
10
10
  * Sequel supports advanced database features such as prepared
11
- statements, bound variables, stored procedures, savepoints,
12
- two-phase commit, transaction isolation, master/slave
13
- configurations, and database sharding.
11
+ statements, bound variables, savepoints, two-phase commit,
12
+ transaction isolation, master/slave configurations, and
13
+ database sharding.
14
14
  * Sequel currently has adapters for ADO, Amalgalite,
15
15
  IBM_DB, JDBC, MySQL, Mysql2, ODBC, Oracle,
16
16
  PostgreSQL, SQLAnywhere, SQLite3, and TinyTDS.
@@ -71,7 +71,7 @@ Sequel includes an IRB console for quick access to databases (usually referred t
71
71
 
72
72
  sequel sqlite://test.db # test.db in current directory
73
73
 
74
- You get an IRB session with the database object stored in DB.
74
+ You get an IRB session with the Sequel::Database object stored in DB.
75
75
 
76
76
  In addition to providing an IRB shell (the default behavior), bin/sequel also has support for migrating databases, dumping schema migrations, and copying databases. See the {bin/sequel guide}[rdoc-ref:doc/bin_sequel.rdoc] for more details.
77
77
 
@@ -89,18 +89,19 @@ Which is equivalent to:
89
89
 
90
90
  SELECT avg(GDP) FROM countries WHERE region = 'Middle East'
91
91
 
92
- Since datasets retrieve records only when needed, they can be stored and later reused. Records are fetched as hashes (or custom model objects), and are accessed using an +Enumerable+ interface:
92
+ Since datasets retrieve records only when needed, they can be stored and later reused. Records are fetched as hashes, and are accessed using an +Enumerable+ interface:
93
93
 
94
94
  middle_east = DB[:countries].where(:region => 'Middle East')
95
95
  middle_east.order(:name).each{|r| puts r[:name]}
96
96
 
97
97
  Sequel also offers convenience methods for extracting data from Datasets, such as an extended +map+ method:
98
98
 
99
- middle_east.map(:name) #=> ['Egypt', 'Turkey', 'Israel', ...]
99
+ middle_east.map(:name) # => ['Egypt', 'Turkey', 'Israel', ...]
100
+ middle_east.map([:id, :name]) # => [[1, 'Egypt'], [3, 'Turkey'], [2, 'Israel'], ...]
100
101
 
101
- Or getting results as a hash via +to_hash+, with one column as key and another as value:
102
+ Or getting results as a hash via +as_hash+, with one column as key and another as value:
102
103
 
103
- middle_east.to_hash(:name, :area) #=> {'Israel' => 20000, 'Turkey' => 120000, ...}
104
+ middle_east.as_hash(:name, :area) # => {'Israel' => 20000, 'Turkey' => 120000, ...}
104
105
 
105
106
  == Getting Started
106
107
 
@@ -118,7 +119,12 @@ The connection URL can also include such stuff as the user name, password, and p
118
119
  You can also specify optional parameters, such as the connection pool size, or loggers for logging SQL queries:
119
120
 
120
121
  DB = Sequel.connect("postgres://user:password@host:port/database_name",
121
- :max_connections => 10, :logger => Logger.new('log/db.log'))
122
+ max_connections: 10, logger: Logger.new('log/db.log'))
123
+
124
+ It is also possible to use a hash instead of a connection URL, but make sure to include the :adapter option in this case:
125
+
126
+ DB = Sequel.connect(adapter: :postgres, user: 'user', password: 'password', host: 'host', port: port,
127
+ database: 'database_name", max_connections: 10, logger: Logger.new('log/db.log'))
122
128
 
123
129
  You can specify a block to connect, which will disconnect from the database after it completes:
124
130
 
@@ -166,7 +172,7 @@ Datasets are the primary way records are retrieved and manipulated. They are ge
166
172
  posts = DB.from(:posts)
167
173
  posts = DB[:posts] # same
168
174
 
169
- Datasets will only fetch records when you tell them to. They can be manipulated to filter records, change ordering, join tables, etc..
175
+ Datasets will only fetch records when you tell them to. They can be manipulated to filter records, change ordering, join tables, etc.. Datasets are always frozen, and they safe to use by multiple threads concurrently.
170
176
 
171
177
  === Retrieving Records
172
178
 
@@ -188,68 +194,92 @@ Or perform more advanced stuff:
188
194
 
189
195
  You can also retrieve the first record in a dataset:
190
196
 
191
- posts.first
192
- # SELECT * FROM posts LIMIT 1
197
+ posts.order(:id).first
198
+ # SELECT * FROM posts ORDER BY id LIMIT 1
193
199
 
194
- Or retrieve a single record with a specific value:
200
+ Note that you can get the first record in a dataset even if it isn't ordered:
195
201
 
196
- posts[:id => 1]
197
- # SELECT * FROM posts WHERE id = 1 LIMIT 1
202
+ posts.first
203
+ # SELECT * FROM posts LIMIT 1
198
204
 
199
205
  If the dataset is ordered, you can also ask for the last record:
200
206
 
201
207
  posts.order(:stamp).last
202
208
  # SELECT * FROM posts ORDER BY stamp DESC LIMIT 1
203
209
 
210
+ You can also provide a filter when asking for a single record:
211
+
212
+ posts.first(:id => 1)
213
+ # SELECT * FROM posts WHERE id = 1 LIMIT 1
214
+
215
+ Or retrieve a single value for a specific record:
216
+
217
+ posts.where(:id => 1).get(:name)
218
+ # SELECT name FROM posts WHERE id = 1 LIMIT 1
219
+
204
220
  === Filtering Records
205
221
 
206
- An easy way to filter records is to provide a hash of values to match to +where+:
222
+ The most common way to filter records is to provide a hash of values to match to +where+:
207
223
 
208
- my_posts = posts.where(:category => 'ruby', :author => 'david')
209
- # WHERE category = 'ruby' AND author = 'david'
224
+ my_posts = posts.where(category: 'ruby', author: 'david')
225
+ # WHERE ((category = 'ruby') AND (author = 'david'))
210
226
 
211
227
  You can also specify ranges:
212
228
 
213
- my_posts = posts.where(:stamp => (Date.today - 14)..(Date.today - 7))
214
- # WHERE stamp >= '2010-06-30' AND stamp <= '2010-07-07'
229
+ my_posts = posts.where(stamp: (Date.today - 14)..(Date.today - 7))
230
+ # WHERE ((stamp >= '2010-06-30') AND (stamp <= '2010-07-07'))
215
231
 
216
232
  Or arrays of values:
217
233
 
218
- my_posts = posts.where(:category => ['ruby', 'postgres', 'linux'])
219
- # WHERE category IN ('ruby', 'postgres', 'linux')
234
+ my_posts = posts.where(category: ['ruby', 'postgres', 'linux'])
235
+ # WHERE (category IN ('ruby', 'postgres', 'linux'))
220
236
 
221
- Sequel also accepts expressions:
237
+ By passing a block to where, you can use expressions (this is fairly "magical"):
222
238
 
223
239
  my_posts = posts.where{stamp > Date.today << 1}
224
- # WHERE stamp > '2010-06-14'
240
+ # WHERE (stamp > '2010-06-14')
225
241
  my_posts = posts.where{stamp =~ Date.today}
226
- # WHERE stamp = '2010-07-14'
242
+ # WHERE (stamp = '2010-07-14')
243
+
244
+ If you want to wrap the objects yourself, you can use expressions without the "magic":
245
+
246
+ my_posts = posts.where(Sequel[:stamp] > Date.today << 1)
247
+ # WHERE (stamp > '2010-06-14')
248
+ my_posts = posts.where(Sequel[:stamp] =~ Date.today)
249
+ # WHERE (stamp = '2010-07-14')
227
250
 
228
- Some adapters will also let you specify Regexps:
251
+ Some databases such as PostgreSQL and MySQL also support filtering via Regexps:
229
252
 
230
- my_posts = posts.where(:category => /ruby/i)
231
- # WHERE category ~* 'ruby'
253
+ my_posts = posts.where(category: /ruby/i)
254
+ # WHERE (category ~* 'ruby')
232
255
 
233
256
  You can also use an inverse filter via +exclude+:
234
257
 
235
- my_posts = posts.exclude(:category => ['ruby', 'postgres', 'linux'])
236
- # WHERE category NOT IN ('ruby', 'postgres', 'linux')
258
+ my_posts = posts.exclude(category: ['ruby', 'postgres', 'linux'])
259
+ # WHERE (category NOT IN ('ruby', 'postgres', 'linux'))
237
260
 
238
- You can also specify a custom WHERE clause using a string:
261
+ But note that this does a full inversion of the filter:
239
262
 
240
- posts.where('stamp IS NOT NULL')
241
- # WHERE stamp IS NOT NULL
263
+ my_posts = posts.exclude(category: ['ruby', 'postgres', 'linux'], id: 1)
264
+ # WHERE ((category NOT IN ('ruby', 'postgres', 'linux')) OR (id != 1))
242
265
 
243
- You can use parameters in your string, as well:
266
+ If at any point you want to use a custom SQL fragment for part of a query,
267
+ you can do so via +Sequel.lit+:
268
+
269
+ posts.where(Sequel.lit('stamp IS NOT NULL'))
270
+ # WHERE (stamp IS NOT NULL)
271
+
272
+ You can safely interpolate parameters into the custom SQL fragment by
273
+ providing them as additional arguments:
244
274
 
245
275
  author_name = 'JKR'
246
- posts.where('(stamp < ?) AND (author != ?)', Date.today - 3, author_name)
247
- # WHERE (stamp < '2010-07-11') AND (author != 'JKR')
276
+ posts.where(Sequel.lit('(stamp < ?) AND (author != ?)', Date.today - 3, author_name))
277
+ # WHERE ((stamp < '2010-07-11') AND (author != 'JKR'))
248
278
 
249
279
  Datasets can also be used as subqueries:
250
280
 
251
- DB[:items].where('price > ?', DB[:items].select{avg(price) + 100})
252
- # WHERE price > (SELECT avg(price) + 100 FROM items)
281
+ DB[:items].where(Sequel[:price] > DB[:items].select{avg(price) + 100})
282
+ # WHERE (price > (SELECT avg(price) + 100 FROM items))
253
283
 
254
284
  After filtering, you can retrieve the matching records by using any of the retrieval methods:
255
285
 
@@ -268,7 +298,7 @@ issues that you should be aware of when using Sequel.
268
298
  Counting records is easy using +count+:
269
299
 
270
300
  posts.where(Sequel.like(:category, '%ruby%')).count
271
- # SELECT COUNT(*) FROM posts WHERE category LIKE '%ruby%'
301
+ # SELECT COUNT(*) FROM posts WHERE (category LIKE '%ruby%' ESCAPE '\')
272
302
 
273
303
  And you can also query maximum/minimum values via +max+ and +min+:
274
304
 
@@ -294,18 +324,15 @@ Ordering datasets is simple using +order+:
294
324
  posts.order(:stamp, :name)
295
325
  # ORDER BY stamp, name
296
326
 
297
- Chaining +order+ doesn't work the same as +where+:
327
+ +order+ always overrides the existing order:
298
328
 
299
329
  posts.order(:stamp).order(:name)
300
330
  # ORDER BY name
301
331
 
302
- The +order_append+ method chains this way, though:
332
+ If you would like to add to the existing order, use +order_append+ or +order_prepend+:
303
333
 
304
334
  posts.order(:stamp).order_append(:name)
305
335
  # ORDER BY stamp, name
306
-
307
- The +order_prepend+ method can be used as well:
308
-
309
336
  posts.order(:stamp).order_prepend(:name)
310
337
  # ORDER BY name, stamp
311
338
 
@@ -335,7 +362,7 @@ Selecting specific columns to be returned is also simple using +select+:
335
362
  posts.select(:stamp, :name)
336
363
  # SELECT stamp, name FROM posts
337
364
 
338
- Chaining +select+ works like +order+, not +where+:
365
+ Like +order+, +select+ overrides an existing selection:
339
366
 
340
367
  posts.select(:stamp).select(:name)
341
368
  # SELECT name FROM posts
@@ -349,52 +376,56 @@ As you might expect, there is an +order_append+ equivalent for +select+ called +
349
376
 
350
377
  Deleting records from the table is done with +delete+:
351
378
 
352
- posts.where('stamp < ?', Date.today - 3).delete
353
- # DELETE FROM posts WHERE stamp < '2010-07-11'
379
+ posts.where(Sequel[:stamp] < Date.today - 3).delete
380
+ # DELETE FROM posts WHERE (stamp < '2010-07-11')
354
381
 
355
382
  Be very careful when deleting, as +delete+ affects all rows in the dataset.
356
383
  Call +where+ first and +delete+ second:
357
384
 
358
385
  # DO THIS:
359
- posts.where('stamp < ?', Date.today - 7).delete
386
+ posts.where(Sequel[:stamp] < Date.today - 7).delete
360
387
  # NOT THIS:
361
- posts.delete.where('stamp < ?', Date.today - 7)
388
+ posts.delete.where(Sequel[:stamp] < Date.today - 7)
362
389
 
363
390
  === Inserting Records
364
391
 
365
392
  Inserting records into the table is done with +insert+:
366
393
 
367
- posts.insert(:category => 'ruby', :author => 'david')
394
+ posts.insert(category: 'ruby', author: 'david')
368
395
  # INSERT INTO posts (category, author) VALUES ('ruby', 'david')
369
396
 
370
397
  === Updating Records
371
398
 
372
399
  Updating records in the table is done with +update+:
373
400
 
374
- posts.where('stamp < ?', Date.today - 7).update(:state => 'archived')
375
- # UPDATE posts SET state = 'archived' WHERE stamp < '2010-07-07'
401
+ posts.where(Sequel[:stamp] < Date.today - 7).update(state: 'archived')
402
+ # UPDATE posts SET state = 'archived' WHERE (stamp < '2010-07-07')
376
403
 
377
- You can reference table columns when choosing what values to set:
404
+ You can provide arbitrary expressions when choosing what values to set:
378
405
 
379
- posts.where{|o| o.stamp < Date.today - 7}.update(:backup_number => Sequel.+(:backup_number, 1))
380
- # UPDATE posts SET backup_number = backup_number + 1 WHERE stamp < '2010-07-07'
406
+ posts.where(Sequel[:stamp] < Date.today - 7).update(backup_number: Sequel[:backup_number] + 1)
407
+ # UPDATE posts SET backup_number = (backup_number + 1) WHERE (stamp < '2010-07-07'))))
381
408
 
382
409
  As with +delete+, +update+ affects all rows in the dataset, so +where+ first,
383
410
  +update+ second:
384
411
 
385
412
  # DO THIS:
386
- posts.where('stamp < ?', Date.today - 7).update(:state => 'archived')
413
+ posts.where(Sequel[:stamp] < Date.today - 7).update(:state => 'archived')
387
414
  # NOT THIS:
388
- posts.update(:state => 'archived').where('stamp < ?', Date.today - 7)
415
+ posts.update(:state => 'archived').where(Sequel[:stamp] < Date.today - 7)
389
416
 
390
417
  === Transactions
391
418
 
392
- You can wrap some code in a database transaction using the <tt>Database#transaction</tt> method:
419
+ You can wrap a block of code in a database transaction using the <tt>Database#transaction</tt> method:
393
420
 
394
421
  DB.transaction do
395
- posts.insert(:category => 'ruby', :author => 'david')
396
- posts.where('stamp < ?', Date.today - 7).update(:state => 'archived')
422
+ # BEGIN
423
+ posts.insert(category: 'ruby', author: 'david')
424
+ # INSERT
425
+ posts.where(Sequel[:stamp] < Date.today - 7).update(:state => 'archived')
426
+ # UPDATE
397
427
  end
428
+ # COMMIT
398
429
 
399
430
  If the block does not raise an exception, the transaction will be committed.
400
431
  If the block does raise an exception, the transaction will be rolled back,
@@ -403,21 +434,24 @@ and not raise an exception outside the block, you can raise the
403
434
  <tt>Sequel::Rollback</tt> exception inside the block:
404
435
 
405
436
  DB.transaction do
437
+ # BEGIN
406
438
  posts.insert(:category => 'ruby', :author => 'david')
439
+ # INSERT
407
440
  if posts.where('stamp < ?', Date.today - 7).update(:state => 'archived') == 0
441
+ # UPDATE
408
442
  raise Sequel::Rollback
409
443
  end
410
444
  end
445
+ # ROLLBACK
411
446
 
412
447
  === Joining Tables
413
448
 
414
449
  Sequel makes it easy to join tables:
415
450
 
416
- order_items = DB[:items].join(:order_items, :item_id => :id).
417
- where(:order_id => 1234)
418
- # SELECT * FROM items INNER JOIN order_items
419
- # ON order_items.item_id = items.id
420
- # WHERE order_id = 1234
451
+ order_items = DB[:items].join(:order_items, item_id: :id).where(order_id: 1234)
452
+ # SELECT * FROM items
453
+ # INNER JOIN order_items ON (order_items.item_id = items.id)
454
+ # WHERE (order_id = 1234)
421
455
 
422
456
  The important thing to note here is that item_id is automatically qualified with
423
457
  the table being joined, and id is automatically qualified with the last table
@@ -426,9 +460,9 @@ joined.
426
460
  You can then do anything you like with the dataset:
427
461
 
428
462
  order_total = order_items.sum(:price)
429
- # SELECT sum(price) FROM items INNER JOIN order_items
430
- # ON order_items.item_id = items.id
431
- # WHERE order_items.order_id = 1234
463
+ # SELECT sum(price) FROM items
464
+ # INNER JOIN order_items ON (order_items.item_id = items.id)
465
+ # WHERE (order_id = 1234)
432
466
 
433
467
  Note that the default selection in Sequel is <tt>*</tt>, which includes all columns
434
468
  in all joined tables. Because Sequel returns results as a hash keyed by column name
@@ -440,57 +474,52 @@ selection using +select+, +select_all+, and/or +select_append+.
440
474
 
441
475
  Sequel expects column names to be specified using symbols. In addition, returned hashes always use symbols as their keys. This allows you to freely mix literal values and column references in many cases. For example, the two following lines produce equivalent SQL:
442
476
 
443
- items.where(:x => 1)
477
+ items.where(x: 1)
444
478
  # SELECT * FROM items WHERE (x = 1)
445
479
  items.where(1 => :x)
446
480
  # SELECT * FROM items WHERE (1 = x)"
447
481
 
448
482
  Ruby strings are generally treated as SQL strings:
449
483
 
450
- items.where(:x => 'x')
484
+ items.where(x: 'x')
451
485
  # SELECT * FROM items WHERE (x = 'x')
452
486
 
453
487
  === Qualifying identifiers (column/table names)
454
488
 
455
489
  An identifier in SQL is a name that represents a column, table, or schema.
456
- By default, identifiers can be qualified by using the double underscore special notation <tt>:table__column</tt>:
457
-
458
- items.literal(:items__price)
459
- # items.price
490
+ The recommended way to qualify columns is to use <tt>Sequel[][]</tt> or +Sequel.qualify+
460
491
 
461
- Another way to qualify columns is to use the <tt>Sequel[][]</tt> method:
492
+ Sequel[:table][:column]
493
+ Sequel.qualify(:table, :column)
494
+ # table.column
462
495
 
463
- items.literal(Sequel[:items][:price])
464
- # items.price
496
+ You can also qualify tables with schemas:
465
497
 
466
- While it is more common to qualify column identifiers with table identifiers, you can also qualify table identifiers with schema identifiers
467
- to select from a qualified table:
498
+ Sequel[:schema][:table]
499
+ # schema.table
468
500
 
469
- posts = DB[:some_schema__posts]
470
- # SELECT * FROM some_schema.posts
501
+ or use multi-level qualification:
471
502
 
472
- === Identifier aliases
503
+ Sequel[:schema][:table][:column]
504
+ # schema.table.column
473
505
 
474
- By default, you can also alias identifiers by using the triple underscore special notation <tt>:column___alias</tt> or <tt>:table__column___alias</tt>:
506
+ === Expression aliases
475
507
 
476
- items.literal(:price___p)
477
- # price AS p
478
- items.literal(:items__price___p)
479
- # items.price AS p
508
+ You can alias identifiers using <tt>Sequel[].as</tt> or +Sequel.as+:
480
509
 
481
- Another way to alias columns is to use the <tt>Sequel.as</tt> method:
482
-
483
- items.literal(Sequel.as(:price, :p))
484
- # price AS p
510
+ Sequel[:column].as(:alias)
511
+ Sequel.as(:column, :alias)
512
+ # column AS alias
485
513
 
486
514
  You can use the <tt>Sequel.as</tt> method to alias arbitrary expressions, not just identifiers:
487
515
 
488
- items.literal(Sequel.as(DB[:posts].select{max(id)}, :p))
516
+ Sequel.as(DB[:posts].select{max(id)}, :p)
489
517
  # (SELECT max(id) FROM posts) AS p
490
518
 
491
- You can turn off the splitting of symbols containing double and triple underscores, and treat all symbols as regular identifiers, by using:
519
+ And most Sequel expression objects support an +as+ method for aliasing:
492
520
 
493
- Sequel.split_symbols = false
521
+ (Sequel[:column] + 2).as(:c_plus_2)
522
+ # (column + 2) AS c_plus_2
494
523
 
495
524
  == Sequel Models
496
525
 
@@ -508,7 +537,7 @@ implements the active record pattern).
508
537
 
509
538
  Sequel model classes assume that the table name is an underscored plural of the class name:
510
539
 
511
- Post.table_name #=> :posts
540
+ Post.table_name # => :posts
512
541
 
513
542
  You can explicitly set the table name or even the dataset used:
514
543
 
@@ -518,27 +547,27 @@ You can explicitly set the table name or even the dataset used:
518
547
 
519
548
  If you pass a symbol to the <tt>Sequel::Model</tt> method, it assumes you are referring to the table with the same name. You can also call it with a dataset, which will set the defaults for all retrievals for that model:
520
549
 
521
- class Post < Sequel::Model(DB[:my_posts].where(:category => 'ruby')); end
550
+ class Post < Sequel::Model(DB[:my_posts].where(category: 'ruby')); end
522
551
  class Post < Sequel::Model(DB[:my_posts].select(:id, :name).order(:date)); end
523
552
 
524
553
  === Model instances
525
554
 
526
- Model instances are identified by a primary key. In most cases, Sequel can query the database to determine the primary key, but if not, it defaults to using <tt>:id</tt>. The <tt>Model.[]</tt> method can be used to fetch records by their primary key:
555
+ Model instances are identified by a primary key. Sequel queries the database to determine the primary key for each model. The <tt>Model.[]</tt> method can be used to fetch records by their primary key:
527
556
 
528
557
  post = Post[123]
529
558
 
530
559
  The +pk+ method is used to retrieve the record's primary key value:
531
560
 
532
- post.pk #=> 123
561
+ post.pk # => 123
533
562
 
534
- Sequel models allow you to use any column as a primary key, and even composite keys made from multiple columns:
563
+ If you want to override which column(s) to use as the primary key, you can use +set_primary_key+:
535
564
 
536
565
  class Post < Sequel::Model
537
566
  set_primary_key [:category, :title]
538
567
  end
539
568
 
540
569
  post = Post['ruby', 'hello world']
541
- post.pk #=> ['ruby', 'hello world']
570
+ post.pk # => ['ruby', 'hello world']
542
571
 
543
572
  You can also define a model class that does not have a primary key via +no_primary_key+, but then you lose the ability to easily update and delete records:
544
573
 
@@ -546,39 +575,43 @@ You can also define a model class that does not have a primary key via +no_prima
546
575
 
547
576
  A single model instance can also be fetched by specifying a condition:
548
577
 
549
- post = Post[:title => 'hello world']
578
+ post = Post.first(title: 'hello world')
550
579
  post = Post.first{num_comments < 10}
551
580
 
581
+ The dataset for a model class returns rows a model instances instead of plain hashes:
582
+
583
+ DB[:posts].first.class # => Hash
584
+ Post.first.class # => Post
585
+
552
586
  === Acts like a dataset
553
587
 
554
588
  A model class forwards many methods to the underlying dataset. This means that you can use most of the +Dataset+ API to create customized queries that return model instances, e.g.:
555
589
 
556
- Post.where(:category => 'ruby').each{|post| p post}
590
+ Post.where(category: 'ruby').each{|post| p post}
557
591
 
558
592
  You can also manipulate the records in the dataset:
559
593
 
560
594
  Post.where{num_comments < 7}.delete
561
- Post.where(Sequel.like(:title, /ruby/)).update(:category => 'ruby')
595
+ Post.where(Sequel.like(:title, /ruby/)).update(category: 'ruby')
562
596
 
563
597
  === Accessing record values
564
598
 
565
599
  A model instance stores its values as a hash with column symbol keys, which you can access directly via the +values+ method:
566
600
 
567
- post.values #=> {:id => 123, :category => 'ruby', :title => 'hello world'}
601
+ post.values # => {:id => 123, :category => 'ruby', :title => 'hello world'}
568
602
 
569
603
  You can read the record values as object attributes, assuming the attribute names are valid columns in the model's dataset:
570
604
 
571
- post.id #=> 123
572
- post.title #=> 'hello world'
605
+ post.id # => 123
606
+ post.title # => 'hello world'
573
607
 
574
608
  If the record's attributes names are not valid columns in the model's dataset (maybe because you used +select_append+ to add a computed value column), you can use <tt>Model#[]</tt> to access the values:
575
609
 
576
- post[:id] #=> 123
577
- post[:title] #=> 'hello world'
610
+ post[:id] # => 123
611
+ post[:title] # => 'hello world'
578
612
 
579
613
  You can also modify record values using attribute setters or the <tt>[]=</tt> method.
580
614
 
581
-
582
615
  post.title = 'hey there'
583
616
  post[:title] = 'hey there'
584
617
 
@@ -590,24 +623,26 @@ That will just change the value for the object, it will not update the row in th
590
623
 
591
624
  You can also set the values for multiple columns in a single method call, using one of the mass-assignment methods. See the {mass assignment guide}[rdoc-ref:doc/mass_assignment.rdoc] for details. For example +set+ updates the model's column values without saving:
592
625
 
593
- post.set(:title=>'hey there', :updated_by=>'foo')
626
+ post.set(title: 'hey there', updated_by: 'foo')
594
627
 
595
628
  and +update+ updates the model's column values and then saves the changes to the database:
596
629
 
597
- post.update(:title => 'hey there', :updated_by=>'foo')
630
+ post.update(title: 'hey there', updated_by: 'foo')
598
631
 
599
632
  === Creating new records
600
633
 
601
- New records can be created by calling <tt>Model.create</tt>:
634
+ New model instances can be created by calling <tt>Model.new</tt>, which returns a new model instance without updating the database:
602
635
 
603
- post = Post.create(:title => 'hello world')
636
+ post = Post.new(title: 'hello world')
604
637
 
605
- Another way is to construct a new instance and save it later:
638
+ You can save the record to the database later by calling +save+ on the model instance:
606
639
 
607
- post = Post.new
608
- post.title = 'hello world'
609
640
  post.save
610
641
 
642
+ If you want to create a new record and save it to the database at the same time, you can use <tt>Model.create</tt>:
643
+
644
+ post = Post.create(title: 'hello world')
645
+
611
646
  You can also supply a block to <tt>Model.new</tt> and <tt>Model.create</tt>:
612
647
 
613
648
  post = Post.new do |p|
@@ -634,7 +669,7 @@ You can execute custom code when creating, updating, or deleting records by defi
634
669
 
635
670
  Note the use of +super+ if you define your own hook methods. Almost all <tt>Sequel::Model</tt> class and instance methods (not just hook methods) can be overridden safely, but you have to make sure to call +super+ when doing so, otherwise you risk breaking things.
636
671
 
637
- For the example above, you should probably use a database trigger if you can. Hooks can be used for data integrity, but they will only enforce that integrity when you are modifying the database through model instances, and even then they are often subject to race conditions. It's best to use database triggers and constraints to enforce data integrity.
672
+ For the example above, you should probably use a database trigger if you can. Hooks can be used for data integrity, but they will only enforce that integrity when you are modifying the database through model instances, and even then they are often subject to race conditions. It's best to use database triggers and database constraints to enforce data integrity.
638
673
 
639
674
  === Deleting records
640
675
 
@@ -666,21 +701,21 @@ Associations are used in order to specify relationships between model classes th
666
701
 
667
702
  +many_to_one+ and +one_to_one+ create a getter and setter for each model object:
668
703
 
669
- post = Post.create(:name => 'hi!')
670
- post.author = Author[:name => 'Sharon']
704
+ post = Post.create(name: 'hi!')
705
+ post.author = Author.first(name: 'Sharon')
671
706
  post.author
672
707
 
673
708
  +one_to_many+ and +many_to_many+ create a getter method, a method for adding an object to the association, a method for removing an object from the association, and a method for removing all associated objects from the association:
674
709
 
675
- post = Post.create(:name => 'hi!')
710
+ post = Post.create(name: 'hi!')
676
711
  post.comments
677
712
 
678
- comment = Comment.create(:text=>'hi')
713
+ comment = Comment.create(text: 'hi')
679
714
  post.add_comment(comment)
680
715
  post.remove_comment(comment)
681
716
  post.remove_all_comments
682
717
 
683
- tag = Tag.create(:tag=>'interesting')
718
+ tag = Tag.create(tag: 'interesting')
684
719
  post.add_tag(tag)
685
720
  post.remove_tag(tag)
686
721
  post.remove_all_tags
@@ -693,7 +728,7 @@ All associations add a dataset method that can be used to further filter or reor
693
728
  post.comments_dataset.destroy
694
729
 
695
730
  # Return all tags related to this post with no subscribers, ordered by the tag's name
696
- post.tags_dataset.where(:subscribers=>0).order(:name).all
731
+ post.tags_dataset.where(subscribers: 0).order(:name).all
697
732
 
698
733
  === Eager Loading
699
734
 
@@ -735,32 +770,32 @@ Associations can be eagerly loaded via +eager+ and the <tt>:eager</tt> associati
735
770
  Post.eager(:person).eager(:tags).all
736
771
 
737
772
  # Cascading via .eager
738
- Tag.eager(:posts=>:replies).all
773
+ Tag.eager(posts: :replies).all
739
774
 
740
775
  # Will also grab all associated posts' tags (because of :eager)
741
- Reply.eager(:person=>:posts).all
776
+ Reply.eager(person: :posts).all
742
777
 
743
778
  # No depth limit (other than memory/stack), and will also grab posts' tags
744
779
  # Loads all people, their posts, their posts' tags, replies to those posts,
745
780
  # the person for each reply, the tag for each reply, and all posts and
746
781
  # replies that have that tag. Uses a total of 8 queries.
747
- Person.eager(:posts=>{:replies=>[:person, {:tags=>[:posts, :replies]}]}).all
782
+ Person.eager(posts: {replies: [:person, {tags: [:posts, :replies]}]}).all
748
783
 
749
- In addition to using +eager+, you can also use +eager_graph+, which will use a single query to get the object and all associated objects. This may be necessary if you want to filter or order the result set based on columns in associated tables. It works with cascading as well, the API is very similar. Note that using +eager_graph+ to eagerly load multiple <tt>*_to_many</tt> associations will cause the result set to be a cartesian product, so you should be very careful with your filters when using it in that case.
784
+ In addition to using +eager+, you can also use +eager_graph+, which will use a single query to get the object and all associated objects. This may be necessary if you want to filter or order the result set based on columns in associated tables. It works with cascading as well, the API is similar. Note that using +eager_graph+ to eagerly load multiple <tt>*_to_many</tt> associations will cause the result set to be a cartesian product, so you should be very careful with your filters when using it in that case.
750
785
 
751
786
  You can dynamically customize the eagerly loaded dataset by using a proc. This proc is passed the dataset used for eager loading, and should return a modified copy of that dataset:
752
787
 
753
788
  # Eagerly load only replies containing 'foo'
754
- Post.eager(:replies=>proc{|ds| ds.where(Sequel.like(text, '%foo%'))}).all
789
+ Post.eager(replies: proc{|ds| ds.where(Sequel.like(text, '%foo%'))}).all
755
790
 
756
791
  This also works when using +eager_graph+, in which case the proc is called with dataset to graph into the current dataset:
757
792
 
758
- Post.eager_graph(:replies=>proc{|ds| ds.where(Sequel.like(text, '%foo%'))}).all
793
+ Post.eager_graph(replies: proc{|ds| ds.where(Sequel.like(text, '%foo%'))}).all
759
794
 
760
795
  You can dynamically customize eager loads for both +eager+ and +eager_graph+ while also cascading, by making the value a single entry hash with the proc as a key, and the cascaded associations as the value:
761
796
 
762
797
  # Eagerly load only replies containing 'foo', and the person and tags for those replies
763
- Post.eager(:replies=>{proc{|ds| ds.where(Sequel.like(text, '%foo%'))}=>[:person, :tags]}).all
798
+ Post.eager(replies: {proc{|ds| ds.where(Sequel.like(text, '%foo%'))} => [:person, :tags]}).all
764
799
 
765
800
  === Joining with Associations
766
801
 
@@ -778,7 +813,7 @@ This comes with variants for different join types:
778
813
 
779
814
  Similar to the eager loading methods, you can use multiple associations and nested associations:
780
815
 
781
- Post.association_join(:author, :replies=>:person).all
816
+ Post.association_join(:author, replies: :person).all
782
817
  # SELECT * FROM posts
783
818
  # INNER JOIN authors AS author ON (author.id = posts.author_id)
784
819
  # INNER JOIN replies ON (replies.post_id = posts.id)
@@ -802,16 +837,16 @@ The recommended way to implement table-wide logic by defining methods on the dat
802
837
 
803
838
  This allows you to have access to your model API from filtered datasets as well:
804
839
 
805
- Post.where(:category => 'ruby').clean_boring
840
+ Post.where(category: 'ruby').clean_boring
806
841
  # DELETE FROM posts WHERE ((category = 'ruby') AND (num_comments < 30))
807
842
 
808
843
  Inside +dataset_module+ blocks, there are numerous methods that support easy creation of dataset methods.
809
844
  Most of these methods are named after the dataset methods themselves, such as +select+, +order+, and
810
- +group+, and there is also a method named +subset+ which uses a filter:
845
+ +group+:
811
846
 
812
847
  class Post < Sequel::Model
813
848
  dataset_module do
814
- subset(:with_few_comments){num_comments < 30}
849
+ where(:with_few_comments, Sequel[:num_comments] < 30)
815
850
  select :with_title_and_date, :id, :title, :post_date
816
851
  order :by_post_date, :post_date
817
852
  limit :top10, 10
@@ -824,6 +859,10 @@ Most of these methods are named after the dataset methods themselves, such as +s
824
859
  # ORDER BY post_date
825
860
  # LIMIT 10
826
861
 
862
+ One advantage of using these methods inside dataset_module blocks, instead of
863
+ defining methods manually, is that the created methods will generally cache
864
+ the resulting values and result in better performance.
865
+
827
866
  === Model Validations
828
867
 
829
868
  You can define a +validate+ method for your model, which +save+
@@ -831,8 +870,7 @@ will check before attempting to save the model in the database.
831
870
  If an attribute of the model isn't valid, you should add an error
832
871
  message for that attribute to the model object's +errors+. If an
833
872
  object has any errors added by the validate method, +save+ will
834
- raise an error or return false depending on how it is configured
835
- (the +raise_on_save_failure+ flag).
873
+ raise an error by default:
836
874
 
837
875
  class Post < Sequel::Model
838
876
  def validate
@@ -841,3 +879,24 @@ raise an error or return false depending on how it is configured
841
879
  errors.add(:written_on, "should be in the past") if written_on >= Time.now
842
880
  end
843
881
  end
882
+
883
+ == Sequel Release Policy
884
+
885
+ New major versions of Sequel do not have a defined release policy, but historically have
886
+ occurred once ever few years.
887
+
888
+ New minor versions of Sequel are released around once a month near the start of the month.
889
+
890
+ New tiny versions of Sequel are only released to address security issues or regressions
891
+ in the most current release.
892
+
893
+ == Ruby Support Policy
894
+
895
+ Sequel fully supports the currently supported versions of Ruby (MRI) and JRuby. It may
896
+ support unsupported versions of Ruby or JRuby, but such support may be dropped in any
897
+ minor version of keeping it becomes a support issue. The minimum Ruby version
898
+ required to run the current version of Sequel is 1.9.2.
899
+
900
+ == Maintainer
901
+
902
+ Jeremy Evans <code@jeremyevans.net>