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
@@ -22,7 +22,7 @@ For SELECT queries, you should probably use <tt>Database#fetch</tt> with a strin
22
22
 
23
23
  You can also use named placeholders by starting the placeholder with a colon, and using a hash for the argument:
24
24
 
25
- DB.fetch("SELECT * FROM albums WHERE name LIKE :pattern", :pattern=>'A%') do |row|
25
+ DB.fetch("SELECT * FROM albums WHERE name LIKE :pattern", pattern: 'A%') do |row|
26
26
  puts row[:name]
27
27
  end
28
28
 
@@ -121,21 +121,15 @@ As you can see, Sequel quotes identifiers by default. Depending on your databas
121
121
 
122
122
  :column # "COLUMN" on some databases
123
123
 
124
- A plain symbol is usually treated as an unqualified identifier. However, if you are using multiple tables in a query, and you want to reference a column in one of the tables that has the same name as a column in another one of the tables, you need to qualify that reference. There are two main ways in Sequel to do that. The first is implicit qualification inside the symbol, using the double underscore:
125
-
126
- :table__column # "table"."column"
127
-
128
- This works by default, but it is possible to turn off by setting <tt>Sequel.split_symbols = false</tt>.
129
-
130
- Note that you can't use a period to separate them:
124
+ A plain symbol is usually treated as an unqualified identifier. However, if you are using multiple tables in a query, and you want to reference a column in one of the tables that has the same name as a column in another one of the tables, you need to qualify that reference. Note that you can't use a period to separate them:
131
125
 
132
126
  :table.column # calls the column method on the symbol
133
127
 
134
128
  Also note that specifying the period inside the symbol doesn't work if you are quoting identifiers:
135
129
 
136
- :"table.column" # "table.column"
130
+ :"table.column" # "table.column" instead of "table"."column"
137
131
 
138
- The second way is to explicitly create a qualified identifier either by using <tt>Sequel.[]</tt> to create an identifier and call <tt>[]</tt> or +qualify+ on that, or by using the <tt>Sequel.qualify</tt> method with the table and column symbols:
132
+ There are a few different Sequel methods for creating qualified identifier objects. The recommended way is to explicitly create a qualified identifier by using <tt>Sequel.[]</tt> to create an identifier and call <tt>[]</tt> or +qualify+ on that, or by using the <tt>Sequel.qualify</tt> method with the table and column symbols:
139
133
 
140
134
  Sequel[:table][:column] # "table"."column"
141
135
  Sequel[:column].qualify(:table) # "table"."column"
@@ -148,6 +142,7 @@ Another way to generate identifiers is to use Sequel's {virtual row support}[rdo
148
142
 
149
143
  You can also use the symbol_aref extension for creating qualified identifiers:
150
144
 
145
+ Sequel.extension :symbol_aref
151
146
  :table[:column] # "table"."column"
152
147
 
153
148
  === Numbers
@@ -173,24 +168,16 @@ In general, Ruby strings map directly to SQL strings:
173
168
 
174
169
  === Aliasing
175
170
 
176
- Sequel allows for implicit aliasing in column symbols using the triple underscore:
177
-
178
- :column___alias # "column" AS "alias"
179
-
180
- You can combine this with implicit qualification:
181
-
182
- :table__column___alias # "table"."column" AS "alias"
183
-
184
- As with creating qualified identifiers via a double underscore, this works by default, but it is possible to turn off by setting <tt>Sequel.split_symbols = false</tt>.
185
-
186
- You can also use the <tt>Sequel.as</tt> method to create an alias, and the +as+ method on most Sequel-specific expression objects:
171
+ You can use the <tt>Sequel.as</tt> method to create an alias, and the +as+ method on most Sequel-specific expression objects:
187
172
 
188
173
  Sequel.as(:column, :alias) # "column" AS "alias"
189
174
  Sequel[:column].as(:alias) # "column" AS "alias"
190
175
  Sequel[:table][:column].as(:alias) # "table"."column" AS "alias"
176
+ (Sequel[:column] + 1).as(:alias) # ("column" + 1) AS "alias"
191
177
 
192
178
  You can also use the symbol_as extension for creating aliased identifiers:
193
179
 
180
+ Sequel.extension :symbol_as
194
181
  :column.as(:alias) # "column" AS "alias"
195
182
 
196
183
  If you want to use a derived column list, you can provide an array of column aliases:
@@ -215,11 +202,11 @@ Aggregate functions work the same way as normal functions, since they share the
215
202
 
216
203
  Sequel.function(:sum, :column) # sum(column)
217
204
 
218
- To use the DISTINCT modifier to an aggregate function, call the +distinct+ method on the function:
205
+ To use the DISTINCT modifier to an aggregate function, call the +distinct+ method on the function expression, which returns a new function expression:
219
206
 
220
207
  DB[:albums].select{sum(:column).distinct} # SELECT sum(DISTINCT column) FROM albums
221
208
 
222
- If you want to use the wildcard as the sole argument of the aggregate function, use the * method on the Function:
209
+ If you want to use the wildcard as the sole argument of the aggregate function, use the * method on the function expression:
223
210
 
224
211
  Sequel.function(:count).* # count(*)
225
212
  DB[:albums].select{count.function.*} # SELECT count(*) FROM albums
@@ -228,10 +215,10 @@ Note that Sequel provides helper methods for aggregate functions such as +count+
228
215
 
229
216
  === Window Functions
230
217
 
231
- If the database supports window functions, Sequel can handle them by calling the +over+ method on a Function:
218
+ If the database supports window functions, Sequel can handle them by calling the +over+ method on a function expression:
232
219
 
233
- DB[:albums].select{function.function.over}
234
- # SELECT function() OVER () FROM albums
220
+ DB[:albums].select{row_number.function.over}
221
+ # SELECT row_number() OVER () FROM albums
235
222
 
236
223
  DB[:albums].select{count.function.*.over}
237
224
  # SELECT count(*) OVER () FROM albums
@@ -244,12 +231,12 @@ If the database supports window functions, Sequel can handle them by calling the
244
231
 
245
232
  === Schema Qualified Functions
246
233
 
