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
data/Rakefile CHANGED
@@ -6,20 +6,15 @@ VERS = lambda do
6
6
  require File.expand_path("../lib/sequel/version", __FILE__)
7
7
  Sequel.version
8
8
  end
9
- CLEAN.include ["**/.*.sw?", "sequel-*.gem", ".config", "rdoc", "coverage", "www/public/*.html", "www/public/rdoc*", '**/*.rbc', "spec/bin-sequel-*"]
9
+ CLEAN.include ["sequel-*.gem", "rdoc", "coverage", "www/public/*.html", "www/public/rdoc*", "spec/bin-sequel-*"]
10
10
 
11
- # Gem Packaging and Release
11
+ # Gem Packaging
12
12
 
13
13
  desc "Build sequel gem"
14
14
  task :package=>[:clean] do |p|
15
15
  sh %{#{FileUtils::RUBY} -S gem build sequel.gemspec}
16
16
  end
17
17
 
18
- desc "Publish sequel gem to rubygems.org"
19
- task :release=>[:package] do
20
- sh %{#{FileUtils::RUBY} -S gem push ./#{NAME}-#{VERS.call}.gem}
21
- end
22
-
23
18
  ### Website
24
19
 
25
20
  desc "Make local version of website"
@@ -29,7 +24,7 @@ end
29
24
 
30
25
  ### RDoc
31
26
 
32
- RDOC_DEFAULT_OPTS = ["--line-numbers", "--inline-source", '--title', 'Sequel: The Database Toolkit for Ruby']
27
+ RDOC_DEFAULT_OPTS = ["--line-numbers", '--title', 'Sequel: The Database Toolkit for Ruby']
33
28
 
34
29
  begin
35
30
  # Sequel uses hanna-nouveau for the website RDoc.
@@ -38,46 +33,35 @@ begin
38
33
  rescue Gem::LoadError
39
34
  end
40
35
 
41
- rdoc_task_class = begin
42
- require "rdoc/task"
43
- RDoc::Task
44
- rescue LoadError
45
- begin
46
- require "rake/rdoctask"
47
- Rake::RDocTask
48
- rescue LoadError, StandardError
49
- end
50
- end
36
+ require "rdoc/task"
51
37
 
52
- if rdoc_task_class
53
- RDOC_OPTS = RDOC_DEFAULT_OPTS + ['--main', 'README.rdoc']
38
+ RDOC_OPTS = RDOC_DEFAULT_OPTS + ['--main', 'README.rdoc']
54
39
 
55
- rdoc_task_class.new do |rdoc|
56
- rdoc.rdoc_dir = "rdoc"
57
- rdoc.options += RDOC_OPTS
58
- rdoc.rdoc_files.add %w"README.rdoc CHANGELOG MIT-LICENSE lib/**/*.rb doc/*.rdoc doc/release_notes/*.txt"
59
- end
40
+ RDoc::Task.new do |rdoc|
41
+ rdoc.rdoc_dir = "rdoc"
42
+ rdoc.options += RDOC_OPTS
43
+ rdoc.rdoc_files.add %w"README.rdoc CHANGELOG MIT-LICENSE lib/**/*.rb doc/*.rdoc doc/release_notes/*.txt"
44
+ end
60
45
 
61
- desc "Make rdoc for website"
62
- task :website_rdoc=>[:website_rdoc_main, :website_rdoc_adapters, :website_rdoc_plugins]
46
+ desc "Make rdoc for website"
47
+ task :website_rdoc=>[:website_rdoc_main, :website_rdoc_adapters, :website_rdoc_plugins]
63
48
 
64
- rdoc_task_class.new(:website_rdoc_main) do |rdoc|
65
- rdoc.rdoc_dir = "www/public/rdoc"
66
- rdoc.options += RDOC_OPTS + %w'--no-ignore-invalid'
67
- rdoc.rdoc_files.add %w"README.rdoc CHANGELOG MIT-LICENSE lib/*.rb lib/sequel/*.rb lib/sequel/{connection_pool,dataset,database,model}/*.rb doc/*.rdoc doc/release_notes/*.txt lib/sequel/extensions/migration.rb"
68
- end
49
+ RDoc::Task.new(:website_rdoc_main) do |rdoc|
50
+ rdoc.rdoc_dir = "www/public/rdoc"
51
+ rdoc.options += RDOC_OPTS + %w'--no-ignore-invalid'
52
+ rdoc.rdoc_files.add %w"README.rdoc CHANGELOG MIT-LICENSE lib/*.rb lib/sequel/*.rb lib/sequel/{connection_pool,dataset,database,model}/*.rb doc/*.rdoc doc/release_notes/*.txt lib/sequel/extensions/migration.rb"
53
+ end
69
54
 
70
- rdoc_task_class.new(:website_rdoc_adapters) do |rdoc|
71
- rdoc.rdoc_dir = "www/public/rdoc-adapters"
72
- rdoc.options += RDOC_DEFAULT_OPTS + %w'--main Sequel --no-ignore-invalid'
73
- rdoc.rdoc_files.add %w"lib/sequel/adapters/**/*.rb"
74
- end
55
+ RDoc::Task.new(:website_rdoc_adapters) do |rdoc|
56
+ rdoc.rdoc_dir = "www/public/rdoc-adapters"
57
+ rdoc.options += RDOC_DEFAULT_OPTS + %w'--main Sequel --no-ignore-invalid'
58
+ rdoc.rdoc_files.add %w"lib/sequel/adapters/**/*.rb"
59
+ end
75
60
 
76
- rdoc_task_class.new(:website_rdoc_plugins) do |rdoc|
77
- rdoc.rdoc_dir = "www/public/rdoc-plugins"
78
- rdoc.options += RDOC_DEFAULT_OPTS + %w'--main Sequel --no-ignore-invalid'
79
- rdoc.rdoc_files.add %w"lib/sequel/{extensions,plugins}/**/*.rb doc/core_*"
80
- end
61
+ RDoc::Task.new(:website_rdoc_plugins) do |rdoc|
62
+ rdoc.rdoc_dir = "www/public/rdoc-plugins"
63
+ rdoc.options += RDOC_DEFAULT_OPTS + %w'--main Sequel --no-ignore-invalid'
64
+ rdoc.rdoc_files.add %w"lib/sequel/{extensions,plugins}/**/*.rb doc/core_*"
81
65
  end
82
66
 
83
67
  ### Specs
data/bin/sequel CHANGED
@@ -1,7 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen-string-literal: true
3
3
 
4
- require 'rubygems'
5
4
  require 'optparse'
6
5
 
7
6
  code = nil
@@ -84,7 +83,7 @@ options = OptionParser.new do |opts|
84
83
  end
85
84
 
86
85
  opts.on("-M", "--migrate-version VER", "migrate the database to version given") do |v|
87
- migrate_ver = Integer(v)
86
+ migrate_ver = Integer(v, 10)
88
87
  end
89
88
 
90
89
  opts.on("-N", "--no-test-connection", "do not test the connection") do
@@ -133,12 +132,11 @@ connect_proc = lambda do |database|
133
132
  db_config = YAML.load_file(database)
134
133
  db_config = db_config[env] || db_config[env.to_sym] || db_config
135
134
  db_config.keys.each{|k| db_config[k.to_sym] = db_config.delete(k)}
136
- Sequel.connect(db_config)
135
+ Sequel.connect(db_config, :test=>test)
137
136
  else
138
- Sequel.connect(database)
137
+ Sequel.connect(database, :test=>test)
139
138
  end
140
139
  db.loggers = loggers
141
- db.test_connection if test
142
140
  db
143
141
  end
144
142
 
@@ -1,19 +1,22 @@
1
1
  = Advanced Associations
2
2
 
3
- Sequel::Model has the most powerful and flexible associations of any ruby ORM.
3
+ Sequel::Model's association support is very powerful and flexible, but using that power and flexibility
4
+ often results in complexity.
5
+
6
+ You should probably review the {Model Associations Basics and Options guide}[rdoc-ref:doc/association_basics.rdoc]
7
+ before reviewing this guide.
4
8
 
5
9
  == Background: Sequel::Model association options
6
10
 
7
11
  There are a bunch of advanced association options that are available to
8
- handle more complex cases. First we'll go over some of
9
- the simpler ones:
12
+ handle more complex cases. First we'll go over some of the simpler ones:
10
13
 
11
14
  All associations take a block that can be used to further filter/modify the
12
15
  default dataset. There's also an :eager_block option if you want to use
13
16
  a different block when eager loading via <tt>Dataset#eager</tt>. Association blocks are
14
17
  useful for things like:
15
18
 
16
- Artist.one_to_many :gold_albums, :class=>:Album do |ds|
19
+ Artist.one_to_many :gold_albums, class: :Album do |ds|
17
20
  ds.where{copies_sold > 500000}
18
21
  end
19
22
 
@@ -42,24 +45,23 @@ These can be used like this:
42
45
 
43
46
  # Makes Artist.eager_graph(:required_albums).all not return artists that
44
47
  # don't have any albums
45
- Artist.one_to_many :required_albums, :class=>:Album, :graph_join_type=>:inner
48
+ Artist.one_to_many :required_albums, class: :Album, graph_join_type: :inner
46
49
 
47
50
  # Makes sure all returned albums have the active flag set
48
- Artist.one_to_many :active_albums, :class=>:Album, \
49
- :graph_conditions=>{:active=>true}
51
+ Artist.one_to_many :active_albums, class: :Album, graph_conditions: {active: true}
50
52
 
51
53
  # Only returns albums that have sold more than 500,000 copies
52
- Artist.one_to_many :gold_albums, :class=>:Album, \
53
- :graph_block=>proc{|j,lj,js| Sequel[j][:copies_sold] > 500000}
54
+ Artist.one_to_many :gold_albums, class: :Album,
55
+ graph_block: proc{|j,lj,js| Sequel[j][:copies_sold] > 500000}
54
56
 
55
57
  # Handles the case where the tables are associated by a case insensitive name string
56
- Artist.one_to_many :albums, :key=>:artist_name, \
57
- :graph_only_conditions=>nil, \
58
- :graph_block=>proc{|j,lj,js| {Sequel.function(:lower, Sequel[j][:artist_name])=>Sequel.function(:lower, Sequel[lj][:name])}}
58
+ Artist.one_to_many :albums, key: :artist_name,
59
+ graph_only_conditions: nil,
60
+ graph_block: proc{|j,lj,js| {Sequel.function(:lower, Sequel[j][:artist_name])=>Sequel.function(:lower, Sequel[lj][:name])}}
59
61
 
60
62
  # Handles the case where both key columns have the name artist_name, and you want to use
61
63
  # a JOIN USING
62
- Artist.one_to_many :albums, :key=>:artist_name, :graph_only_conditions=>[:artist_name]
64
+ Artist.one_to_many :albums, key: :artist_name, graph_only_conditions: [:artist_name]
63
65
 
64
66
  Remember, using +eager_graph+ is generally only necessary when you need to
65
67
  filter/order based on columns in an associated table, it is recommended to
@@ -244,7 +246,7 @@ loading.
244
246
 
245
247
  Sequel supports specifying limits and/or offsets for associations:
246
248
 
247
- Artist.one_to_many :first_10_albums, :class=>:Album, :order=>:release_date, :limit=>10
249
+ Artist.one_to_many :first_10_albums, class: :Album, order: :release_date, limit: 10
248
250
 
249
251
  For retrieving the associated objects for a single object, this just uses
250
252
  a LIMIT:
@@ -260,7 +262,7 @@ approach. Sequel has 4 separate strategies for dealing with such cases.
260
262
  The default strategy used on all databases is a UNION-based approach, which
261
263
  will submit multiple subqueries in a UNION query:
262
264
 
263
- Artist.where(:id=>[1,2]).eager(:first_10_albums).all
265
+ Artist.where(id: [1,2]).eager(:first_10_albums).all
264
266
  # SELECT * FROM (SELECT * FROM albums WHERE (artist_id = 1) LIMIT 10) UNION ALL
265
267
  # SELECT * FROM (SELECT * FROM albums WHERE (artist_id = 2) LIMIT 10)
266
268
 
@@ -272,9 +274,9 @@ index, you'll want to manually specify the :eager_limit_strategy option as shown
272
274
  On PostgreSQL, for *_one associations that don't use an offset, you can
273
275
  choose to use a the distinct on strategy:
274
276
 
275
- Artist.one_to_one :first_album, :class=>:Album, :order=>:release_date,
276
- :eager_limit_strategy=>:distinct_on
277
- Artist.where(:id=>[1,2]).eager(:first_album).all
277
+ Artist.one_to_one :first_album, class: :Album, order: :release_date,
278
+ eager_limit_strategy: :distinct_on
279
+ Artist.where(id: [1,2]).eager(:first_album).all
278
280
  # SELECT DISTINCT ON (albums.artist_id) *
279
281
  # FROM albums
280
282
  # WHERE (albums.artist_id IN (1, 2))
@@ -283,8 +285,8 @@ choose to use a the distinct on strategy:
283
285
  Otherwise, if the database supports window functions, you can choose to use
284
286
  the window function strategy:
285
287
 
286
- Artist.one_to_many :first_10_albums, :class=>:Album, :order=>:release_date, :limit=>10,
287
- :eager_limit_strategy=>:window_function
288
+ Artist.one_to_many :first_10_albums, class: :Album, order: :release_date, limit: 10,
289
+ eager_limit_strategy: :window_function
288
290
  Artist.where(:id=>[1,2]).eager(:first_10_albums).all
289
291
  # SELECT * FROM (
290
292
  # SELECT *, row_number() OVER (PARTITION BY albums.artist_id ORDER BY release_date) AS x_sequel_row_number_x
@@ -304,7 +306,7 @@ known at the time of the association definition), Sequel supports an
304
306
  :eager_limit dataset option that can be defined in an eager loading callback:
305
307
 
306
308
  Artist.one_to_many :albums
307
- Artist.where(:id => [1, 2]).eager(:albums => proc{|ds| ds.order(:release_date).clone(:eager_limit => 3)}).all
309
+ Artist.where(id: [1, 2]).eager(albums: lambda{|ds| ds.order(:release_date).clone(eager_limit: 3)}).all
308
310
  # SELECT * FROM (
309
311
  # SELECT *, row_number() OVER (PARTITION BY albums.artist_id ORDER BY release_date) AS x_sequel_row_number_x
310
312
  # FROM albums
@@ -314,7 +316,7 @@ known at the time of the association definition), Sequel supports an
314
316
 