247
- If the database supports schema qualified functions, Sequel can handle them by calling the +function+ method on a QuailfiedIdentifier:
234
+ If the database supports schema qualified functions, Sequel can handle them by calling the +function+ method on a qualified identifier:
248
235
 
249
236
  DB[:albums].select{schema[:function].function}
250
237
  # SELECT schema.function() FROM albums
251
238
 
252
- DB[:albums].select{schema[:function].function(col, 2, "a")}
239
+ DB[:albums].select{schema[:function].function(:col, 2, "a")}
253
240
  # SELECT schema.function(col, 2, 'a') FROM albums
254
241
 
255
242
  === Portable/Emulated Functions
@@ -265,7 +252,7 @@ Some examples are:
265
252
 
266
253
  Sequel uses hashes to specify equality:
267
254
 
268
- {:column=>1} # ("column" = 1)
255
+ {column: 1} # ("column" = 1)
269
256
 
270
257
  You can also specify this as an array of two element arrays:
271
258
 
@@ -279,27 +266,27 @@ For expression objects, you can also use the =~ method:
279
266
 
280
267
  You can specify a not equals condition by inverting the hash or array of two element arrays using <tt>Sequel.negate</tt> or <tt>Sequel.~</tt>:
281
268
 
282
- Sequel.negate(:column => 1) # ("column" != 1)
269
+ Sequel.negate(column: 1) # ("column" != 1)
283
270
  Sequel.negate([[:column, 1]]) # ("column" != 1)
284
- Sequel.~(:column => 1) # ("column" != 1)
271
+ Sequel.~(column: 1) # ("column" != 1)
285
272
  Sequel.~([[:column, 1]]) # ("column" != 1)
286
273
 
287
274
  The difference between the two is that +negate+ only works on hashes and arrays of element arrays, and it negates all entries in the hash or array, while ~ does a general inversion. This is best shown by an example with multiple entries:
288
275
 
289
- Sequel.negate(:column => 1, :foo => 2) # (("column" != 1) AND (foo != 2))
290
- Sequel.~(:column => 1, :foo => 2) # (("column" != 1) OR (foo != 2))
276
+ Sequel.negate(column: 1, foo: 2) # (("column" != 1) AND (foo != 2))
277
+ Sequel.~(column: 1, foo: 2) # (("column" != 1) OR (foo != 2))
291
278
 
292
279
  You can also use the ~ method on an equality expression:
293
280
 
294
281
  where{~(column =~ 1)} # ("column" != 1)
295
282
 
296
- On Ruby 1.9+, you can use the !~ method:
283
+ Or you can use the !~ method:
297
284
 
298
285
  where{column !~ 1} # ("column" != 1)
299
286
 
300
287
  The most common need for not equals is in filters, in which case you can use the +exclude+ method:
301
288
 
302
- DB[:albums].exclude(:column=>1) # SELECT * FROM "albums" WHERE ("column" != 1)
289
+ DB[:albums].exclude(column: 1) # SELECT * FROM "albums" WHERE ("column" != 1)
303
290
 
304
291
  Note that +exclude+ does a generalized inversion, similar to <tt>Sequel.~</tt>.
305
292
 
@@ -307,19 +294,19 @@ Note that +exclude+ does a generalized inversion, similar to <tt>Sequel.~</tt>.
307
294
 
308
295
  Sequel also uses hashes to specify inclusion, and inversions of those hashes to specify exclusion:
309
296
 
310
- {:column=>[1, 2, 3]} # ("column" IN (1, 2, 3))
311
- Sequel.~(:column=>[1, 2, 3]) # ("column" NOT IN (1, 2, 3))
297
+ {column: [1, 2, 3]} # ("column" IN (1, 2, 3))
298
+ Sequel.~(column: [1, 2, 3]) # ("column" NOT IN (1, 2, 3))
312
299
 
313
300
  As you may have guessed, Sequel switches from an = to an IN when the hash value is an array. It also does this for datasets, which easily allows you to test for inclusion and exclusion in a subselect:
314
301
 
315
- {:column=>DB[:albums].select(:id)} # ("column" IN (SELECT "id" FROM "albums"))
316
- Sequel.~(:column=>DB[:albums].select(:id)) # ("column" NOT IN (SELECT "id" FROM "albums"))
302
+ {column: DB[:albums].select(:id)} # ("column" IN (SELECT "id" FROM "albums"))
303
+ Sequel.~(column: DB[:albums].select(:id)) # ("column" NOT IN (SELECT "id" FROM "albums"))
317
304
 
318
305
  Similar to =, you can also use =~ with expressions for inclusion:
319
306
 
320
307
  where{column =~ [1, 2, 3]} # ("column" IN (1, 2, 3))
321
308
 
322
- and on Ruby 1.9, !~ for exclusion:
309
+ and !~ for exclusion:
323
310
 
324
311
  where{column !~ [1, 2, 3]} # ("column" NOT IN (1, 2, 3))
325
312
 
@@ -331,17 +318,17 @@ Sequel also supports the SQL EXISTS operator using <tt>Dataset#exists</tt>:
331
318
 
332
319
  Hashes in Sequel use IS if the value is +true+, +false+, or +nil+:
333
320
 
334
- {:column=>nil} # ("column" IS NULL)
335
- {:column=>true} # ("column" IS TRUE)
336
- {:column=>false} # ("column" IS FALSE)
321
+ {column: nil} # ("column" IS NULL)
322
+ {column: true} # ("column" IS TRUE)
323
+ {column: false} # ("column" IS FALSE)
337
324
 
338
325
  Negation works the same way as it does for equality and inclusion:
339
326
 
340
- Sequel.~(:column=>nil) # ("column" IS NOT NULL)
341
- Sequel.~(:column=>true) # ("column" IS NOT TRUE)
342
- Sequel.~(:column=>false) # ("column" IS NOT FALSE)
327
+ Sequel.~(column: nil) # ("column" IS NOT NULL)
328
+ Sequel.~(column: true) # ("column" IS NOT TRUE)
329
+ Sequel.~(column: false) # ("column" IS NOT FALSE)
343
330
 
344
- Likewise, =~ works for identity (and Ruby 1.9, !~ for negative identity):
331
+ Likewise, =~ works for identity and !~ for negative identity on expressions:
345
332
 
346
333
  where{column =~ nil} # ("column" IS NULL)
347
334
  where{column !~ nil} # ("column" IS NOT NULL)
@@ -354,7 +341,7 @@ Sequel's general inversion operator is ~, which works on symbols and most Sequel
354
341
 
355
342
  Note that ~ will actually apply the inversion operation to the underlying object, which is why
356
343
 
357
- Sequel.~(:column=>1)
344
+ Sequel.~(column: 1)
358
345
 
359
346
  produces <tt>(column != 1)</tt> instead of <tt>NOT (column = 1)</tt>.
360
347
 
@@ -367,7 +354,7 @@ Sequel defines the inequality operators directly on most Sequel-specific express
367
354
  Sequel.function(:func) >= 1 # (func() >= 1)
368
355
  Sequel.function(:func, :column) <= 1 # (func("column") <= 1)
369
356
 
370
- If you want to use them on a symbol, you should call <tt>Sequel.[]</tt> with the symbol:
357
+ If you want to use them on a symbol, you should call <tt>Sequel.[]</tt> with the symbol to get an expression object:
371
358
 
372
359
  Sequel[:column] > 1 # ("column" > 1)
373
360
 
@@ -403,7 +390,7 @@ Note that since Sequel implements support for Ruby's coercion protocol, the foll
403
390
  Sequel defines the & and | methods on most Sequel-specific expression objects to handle AND and OR:
404
391
 
405
392
  Sequel[:column1] & :column2 # ("column1" AND "column2")
406
- Sequel[:column1=>1] | {:column2=>2} # (("column1" = 1) OR ("column2" = 2))
393
+ Sequel[{column1: 1}] | {column2: 2} # (("column1" = 1) OR ("column2" = 2))
407
394
  (Sequel.function(:func) > 1) & :column3 # ((func() > 1) AND "column3")
408
395
 
409
396
  Note the use of parentheses in the last statement. If you omit them, you won't get what you expect.
@@ -418,28 +405,28 @@ is parsed as:
418
405
  You can also use the <tt>Sequel.&</tt> and <tt>Sequel.|</tt> methods:
419
406
 
420
407
  Sequel.&(:column1, :column2) # ("column1" AND "column2")
421
- Sequel.|({:column1=>1}, {:column2=>2}) # (("column1" = 1) OR ("column2" = 2))
408
+ Sequel.|({column1: 1}, {column2: 2}) # (("column1" = 1) OR ("column2" = 2))
422
409
 
423
410
  You can use hashes and arrays of two element arrays to specify AND and OR with equality conditions:
424
411
 
425
- {:column1=>1, :column2=>2} # (("column1" = 1) AND ("column2" = 2))
412
+ {column1: 1, column2: 2} # (("column1" = 1) AND ("column2" = 2))
426
413
  [[:column1, 1], [:column2, 2]] # (("column1" = 1) AND ("column2" = 2))
427
414
 
428
415
  As you can see, these literalize with ANDs by default. You can use the <tt>Sequel.or</tt> method to use OR instead:
429
416
 
430
- Sequel.or(:column1=>1, :column2=>2) # (("column1" = 1) OR ("column2" = 2))
417
+ Sequel.or(column1: 1, column2: 2) # (("column1" = 1) OR ("column2" = 2))
431
418
 
432
419
  You've already seen the <tt>Sequel.negate</tt> method, which will use ANDs if multiple entries are used:
433
420
 
434
- Sequel.negate(:column1=>1, :column2=>2) # (("column1" != 1) AND ("column2" != 2))
421
+ Sequel.negate(column1: 1, column2: 2) # (("column1" != 1) AND ("column2" != 2))
435
422
 
436
423
  To negate while using ORs, the <tt>Sequel.~</tt> operator can be used:
437
424
 
438
- Sequel.~(:column1=>1, :column2=>2) # (("column1" != 1) OR ("column2" != 2))
425
+ Sequel.~(column1: 1, column2: 2) # (("column1" != 1) OR ("column2" != 2))
439
426
 
440
427
  Note again that <tt>Dataset#exclude</tt> uses ~, not +negate+:
441
428
 
442
- DB[:albums].exclude(:column1=>1, :column2=>2) # SELECT * FROM "albums" WHERE (("column" != 1) OR ("column2" != 2))
429
+ DB[:albums].exclude(column1: 1, column2: 2) # SELECT * FROM "albums" WHERE (("column" != 1) OR ("column2" != 2))
443
430
 
444
431
  === Casts
445
432
 
@@ -521,8 +508,8 @@ Sequel also supports SQL regular expressions on MySQL and PostgreSQL. You can u
521
508
 
522
509
  Sequel.like(:name, /^A/) # ("name" ~ '^A')
523
510
  ~Sequel.ilike(:name, /^A/) # ("name" !~* '^A')
524
- {:name=>/^A/i} # ("name" ~* '^A')
525
- Sequel.~(:name=>/^A/) # ("name" !~ '^A')
511
+ {name: /^A/i} # ("name" ~* '^A')
512
+ Sequel.~(name: /^A/) # ("name" !~ '^A')
526
513
 
527
514
  Note that using +ilike+ with a regular expression will always make the regexp case insensitive. If you use +like+ or the hash with regexp value, it will only be case insensitive if the Regexp itself is case insensitive.
528
515
 
@@ -545,21 +532,22 @@ On some databases, you can specify null ordering:
545
532
 
546
533
  === All Columns (.*)
547
534
 
548
- To select all columns in a table, Sequel supports the * method on identifiers without an argument:
535
+ To select all columns in a table, Sequel supports the * method on identifiers and qualified without an argument:
549
536
 
550
- Sequel[:table].* # "table".*
537
+ Sequel[:table].* # "table".*
538
+ Sequel[:schema][:table].* # "schema"."table".*
551
539
 
552
540
  === CASE statements
553
541
 