315
317
  You can also customize the :eager_limit_strategy on a case-by-case basis by passing in that option in the same way:
316
318
 
317
- Artist.where(:id => [1, 2]).eager(:albums => proc{|ds| ds.order(:release_date).clone(:eager_limit => 3, :eager_limit_strategy => :ruby)}).all
319
+ Artist.where(id: [1, 2]).eager(albums: lambda{|ds| ds.order(:release_date).clone(eager_limit: 3, eager_limit_strategy: :ruby)}).all
318
320
  # SELECT * FROM albums WHERE (albums.artist_id IN (1, 2)) ORDER BY release_date
319
321
 
320
322
  The :eager_limit and :eager_limit_strategy options currently only work when
@@ -333,7 +335,7 @@ eager_graph_with_options method with the :limit_strategy option.
333
335
  The :distinct_on strategy uses DISTINCT ON in a subquery and JOINs that
334
336
  subquery:
335
337
 
336
- Artist.eager_graph_with_options(:first_album, :limit_strategy=>true).all
338
+ Artist.eager_graph_with_options(:first_album, limit_strategy: :distinct_on).all
337
339
  # SELECT artists.id, artists.name, first_album.id AS first_album_id,
338
340
  # first_album.name AS first_album_name, first_album.artist_id,
339
341
  # first_album.release_date