554
- Sequel allows the easy production of SQL CASE statements using the <tt>Sequel.case</tt> method. The first argument is a hash or array of two element arrays representing the conditions, the second argument is the default value (ELSE). The keys of the hash (or first element in each array) is the WHEN condition, and the values of the hash (or second element in each array) is the THEN result. Here are some examples:
542
+ Sequel supports SQL CASE statements using the <tt>Sequel.case</tt> method. The first argument is a hash or array of two element arrays representing the conditions, the second argument is the default value (ELSE). The keys of the hash (or first element in each array) is the WHEN condition, and the values of the hash (or second element in each array) is the THEN result. Here are some examples:
555
543
 
556
- Sequel.case({:column=>1}, 0) # (CASE WHEN "column" THEN 1 ELSE 0 END)
557
- Sequel.case([[column, 1]], 0) # (CASE WHEN "column" THEN 1 ELSE 0 END)
558
- Sequel.case({{:column=>nil}=>1}, 0) # (CASE WHEN (column IS NULL) THEN 1 ELSE 0 END)
544
+ Sequel.case({column: 1}, 0) # (CASE WHEN "column" THEN 1 ELSE 0 END)
545
+ Sequel.case([[:column, 1]], 0) # (CASE WHEN "column" THEN 1 ELSE 0 END)
546
+ Sequel.case({{column: nil}=>1}, 0) # (CASE WHEN (column IS NULL) THEN 1 ELSE 0 END)
559
547
 
560
548
  If the hash or array has multiple arguments, multiple WHEN clauses are used:
561
549
 
562
- Sequel.case({:c=>1, :d=>2}, 0) # (CASE WHEN "c" THEN 1 WHEN "d" THEN 2 ELSE 0 END)
550
+ Sequel.case({c: 1, d: 2}, 0) # (CASE WHEN "c" THEN 1 WHEN "d" THEN 2 ELSE 0 END)
563
551
  Sequel.case([[:c, 1], [:d, 2]], 0) # (CASE WHEN "c" THEN 1 WHEN "d" THEN 2 ELSE 0 END)
564
552
 
565
553
  If you provide a 3rd argument to <tt>Sequel.case</tt>, it goes between CASE and WHEN:
@@ -156,13 +156,11 @@ SEQUEL_COLUMNS_INTROSPECTION :: Use the columns_introspection extension when run
156
156
  SEQUEL_CONNECTION_VALIDATOR :: Use the connection validator extension when running the specs
157
157
  SEQUEL_DUPLICATE_COLUMNS_HANDLER :: Use the duplicate columns handler extension with value given when running the specs
158
158
  SEQUEL_ERROR_SQL :: Use the error_sql extension when running the specs
159
- SEQUEL_FREEZE_DATASETS :: Use the freeze_datasets extension when running the specs
160
159
  SEQUEL_FREEZE_DATABASE :: Freeze the database before running the integration specs
161
160
  SEQUEL_IDENTIFIER_MANGLING :: Use the identifier_mangling extension when running the specs
162
- SEQUEL_MODEL_PREPARED_STATEMENTS :: Use the prepared_statements and prepared_statements_associations plugins when running the specs
163
- SEQUEL_NO_AUTO_LITERAL_STRINGS :: Use the no_auto_string_literals extension when running the specs
161
+ SEQUEL_MODEL_PREPARED_STATEMENTS :: Use the prepared_statements plugin when running the specs
164
162
  SEQUEL_NO_CACHE_ASSOCIATIONS :: Don't cache association metadata when running the specs
165
163
  SEQUEL_NO_CHECK_SQLS :: Don't check for specific SQL syntax when running the specs
164
+ SEQUEL_CHECK_PENDING :: Try running all specs (note, can cause lockups for some adapters), and raise errors for skipped specs that don't fail
166
165
  SEQUEL_NO_PENDING :: Don't skip any specs, try running all specs (note, can cause lockups for some adapters)
167
- SEQUEL_NO_SPLIT_SYMBOLS :: Turn off symbol splitting when running the specs
168
- SKIPPED_TEST_WARN :: Warn when skipping any tests because libraries aren't available
166
+ SEQUEL_SPLIT_SYMBOLS :: Turn on symbol splitting when running the adapter and integration specs
@@ -1,10 +1,10 @@
1
1
  = Thread Safety
2
2
 
3
- Most Sequel usage (and all common Sequel usage) is thread safe by default. Specifically, multiple threads can operate on Database instances, Dataset instances, and Model classes concurrently without problems. In general, Database instance and Model classes are not modified after application startup, and modifying Dataset instances returns modified copies of the dataset instead of mutating it.
3
+ Most Sequel usage (and all common Sequel usage) is thread safe by default. Specifically, multiple threads can operate on Database instances, Dataset instances, and Model classes concurrently without problems. In general, Database instance and Model classes are not modified after application startup, and Dataset instances are always frozen.
4
4
 
5
5
  == Connection Pool
6
6
 
7
- In order to allow multiple threads to operate on the same database at the same time, Sequel uses a connection pool. The connection pool is designed so that a thread uses a connection for the minimum amount of time, returning the connection to the pool as soon as it is done using the connection. If a thread requests a connection and the pool does not have an available connection, a new connection will be created. If the maximum number of connections in the pool has already been reached, the thread will block until a connection is available or the connection pool timeout has elapsed (in which case a PoolTimeout error will be raised).
7
+ In order to allow multiple threads to operate on the same database at the same time, Sequel uses a connection pool. The connection pool is designed so that a thread uses a connection for the minimum amount of time, returning the connection to the pool as soon as it is done using the connection. If a thread requests a connection and the pool does not have an available connection, a new connection will be created. If the maximum number of connections in the pool has already been reached, the thread will block until a connection is available or the connection pool timeout has elapsed (in which case a Sequel::PoolTimeout error will be raised).
8
8
 
9
9
  == Exceptions
10
10
 
@@ -13,5 +13,3 @@ This is a small list of things that are specifically non thread-safe. This is n
13
13
  1) Model instances: Model instances are not thread-safe unless they are frozen first. Multiple threads should not operate on an unfrozen model instance concurrently.
14
14
 
15
15
  2) Model class modifications: Model class modifications, such as adding associations and loading plugins, are not designed to be thread safe. You should not modify a class in one thread if any other thread can concurrently access it. Model subclassing is designed to be thread-safe, so you create a model subclass in a thread and modify it safely.