@@ -347,7 +349,7 @@ subquery:
347
349
  The :window_function approach JOINs to a nested subquery using a window
348
350
  function:
349
351
 
350
- Artist.eager_graph_with_options(:first_10_albums, :limit_strategy=>true).all
352
+ Artist.eager_graph_with_options(:first_10_albums, limit_strategy: :window_function).all
351
353
  # SELECT artists.id, artists.name, first_10_albums.id AS first_10_albums_id,
352
354
  # first_10_albums.name AS first_10_albums_name, first_10_albums.artist_id,
353
355
  # first_10_albums.release_date
@@ -363,7 +365,7 @@ function:
363
365
  The :correlated_subquery approach JOINs to a nested subquery using a correlated
364
366
  subquery:
365
367
 
366
- Artist.eager_graph_with_options(:first_10_albums, :limit_strategy=>true).all
368
+ Artist.eager_graph_with_options(:first_10_albums, :limit_strategy=>:correlated_subquery).all
367
369
  # SELECT artists.id, artists.name, first_10_albums.id AS first_10_albums_id,
368
370
  # first_10_albums.name AS first_10_albums_name, first_10_albums.artist_id,
369
371
  # first_10_albums.release_date
@@ -380,8 +382,6 @@ subquery:
380
382
  # )
381
383
  # ) AS first_10_albums ON (first_10_albums.artist_id = artists.id)