16
-
17
- 3) Dataset mutation methods: Dataset mutation methods are not thread safe, you should not call them on datasets that could be accessed by other threads. It is safe to clone the dataset first inside a thread and call mutation methods on the cloned dataset.
@@ -3,6 +3,7 @@
3
3
  Sequel uses autocommit mode by default for all of its database adapters, so in general in Sequel if you want to use database transactions, you need to be explicit about it. There are a few cases where transactions are used implicitly by default:
4
4
 
5
5
  * Dataset#import to insert many records at once
6
+ * Dataset#paged_each to iterate over large datasets in batches
6
7
  * Model#save
7
8
  * Model#destroy
8
9
  * Migrations if the database supports transactional schema
@@ -35,16 +36,16 @@ If any other exception is raised, the transaction is rolled back, and the except
35
36
  end # ROLLBACK
36
37
  # ArgumentError raised
37
38
 
38
- If you want Sequel::Rollback exceptions to be reraised, use the <tt>:rollback => :reraise</tt> option:
39
+ If you want Sequel::Rollback exceptions to be reraised, use the <tt>rollback: :reraise</tt> option:
39
40
 
40
- DB.transaction(:rollback => :reraise) do # BEGIN
41
+ DB.transaction(rollback: :reraise) do # BEGIN
41
42
  raise Sequel::Rollback
42
43
  end # ROLLBACK
43
44
  # Sequel::Rollback raised
44
45
 
45
- If you always want to rollback (useful for testing), use the <tt>:rollback => :always</tt> option:
46
+ If you always want to rollback (useful for testing), use the <tt>rollback: :always</tt> option:
46
47
 
47
- DB.transaction(:rollback => :always) do # BEGIN
48
+ DB.transaction(rollback: :always) do # BEGIN
48
49
  DB[:foo].insert(1) # INSERT
49
50
  end # ROLLBACK
50
51
  # no exception raised
@@ -86,17 +87,17 @@ You can nest calls to transaction, which by default just reuses the existing tra
86
87
  end
87
88
  end # COMMIT
88
89
 
89
- You can use the <tt>:savepoint => true</tt> option in the inner transaction to explicitly use a savepoint (if the database supports it):
90
+ You can use the <tt>savepoint: true</tt> option in the inner transaction to explicitly use a savepoint (if the database supports it):
90
91
 
91
92
  DB.transaction do # BEGIN
92
- DB.transaction(:savepoint => true) do # SAVEPOINT
93
+ DB.transaction(savepoint: true) do # SAVEPOINT
93
94
  DB[:foo].insert(1) # INSERT
94
95
  end # RELEASE SAVEPOINT
95
96
  end # COMMIT
96
97
 
97
- You can use the <tt>:auto_savepoint => true</tt> option in the outer transaction to explicitly use a savepoint in the inner transaction (if the database supports it):
98
+ You can use the <tt>auto_savepoint: true</tt> option in the outer transaction to explicitly use a savepoint in the inner transaction (if the database supports it):
98
99
 
99
- DB.transaction(:auto_savepoint => true) do # BEGIN
100
+ DB.transaction(auto_savepoint: true) do # BEGIN
100
101
  DB.transaction do # SAVEPOINT
101
102
  DB[:foo].insert(1) # INSERT
102
103
  end # RELEASE SAVEPOINT
@@ -105,7 +106,7 @@ You can use the <tt>:auto_savepoint => true</tt> option in the outer transaction
105
106
  If a Sequel::Rollback exception is raised inside the savepoint block, it will only rollback to the savepoint:
106
107
 
107
108
  DB.transaction do # BEGIN
108
- DB.transaction(:savepoint => true) do # SAVEPOINT
109
+ DB.transaction(savepoint: true) do # SAVEPOINT
109
110
  raise Sequel::Rollback
110
111
  end # ROLLBACK TO SAVEPOINT
111
112
  # no exception raised
@@ -114,7 +115,7 @@ If a Sequel::Rollback exception is raised inside the savepoint block, it will on
114
115
  Other exceptions, unless rescued inside the outer transaction block, will rollback the savepoint and the outer transactions, since they are reraised by the transaction code:
115
116
 
116
117
  DB.transaction do # BEGIN
117
- DB.transaction(:savepoint => true) do # SAVEPOINT
118
+ DB.transaction(savepoint: true) do # SAVEPOINT
118
119
  raise ArgumentError
119
120
  end # ROLLBACK TO SAVEPOINT
120
121
  end # ROLLBACK
@@ -126,7 +127,7 @@ Sequel supports database prepared transactions on PostgreSQL, MySQL, and H2. Wi
126
127
 
127
128
  To use prepared transactions in Sequel, you provide a string as the value of the :prepare option:
128
129
 
129
- DB.transaction(:prepare => 'foo') do # BEGIN
130
+ DB.transaction(prepare: 'foo') do # BEGIN
130
131
  DB[:foo].insert(1) # INSERT
131
132
  end # PREPARE TRANSACTION 'foo'
132
133
 
@@ -140,9 +141,9 @@ or roll the prepared transaction back:
140
141
 
141
142
  == Transaction Isolation Levels
142
143
 
143
- The SQL standard supports 4 isolation levels: READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, and SERIALIZABLE. Not all databases implement the levels as specified in the standard (or implement the levels at all), but on most databases, you can specify which transaction isolation level you want to use via the :isolation option to <tt>Database#transaction</tt>. The isolation level is specified as one of the following symbols: :uncommitted, :committed, :repeatable, and :serializable. Using this option make Sequel use the correct transaction isolation syntax for your database:
144
+ The SQL standard supports 4 isolation levels: READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, and SERIALIZABLE. Not all databases implement the levels as specified in the standard (or implement the levels at all), but on most databases, you can specify which transaction isolation level you want to use via the :isolation option to <tt>Database#transaction</tt>. The isolation level is specified as one of the following symbols: :uncommitted, :committed, :repeatable, and :serializable. Using this option makes Sequel use the correct transaction isolation syntax for your database:
144
145
 
145
- DB.transaction(:isolation => :serializable) do # BEGIN
146
+ DB.transaction(isolation: :serializable) do # BEGIN
146
147
  # SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