382
384
 
383
- (SELECT * FROM tracks WHERE (tracks.id IN (SELECT t1.id FROM tracks AS t1 WHERE (t1.album_id = tracks.album_id) LIMIT 1)))
384
-
385
385
  The reason that Sequel does not automatically use the :distinct_on, :window function
386
386
  or :correlated_subquery strategy for eager_graph is that it can perform much worse than the
387
387
  default of just doing the array slicing in ruby. If you are only using eager_graph to
@@ -403,7 +403,7 @@ strategy based on the database you are using, and you can override it using the
403
403
 
404
404
  The :distinct_on strategy:
405
405
 
406
- Artist.where(:first_album=>Album[1]).all
406
+ Artist.where(first_album: Album[1]).all
407
407
  # SELECT *
408
408
  # FROM artists
409
409
  # WHERE (artists.id IN (
@@ -417,7 +417,7 @@ The :distinct_on strategy:
417
417
 
418
418
  The :window_function strategy:
419
419
 
420
- Artist.where(:first_10_albums=>Album[1]).all
420
+ Artist.where(first_10_albums: Album[1]).all
421
421
  # SELECT *
422
422
  # FROM artists
423
423
  # WHERE (artists.id IN (
@@ -433,7 +433,7 @@ The :window_function strategy:
433
433
 