147
148
  DB[:foo].insert(1) # INSERT
148
149
  end # COMMIT
@@ -151,8 +152,8 @@ The SQL standard supports 4 isolation levels: READ UNCOMMITTED, READ COMMITTED,
151
152
 
152
153
  Sequel offers the ability to automatically restart transactions if specific types of errors are detected. For example, if you want to automatically restart a transaction if a serialization failure is detected:
153
154
 
154
- DB.transaction(:isolation => :serializable, :retry_on=>[Sequel::SerializationFailure]) do
155
- ModelClass.find_or_create(:name=>'Foo')
155
+ DB.transaction(isolation: :serializable, retry_on: [Sequel::SerializationFailure]) do
156
+ ModelClass.find_or_create(name: 'Foo')
156
157
  end
157
158
 
158
159
  At the serializable transaction isolation level, find_or_create may raises a Sequel::SerializationFailure exception if multiple threads simultaneously run that code. With the :retry_on option set, the transaction will be automatically retried until it succeeds.
@@ -161,9 +162,9 @@ Note that automatic retrying should not be used unless the entire transaction
161
162
  block is idempotent, as otherwise it can cause non-idempotent
162
163
  behavior to execute multiple times. For example, with the following code:
163
164
 
164
- DB.transaction(:isolation => :serializable, :retry_on=>[Sequel::SerializationFailure]) do
165
+ DB.transaction(isolation: :serializable, retry_on: [Sequel::SerializationFailure]) do
165
166
  logger.info 'Ensuring existence of ModelClass with name Foo'
166
- ModelClass.find_or_create(:name=>'Foo')
167
+ ModelClass.find_or_create(name: 'Foo')
167
168
  end
168
169
 
169
170
  The logger.info method will be called multiple times if there is a serialization failure.
@@ -13,7 +13,7 @@ types of validations to your models.
13
13
 
14
14
  Validations are primarily useful for associating error messages to display to the user
15
15
  with specific attributes on the model. It is also possible to use them to enforce
16
- data integrity for model instances, but that's not a recommended use unless
16
+ data integrity for model instances, but that's not recommended unless
17
17
  the only way to modify the database is through model instances, or you have
18
18
  complex data integrity requirements that aren't possible to specify via
19
19
  database-level constraints.
@@ -30,19 +30,17 @@ be setting the size of the varchar column to 255, and using a CHECK constraint
30
30
  to ensure that all values have at least two characters.
31
31
 
32
32
  Unfortunately, sometimes there are situations where that is not possible. For