434
434
  The :correlated_subquery strategy:
435
435
 
436
- Artist.where(:first_10_albums=>Album[1]).all
436
+ Artist.where(first_10_albums: Album[1]).all
437
437
  # SELECT *
438
438
  # FROM artists
439
439
  # WHERE (artists.id IN (
@@ -447,11 +447,11 @@ The :correlated_subquery strategy:
447
447
  # LIMIT 1
448
448
  # )) AND (albums.id = 1))))
449
449
 
450
- Note that filtering by limited associations does not work on MySQL, as does not support
450
+ Note that filtering by limited associations does not work on MySQL, as MySQL does not support
451
451
  any of the strategies. It's also not supported when using composite keys on databases
452
452
  that don't support window functions and don't support multiple columns in IN.
453
453
 
454
- == Additional Association Types
454
+ === Additional Association Types
455
455
 
456
456
  While the above examples for limited associations showed one_to_many and one_to_one associations,
457
457
  it's just because those are the simplest examples. Sequel supports all of the same features for
@@ -459,29 +459,7 @@ many_to_many and one_through_one associations that are enabled by default, as we
459
459
  many_through_many and one_through_many associations that are added by the many_through_many
460
460
  plugin.
461
461
 
462
- == ActiveRecord associations
463
-
464
- Sequel supports all of associations that ActiveRecord supports, though some
465
- require different approaches or custom <tt>:eager_loader</tt> options.
466
-
467
- === Association callbacks
468
-
469
- Sequel supports the same callbacks that ActiveRecord does for +one_to_many+ and
470
- +many_to_many+ associations: <tt>:before_add</tt>, <tt>:before_remove</tt>, <tt>:after_add</tt>, and
471
- <tt>:after_remove</tt>. For +many_to_one+ associations and +one_to_one+ associations, Sequel
472
- supports the <tt>:before_set</tt> and <tt>:after_set</tt> callbacks. On all associations,
473
- Sequel supports <tt>:after_load</tt>, which is called after the association has been
474
- loaded.
475
-
476
- Each of these options can be a symbol specifying an instance method
477
- that takes one argument (the associated object), or a proc that takes
478
- two arguments (the current object and the associated object), or an
479
- array of symbols and procs. For <tt>:after_load</tt> with a *_to_many association,
480
- the associated object argument is an array of associated objects.
481
-
482
- If any of the before callbacks return +false+, the adding/removing
483
- does not happen and it either raises a <tt>Sequel::HookFailed</tt> (the default), or
484
- returns false (if +raise_on_save_failure+ is false).
462
+ == More advanced association examples
485
463
 
486
464
  === Association extensions
487
465
 
@@ -504,36 +482,21 @@ the model object that created the association dataset via the dataset's
504
482
  end
505
483
  end
506
484
  class Author < Sequel::Model
507
- one_to_many :authorships, :extend=>FindOrCreate
508
- end
509
- Author.first.authorships_dataset.find_or_create(:name=>'Blah', :number=>10)
510
-
511
- === <tt>has_many :through</tt> associations
512
-
513
- +many_to_many+ handles the usual case of a <tt>has_many :through</tt> with a +belongs_to+ in
514
- the associated model. It doesn't break on the case where the join table is a
515
- model table, unlike ActiveRecord's +has_and_belongs_to_many+.
516
-
517
- ActiveRecord:
518
-
519
- class Author < ActiveRecord::Base
520
- has_many :authorships
521
- has_many :books, :through => :authorships
485
+ one_to_many :authorships, extend: FindOrCreate
522
486
  end
487
+ Author.first.authorships_dataset.find_or_create(name: 'Blah', number: 10)
523
488
 
524
- class Authorship < ActiveRecord::Base
525
- belongs_to :author
526
- belongs_to :book
527
- end
489
+ === many_to_many associations through model tables
528
490
 
529
- @author = Author.find :first
530
- @author.books
531
-
532
- Sequel::Model:
491
+ The many_to_many association can be used even when the join table is a table used for a
492
+ model. The only requirement is the join table has foreign keys to both the current
493
+ model and the associated model. Anytime there is a one_to_many association from model A to
494
+ model B, and model B has a many_to_one association to model C, you can use a many_to_many
495
+ association from model A to model C.
533
496
 
534
497
  class Author < Sequel::Model
535
498
  one_to_many :authorships
536
- many_to_many :books, :join_table=>:authorships
499
+ many_to_many :books, join_table: :authorships
537
500
  end
538
501
 
539
502
  class Authorship < Sequel::Model
@@ -544,33 +507,17 @@ Sequel::Model:
544
507
  @author = Author.first
545
508
  @author.books
546
509
 