33
- example, if you are using MySQL and don't have control over the database configuration,
34
- it's possible that if you attempt to insert a string with 300 characters into a
35
- varchar(255) field, then MySQL may just silently truncate it for you, instead of
36
- raising an error. In that case, it may be necessary to use a model validation
33
+ example, if you don't have control over the schema and cannot add constraints,
34
+ or you are using MySQL (which doesn't support CHECK constraints), it may be necessary to use a model validation
37
35
  to enforce the database integrity.
38
36
 
39
- Also, in some cases you may have data integrity requirements that are difficult to
37
+ In some cases you may have data integrity requirements that are difficult to
40
38
  enforce via database constraints, especially if you are targetting multiple
41
39
  database types.
42
40
 
43
- Finally, validations are generally easier to write than database constraints,
41
+ Validations are generally easier to write than database constraints,
44
42
  so if data integrity isn't of great importance, using validations to provide minimal
45
- data integrity is probably fine.
43
+ data integrity may be acceptable.
46
44
 
47
45
  == Usage
48
46
 
@@ -71,11 +69,12 @@ saving of model objects passes through the +save+ method. This means that all
71
69
  saving of model objects goes through the validation process.
72
70
 
73
71
  The only way to skip validations when saving a model object is to pass the
74
- <tt>:validate => false</tt> option to +save+. If you use that option, +save+ will
72
+ <tt>validate: false</tt> option to +save+. If you use that option, +save+ will
75
73
  not attempt to validate the object before saving it.
76
74
 
77
75
  Note that it's always possible to update the instance's database row without using
78
- +save+, by using a dataset to update it. Validations will only be run if you call
76
+ +save+, by using a Sequel dataset to update it, or updating it via another program.
77
+ Validations will only be run if you call
79
78
  +save+ on the model object, or another model method that calls +save+. For example,
80
79
  the +create+ class method instantiates a new instance of the model, and then calls
81
80
  +save+, so it validates the object. However, the +insert+ class method is a dataset
@@ -96,8 +95,8 @@ model instance is valid. This method should not be overridden. Instead, the
96
95
  end
97
96
 
98
97
  Album.new.valid? # false
99
- Album.new(:name=>'').valid? # false
100
- Album.new(:name=>'RF').valid? # true
98
+ Album.new(name: '').valid? # false
99
+ Album.new(name: 'RF').valid? # true
101
100
 
102
101
  If the <tt>valid?</tt> method returns false, you can call the +errors+ method to
103
102
  get an instance of <tt>Sequel::Model::Errors</tt> describing the errors on the model:
@@ -135,7 +134,7 @@ specifying validations like this:
135
134
  def validate
136
135
  super
137
136
  errors.add(:name, 'cannot be empty') if !name || name.empty?
138
- errors.add(:name, 'is already taken') if name && new? && Album[:name=>name]
137
+ errors.add(:name, 'is already taken') if name && new? && Album[{name: name}]
139
138
  errors.add(:website, 'cannot be empty') if !website || website.empty?
140
139
  errors.add(:website, 'is not a valid URL') unless website =~ /\Ahttps?:\/\//
141
140
  end
@@ -149,7 +148,7 @@ You can call simple methods such as:
149
148
  super
150
149
  validates_presence [:name, :website]
151
150
  validates_unique :name
152
- validates_format /\Ahttps?:\/\//, :website, :message=>'is not a valid URL'
151
+ validates_format /\Ahttps?:\/\//, :website, message: 'is not a valid URL'
153
152
  end
154
153
  end
155
154
 
@@ -168,7 +167,7 @@ The following methods are provided by +validation_helpers+:
168
167
 
169
168
  === +validates_presence+
170
169
 
171
- This is probably the most commonly used helper method, which checks if the specified attributes are not blank. In general, if an object responds to <tt>blank?</tt>, it calls the method to determine if the object is blank. Otherwise, nil is considered blank, empty strings or strings that just contain whitespace are blank, and objects that respond to <tt>empty?</tt> and return true are considered blank. All other objects are considered non-blank for the purposes of +validates_presence+. This means that +validates_presence+ is safe to use on boolean columns where you want to ensure that either true or false is used, but not NULL.
170
+ This method checks that the specified attributes are not blank. In general, if an object responds to <tt>blank?</tt>, it calls the method to determine if the object is blank. Otherwise, nil is considered blank, empty strings or strings that just contain whitespace are blank, and objects that respond to <tt>empty?</tt> and return true are considered blank. All other objects are considered non-blank for the purposes of +validates_presence+. This means that +validates_presence+ is safe to use on boolean columns where you want to ensure that either true or false is used, but not NULL.
172
171
 
173
172
  class Album < Sequel::Model
174
173
  def validate
@@ -195,7 +194,7 @@ This is similar to +validates_presence+, but only checks for NULL/nil values, al
195
194
 
196
195
  === +validates_exact_length+, +validates_min_length+, +validates_max_length+, +validates_length_range+
197
196
 
198
- These methods all deal with ensuring that the length of the specified attribute matches the criteria specified by the first argument to the method. +validates_exact_length+ is for checking that the length of the attribute is equal to that value, +validates_min_length+ is for checking that the length of the attribute is greater than or equal to that value, +validates_max_length+ is for checking that the length of the attribute is less than or equal to that value, and +validates_length_range+ is for checking that the length of the attribute falls in the value, which should be a range or another object that responds to <tt>include?</tt>.
197
+ These methods all deal with ensuring that the length of the specified attribute matches the criteria specified by the first argument to the method. +validates_exact_length+ is for checking that the length of the attribute is equal to that value, +validates_min_length+ is for checking that the length of the attribute is greater than or equal to that value, +validates_max_length+ is for checking that the length of the attribute is less than or equal to that value, and +validates_length_range+ is for checking that the length of the attribute falls in the value, which should be a range or an object that responds to <tt>include?</tt>.
199
198
 
200
199
 
201
200
  class Album < Sequel::Model
@@ -257,17 +256,17 @@ These methods check that the specified attributes can be valid integers or valid
257
256
 
258
257
  === +validates_schema_types+
259
258
 
260
- +validates_schema_types+ uses the database metadata for the model's table to determine which ruby type(s) should be used for the given database type, and calls +validates_type+ with that ruby type. It's designed to be used with the <tt>raise_on_typecast_failure = false</tt> setting (the default starting in Sequel 4). <tt>raise_on_typecast_failure = false</tt>, Sequel attempts to typecast values, but silently ignores any errors raised:
259
+ +validates_schema_types+ uses the database metadata for the model's table to determine which ruby type(s) should be used for the given database type, and calls +validates_type+ with that ruby type. It's designed to be used with the default <tt>raise_on_typecast_failure = false</tt> setting, where Sequel will attempt to typecast values, but silently ignore any errors raised:
261
260
 
262
- Album.raise_on_typecast_failure = false
263
261
  album = Album.new
262
+ album.copies_sold = '1'
263
+ album.copies_sold # => 1
264
264
  album.copies_sold = 'banana'
265
265
  album.copies_sold # => 'banana'
266
266
 
267
- When <tt>raise_on_typecast_failure = false</tt>, you can call +validates_schema_types+ with all columns. If any of those columns has a value that doesn't match the type that Sequel expects, it's probably because the column was set and Sequel was not able to typecast it correctly, which means it probably isn't valid. For example, let's say that you want to check that a couple of columns contain valid dates:
267
+ In general, you can call +validates_schema_types+ with all columns. If any of those columns has a value that doesn't match the type that Sequel expects, it's probably because the column was set and Sequel was not able to typecast it correctly, which means it probably isn't valid. For example, let's say that you want to check that a couple of columns contain valid dates:
268
268
 
269
269
  class Album < Sequel::Model
270
- self.raise_on_typecast_failure = false
271
270
  def validate
272
271
  super
273
272
  validates_schema_types [:release_date, :record_date]
@@ -282,7 +281,7 @@ When <tt>raise_on_typecast_failure = false</tt>, you can call +validates_schema_
282
281
  album.valid? # => false
283
282
  album.errors # => {:release_date=>["is not a valid date"]}
284
283
 
285
- For web applications, you usually want the <tt>raise_on_typecast_failure = false</tt> setting, so that you can accept all of the input without raising an error, and then present the user with all error messages. Without the setting, if the user submits any invalid data, Sequel will immediately raise an error. +validates_schema_types+ is helpful because it allows you to check for typecasting errors on columns, and provides a good default error message stating that the attribute is not of the expected type.
284
+ For web applications, you usually want the default setting, so that you can accept all of the input without raising an error, and then present the user with all error messages. If <tt>raise_on_typecast_failure = true</tt> is set and the user submits any invalid data, Sequel will immediately raise an error. +validates_schema_types+ is helpful because it allows you to check for typecasting errors on columns, and provides a good default error message stating that the attribute is not of the expected type.
286
285
 
287
286
  === +validates_unique+
288
287
 
@@ -310,7 +309,7 @@ You can also include an options hash as the last argument. Unlike the other val
310
309
 
311
310
  :dataset :: The base dataset to use for the unique query, defaults to the model's dataset
312
311
  :message :: The message to use
313
- :only_if_modified :: Only check the uniqueness if the object is new or one of the columns has been modified.
312
+ :only_if_modified :: Only check the uniqueness if the object is new or one of the columns has been modified (true by default).
314
313
  :where :: A callable object where call takes three arguments, a dataset,
315
314
  the current object, and an array of columns, and should return
316
315
  a modified dataset that is filtered to include only rows with
@@ -323,17 +322,17 @@ You can also include an options hash as the last argument. Unlike the other val
323
322
 
324
323
  == +validation_helpers+ Options
325
324
 
326
- All +validation_helpers+ methods except +validates_unique+ accept the following options:
325
+ All other +validation_helpers+ methods accept the following options:
327
326
 
328
327
  === <tt>:message</tt>
329
328
 
330
- The most commonly used option, used to override the default validation message. Can be either a string or a proc. If a string, it is used directly. If a proc, the proc is called and should return a string. If the validation method takes an argument before the array of attributes, that argument is passed as an argument to the proc. The exception is the +validates_not_string+ method, which doesn't take an argument, but passes the schema type symbol as the argument to the proc.
329
+ The <tt>:message</tt> option overrides the default validation error message. Can be either a string or a proc. If a string, it is used directly. If a proc, the proc is called and should return a string. If the validation method takes an argument before the array of attributes, that argument is passed as an argument to the proc.
331
330
 
332
331
  class Album < Sequel::Model
333
332
  def validate
334
333
  super
335
- validates_presence :copies_sold, :message=>'was not given'
336
- validates_min_length 3, :name, :message=>proc{|s| "should be more than #{s} characters"}
334
+ validates_presence :copies_sold, message: 'was not given'
335
+ validates_min_length 3, :name, message: lambda{|s| "should be more than #{s} characters"}
337
336
  end
338
337
  end
339
338
 
@@ -345,7 +344,7 @@ The <tt>:allow_nil</tt> option skips the validation if the attribute value is ni
345
344
  def validate
346
345
  super
347
346
  validates_presence :copies_sold
348
- validates_integer :copies_sold, :allow_nil=>true
347
+ validates_integer :copies_sold, allow_nil: true
349
348
  end
350
349
  end
351
350
 
@@ -358,17 +357,13 @@ The <tt>:allow_blank</tt> is similar to the <tt>:allow_nil</tt> option, but inst
358
357
  class Album < Sequel::Model
359
358
  def validate
360
359
  super
361
- validates_format /\Ahttps?:\/\//, :website, :allow_blank=>true
360
+ validates_format /\Ahttps?:\/\//, :website, allow_blank: true
362
361
  end
363
362
  end
364
363
  a = Album.new
365
364
  a.website = ''
366
365
  a.valid? # true
367
366
 
368
- If you are going to use <tt>:allow_blank</tt> you should make sure that all objects respond to the blank? method. Sequel ships with an extension that will do this for you:
369
-
370
- Sequel.extension :blank
371
-
372
367
  === <tt>:allow_missing</tt>
373
368
 
374
369
  The <tt>:allow_missing</tt> option is different from the <tt>:allow_nil</tt> option, in that instead of checking if the attribute value is nil, it checks if the attribute is present in the model instance's values hash. <tt>:allow_nil</tt> will skip the validation when the attribute is in the values hash and has a nil value and when the attribute is not in the values hash. <tt>:allow_missing</tt> will only skip the validation when the attribute is not in the values hash. If the attribute is in the values hash but has a nil value, <tt>:allow_missing</tt> will not skip it.
@@ -428,17 +423,26 @@ These are the default error messages for all of the helper methods in +validatio
428
423
 
429
424
  == Modifying the Default Options
430
425
 
431
- It's easy to modify the default options used by +validation_helpers+. All of the default options are stored in the <tt>Sequel::Plugins::ValidationHelpers::DEFAULT_OPTIONS</tt> hash. So you just need to modify that hash to change the default options. One way to do that is to use <tt>merge!</tt> to update the hash:
432
-
433
- Sequel::Plugins::ValidationHelpers::DEFAULT_OPTIONS.merge!(
434
- :presence=>{:message=>'cannot be empty'},
435
- :includes=>{:message=>'invalid option', :allow_nil=>true},
436
- :max_length=>{:message=>lambda{|i| "cannot be more than #{i} characters"}, :allow_nil=>true},
437
- :format=>{:message=>'contains invalid characters', :allow_nil=>true})
438
-
439
- This updates the default messages that will be used for the presence, includes, max_length, and format validations, and sets the default value of the <tt>:allow_nil</tt> option to true for the includes, max_length, and format validations.
426
+ You can override <tt>Sequel::Model#default_validation_helpers_options</tt> private method to override the default settings on a per validation type basis:
440
427
 
441
- You can also override <tt>Sequel::Model#default_validation_helpers_options</tt> private method to override these settings on a per-model or even per-instance basis.
428
+ class Sequel::Model
429
+ private
430
+
431
+ def default_validation_helpers_options(type)
432
+ case type
433
+ when :presence
434
+ {message: 'cannot be empty'}
435
+ when :includes
436
+ {message: 'invalid option', allow_nil: true}
437
+ when :max_length
438
+ {message: lambda{|i| "cannot be more than #{i} characters"}, allow_nil: true}
439
+ when :format
440
+ {message: 'contains invalid characters', allow_nil: true}
441
+ else
442
+ super
443
+ end
444
+ end
445
+ end
442
446
 
443
447
  == Custom Validations
444
448
 
@@ -480,7 +484,7 @@ Let's say you want to add some default validations that apply to all of your mod
480
484
  super
481
485
  validates_format(/\A[^\x00-\x08\x0e-\x1f\x7f\x81\x8d\x8f\x90\x9d]*\z/n,
482
486
  model.string_columns,
483
- :message=>"contains invalid characters")
487
+ message: "contains invalid characters")
484
488
  end
485
489
  end
486
490
 
@@ -547,9 +551,8 @@ Sequel ships with a +constraint_validations+ plugin and extension, that allows y
547
551
 
548
552
  === +auto_validations+
549
553
 
550
- Autovalidations uses the not null and type information obtained from parsing the database schema, and the unique index information from parsing the database's index information, and automatically setting up not_null, schema_types, and unique validations. If you don't require customizing validation messages on a per-column basis, it can DRY up a lot of validation code.
554
+ auto_validations uses the not null and type information obtained from parsing the database schema, and the unique index information from parsing the database's index information, and automatically setting up not_null, string length, schema type, and unique validations. If you don't require customizing validation messages on a per-column basis, it can DRY up a lot of validation code.
551
555
 
552
556
  === +validation_class_methods+
553
557
 
554
558
  Sequel ships with the +validation_class_methods+ plugin, which uses class methods instead of instance methods to define validations. It exists mostly for legacy compatibility, but it is still supported.
555
-