547
- If you use an association other than +belongs_to+ in the associated model, such as a +has_many+,
548
- you still use a +many_to_many+ association, but you need to use some options:
549
-
550
- ActiveRecord:
551
-
552
- class Firm < ActiveRecord::Base
553
- has_many :clients
554
- has_many :invoices, :through => :clients
555
- end
510
+ === many_to_many for three-level associations
556
511
 
557
- class Client < ActiveRecord::Base
558
- belongs_to :firm
559
- has_many :invoices
560
- end
561
-
562
- class Invoice < ActiveRecord::Base
563
- belongs_to :client
564
- has_one :firm, :through => :client
565
- end
566
-
567
- Firm.find(:first).invoices
568
-
569
- Sequel::Model:
512
+ You can even use a many_to_many association between model A and model C if model A has a
513
+ one_to_many association to model B, and model B has a one_to_many association to model C.
514
+ You just need to use the appropriate :right_key and :right_primary_key options. And in
515
+ the reverse direction from model C to model A, you can use a one_through_one association
516
+ using the :left_key and :left_primary_key options.
570
517
 
571
518
  class Firm < Sequel::Model
572
519
  one_to_many :clients
573
- many_to_many :invoices, :join_table=>:clients, :right_key=>:id, :right_primary_key=>:client_id
520
+ many_to_many :invoices, join_table: :clients, right_key: :id, right_primary_key: :client_id
574
521
  end
575
522
 
576
523
  class Client < Sequel::Model
@@ -580,12 +527,13 @@ Sequel::Model:
580
527
 
581
528
  class Invoice < Sequel::Model
582
529
  many_to_one :client
583
- one_through_one :firm, :join_table=>:clients, :left_key=>:id, :left_primary_key=>:client_id, :right_key=>:firm_id
530
+ one_through_one :firm, join_table: :clients, left_key: :id, left_primary_key: :client_id
584
531
  end
585
532
 
586
533
  Firm.first.invoices
534
+ Invoice.first.firm
587
535
 
588
- To handle cases where there are multiple join tables, use the many_through_many
536
+ To handle cases where there are multiple join tables, you can use the many_through_many
589
537
  plugin that ships with Sequel.
590
538
 
591
539
  === Polymorphic Associations
@@ -602,38 +550,19 @@ you are stuck with an existing design that uses them.
602
550
  If you must use them, look for the sequel_polymorphic external plugin, as it makes using
603
551
  polymorphic associations in Sequel about as easy as it is in ActiveRecord. However,
604
552
  here's how they can be done using Sequel's custom associations (the sequel_polymorphic
605
- plugin is just a generic version of this code):
606
-
607
- ActiveRecord:
608
-
609
- class Asset < ActiveRecord::Base
610
- belongs_to :attachable, :polymorphic => true
611
- end
612
-
613
- class Post < ActiveRecord::Base
614
- has_many :assets, :as => :attachable
615
- end
616
-
617
- class Note < ActiveRecord::Base
618
- has_many :assets, :as => :attachable
619
- end
620
-
621
- @asset.attachable = @post
622
- @asset.attachable = @note
623
-
624
- Sequel::Model:
553
+ external plugin is just a generic version of this code):
625
554
 
626
555
  class Asset < Sequel::Model
627
- many_to_one :attachable, :reciprocal=>:assets,
628
- :setter=>(proc do |attachable|
556
+ many_to_one :attachable, reciprocal: :assets,
557
+ setter: (lambda do |attachable|
629
558
  self[:attachable_id] = (attachable.pk if attachable)
630
559
  self[:attachable_type] = (attachable.class.name if attachable)
631
560
  end),
632
- :dataset=>(proc do
561
+ dataset: (proc do
633
562
  klass = attachable_type.constantize
634
563
  klass.where(klass.primary_key=>attachable_id)
635
564
  end),
636
- :eager_loader=>(proc do |eo|
565
+ eager_loader: (lambda do |eo|
637
566
  id_map = {}
638
567
  eo[:rows].each do |asset|
639
568
  asset.associations[:attachable] = nil
@@ -651,24 +580,22 @@ Sequel::Model:
651
580
  end
652
581
 
653
582
  class Post < Sequel::Model
654
- one_to_many :assets, :key=>:attachable_id, :reciprocal=>:attachable, :conditions=>{:attachable_type=>'Post'},
655
- :adder=>proc{|asset| asset.update(:attachable_id=>pk, :attachable_type=>'Post')},
656
- :remover=>proc{|asset| asset.update(:attachable_id=>nil, :attachable_type=>nil)},
657
- :clearer=>proc{assets_dataset.update(:attachable_id=>nil, :attachable_type=>nil)}
583
+ one_to_many :assets, key: :attachable_id, reciprocal: :attachable, conditions: {attachable_type: 'Post'},
584
+ adder: lambda{|asset| asset.update(attachable_id: pk, attachable_type: 'Post')},
585
+ remover: lambda{|asset| asset.update(attachable_id: nil, attachable_type: nil)},
586
+ clearer: lambda{assets_dataset.update(attachable_id: nil, attachable_type: nil)}
658
587
  end
659
588
 
660
589
  class Note < Sequel::Model
661
- one_to_many :assets, :key=>:attachable_id, :reciprocal=>:attachable, :conditions=>{:attachable_type=>'Note'},
662
- :adder=>proc{|asset| asset.update(:attachable_id=>pk, :attachable_type=>'Note')},
663
- :remover=>proc{|asset| asset.update(:attachable_id=>nil, :attachable_type=>nil)},
664
- :clearer=>proc{assets_dataset.update(:attachable_id=>nil, :attachable_type=>nil)}
590
+ one_to_many :assets, key: :attachable_id, reciprocal: :attachable, conditions: {attachable_type: 'Note'},
591
+ adder: lambda{|asset| asset.update(attachable_id: pk, attachable_type: 'Note')},
592
+ remover: lambda{|asset| asset.update(attachable_id: nil, attachable_type: nil)},
593
+ clearer: lambda{assets_dataset.update(attachable_id: nil, attachable_type: nil)}
665
594
  end
666
595
 
667
596
  @asset.attachable = @post
668
597
  @asset.attachable = @note
669
598
 
670
- == Other advanced associations
671
-
672
599
  === Joining on multiple keys
673
600
 
674
601
  Let's say you have two tables that are associated with each other with multiple
@@ -680,10 +607,10 @@ associations:
680
607
  # associated favorite track
681
608
 
682
609
  class Track < Sequel::Model
683
- many_to_one :favorite_track, :key=>[:disc_number, :number, :album_id], :primary_key=>[:disc_number, :number, :album_id]
610
+ many_to_one :favorite_track, key: [:disc_number, :number, :album_id], primary_key: [:disc_number, :number, :album_id]
684
611
  end
685
612
  class FavoriteTrack < Sequel::Model
686
- one_to_one :tracks, :key=>[:disc_number, :number, :album_id], :primary_key=>[:disc_number, :number, :album_id]
613
+ one_to_one :tracks, key: [:disc_number, :number, :album_id], primary_key: [:disc_number, :number, :album_id]
687
614
  end
688
615
 
689
616
  === Tree - All Ancestors and Descendents
@@ -692,24 +619,24 @@ Let's say you want to store a tree relationship in your database, it's pretty
692
619
  simple:
693
620
 
694
621
  class Node < Sequel::Model
695
- many_to_one :parent, :class=>self
696
- one_to_many :children, :key=>:parent_id, :class=>self
622
+ many_to_one :parent, class: self
623
+ one_to_many :children, key: :parent_id, class: self
697
624
  end
698
625
 
699
626
  You can easily get a node's parent with node.parent, and a node's children with
700
627
  node.children. You can even eager load the relationship up to a certain depth:
701
628
 
702
629
  # Eager load three generations of generations of children for a given node
703
- Node.where(:id=>1).eager(:children=>{:children=>:children}).all.first
630
+ Node.where(id: 1).eager(children: {children: :children}).all.first
704
631
  # Load parents and grandparents for a group of nodes
705
- Node.where{id < 10}.eager(:parent=>:parent).all
632
+ Node.where{id < 10}.eager(parent: :parent).all
706
633
 
707
634
  What if you want to get all ancestors up to the root node, or all descendents,
708
635
  without knowing the depth of the tree?
709
636
 
710
637
  class Node < Sequel::Model
711
- many_to_one :ancestors, :class=>self,
712
- :eager_loader=>(proc do |eo|
638
+ many_to_one :ancestors, class: self,
639
+ eager_loader: (lambda do |eo|
713
640
  # Handle cases where the root node has the same parent_id as primary_key
714
641
  # and also when it is NULL
715
642
  non_root_nodes = eo[:rows].reject do |n|
@@ -727,13 +654,13 @@ without knowing the depth of the tree?
727
654
  non_root_nodes.each{|n| (id_map[n.parent_id] ||= []) << n}
728
655
  # Doesn't cause an infinte loop, because when only the root node
729
656
  # is left, this is not called.
730
- Node.where(Node.primary_key=>id_map.keys).eager(:ancestors).all do |node|
657
+ Node.where(id: id_map.keys).eager(:ancestors).all do |node|
731
658
  # Populate the parent association for each node
732
659
  id_map[node.pk].each{|n| n.associations[:parent] = node}
733
660
  end
734
661
  end
735
662
  end)
736
- many_to_one :descendants, :eager_loader=>(proc do |eo|
663
+ many_to_one :descendants, eager_loader: (lambda do |eo|
737
664
  id_map = {}
738
665
  eo[:rows].each do |n|
739
666
  # Initialize an empty array of child associations for each parent node
@@ -745,7 +672,7 @@ without knowing the depth of the tree?
745
672
  # if no records are returned. Exclude id = parent_id to avoid infinite loop
746
673
  # if the root note is one of the returned records and it has parent_id = id
747
674
  # instead of parent_id = NULL.
748
- Node.where(:parent_id=>id_map.keys).exclude(:id=>:parent_id).eager(:descendants).all do |node|
675
+ Node.where(parent_id: id_map.keys).exclude(id: :parent_id).eager(:descendants).all do |node|
749
676
  # Get the parent from the identity map
750
677
  parent = id_map[node.parent_id]
751
678
  # Set the child's parent association to the parent
@@ -756,11 +683,7 @@ without knowing the depth of the tree?
756
683
  end)
757
684
  end
758
685
 
759
- Note that unlike ActiveRecord, Sequel supports common table expressions, which allows you to use recursive queries.
760
- The results are not the same as in the above case, as all descendents are stored in a single association,
761
- but all descendants can be both lazy loaded or eager loaded in a single query (assuming your database
762
- supports recursive common table expressions). Sequel ships with an +rcte_tree+ plugin that makes
763
- this easy:
686
+ Note that Sequel ships with an rcte_tree plugin that does all of the above and more:
764
687
 
765
688
  class Node < Sequel::Model
766
689
  plugin :rcte_tree
@@ -780,15 +703,15 @@ What you want to do is get all songs for a given artist, ordered by the song's
780
703
  name, with no duplicates?
781
704
 
782
705
  class Artist < Sequel::Model
783
- one_to_many :songs, :order=>Sequel[:songs][:name], \
784
- :dataset=>proc{Song.select_all(:songs).join(Lyric, :id=>:lyric_id, id=>[:composer_id, :arranger_id, :vocalist_id, :lyricist_id])}, \
785
- :eager_loader=>(proc do |eo|
706
+ one_to_many :songs, order: Sequel[:songs][:name],
707
+ dataset: proc{Song.select_all(:songs).join(:lyrics, id: :lyric_id, id=>[:composer_id, :arranger_id, :vocalist_id, :lyricist_id])},
708
+ eager_loader: (lambda do |eo|
786
709
  h = eo[:id_map]
787
710
  ids = h.keys
788
711
  eo[:rows].each{|r| r.associations[:songs] = []}
789
712
  Song.select_all(:songs).
790
713
  select_append{[lyrics[:composer_id], lyrics[:arranger_id], lyrics[:vocalist_id], lyrics[:lyricist_id]}.
791
- join(Lyric, :id=>:lyric_id){Sequel.or(:composer_id=>ids, :arranger_id=>ids, :vocalist_id=>ids, :lyricist_id=>ids)}.
714
+ join(:lyrics, id: :lyric_id){Sequel.or(composer_id: ids, arranger_id: ids, vocalist_id: ids, lyricist_id: ids)}.
792
715
  order{songs[:name]}.all do |song|
793
716
  [:composer_id, :arranger_id, :vocalist_id, :lyricist_id].each do |x|
794
717
  recs = h[song.values.delete(x)]
@@ -811,11 +734,11 @@ associated tickets.
811
734
 
812
735
  class Project < Sequel::Model
813
736
  one_to_many :tickets
814
- many_to_one :ticket_hours, :read_only=>true, :key=>:id,
815
- :dataset=>proc{Ticket.where(:project_id=>id).select{sum(hours).as(hours)}},
816
- :eager_loader=>(proc do |eo|
737
+ many_to_one :ticket_hours, read_only: true, key: :id,
738
+ dataset: proc{Ticket.where(:project_id=>id).select{sum(hours).as(hours)}},
739
+ eager_loader: (lambda do |eo|
817
740
  eo[:rows].each{|p| p.associations[:ticket_hours] = nil}
818
- Ticket.where(:project_id=>eo[:id_map].keys).
741
+ Ticket.where(project_id: eo[:id_map].keys).
819
742
  select_group(:project_id).
820
743
  select_append{sum(hours).as(hours)}.
821
744
  all do |t|
@@ -838,4 +761,4 @@ associated tickets.
838
761
  end
839
762
 
840
763
  Note that it is often better to use a sum cache instead of this approach. You can implement
841
- a sum cache using +after_create+ and +after_delete+ hooks, or preferrably using a database trigger.
764
+ a sum cache using +after_create+, +after_update+, and +after_delete+ hooks, or preferrably using a database trigger.