sequel 4.49.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
@@ -41,26 +41,12 @@ else
41
41
  alias_method :aref_before_sequel, :[]
42
42
  end
43
43
 
44
- if RUBY_VERSION >= '1.9'
45
- #
46
- def [](v)
47
- case v
48
- when Symbol, Sequel::SQL::Identifier, Sequel::SQL::QualifiedIdentifier
49
- Sequel::SQL::QualifiedIdentifier.new(self, v)
50
- else
51
- aref_before_sequel(v)
52
- end
53
- end
54
- else
55
- def [](*v)
56
- arg = v.first if v.length == 1
57
-
58
- case arg
59
- when Symbol, Sequel::SQL::Identifier, Sequel::SQL::QualifiedIdentifier
60
- Sequel::SQL::QualifiedIdentifier.new(self, arg)
61
- else
62
- respond_to?(:aref_before_sequel) ? aref_before_sequel(*v) : super(*v)
63
- end
44
+ def [](v)
45
+ case v
46
+ when Symbol, Sequel::SQL::Identifier, Sequel::SQL::QualifiedIdentifier
47
+ Sequel::SQL::QualifiedIdentifier.new(self, v)
48
+ else
49
+ aref_before_sequel(v)
64
50
  end
65
51
  end
66
52
  end
@@ -1,24 +1,13 @@
1
1
  # frozen-string-literal: true
2
2
 
3
- require 'sequel/core'
3
+ require_relative 'core'
4
4
 
5
5
  module Sequel
6
- # Delegate to Sequel::Model, only for backwards compatibility.
7
- def self.cache_anonymous_models
8
- Sequel::Deprecation.deprecate("Sequel.cache_anonymous_models", "Use Sequel::Model.cache_anonymous_models")
9
- Model.cache_anonymous_models
10
- end
11
-
12
- # Delegate to Sequel::Model, only for backwards compatibility.
13
- def self.cache_anonymous_models=(v)
14
- Sequel::Deprecation.deprecate("Sequel.cache_anonymous_models=", "Use Sequel::Model.cache_anonymous_models=")
15
- Model.cache_anonymous_models = v
16
- end
17
-
18
6
  # <tt>Sequel::Model</tt> is an object relational mapper built on top of Sequel core. Each
19
7
  # model class is backed by a dataset instance, and many dataset methods can be
20
8
  # called directly on the class. Model datasets return rows as model instances,
21
- # which have fairly standard ORM instance behavior.
9
+ # which are wrappers around the underlying hash that allow easily updating or
10
+ # deleting the individual row.
22
11
  #
23
12
  # <tt>Sequel::Model</tt> is built completely out of plugins. Plugins can override any class,
24
13
  # instance, or dataset method defined by a previous plugin and call super to get the default
@@ -31,47 +20,30 @@ module Sequel
31
20
  class Model
32
21
  OPTS = Sequel::OPTS
33
22
 
34
- DATASET_METHODS = (Dataset::ACTION_METHODS + Dataset::QUERY_METHODS + [:each_server, :where_all, :where_each, :where_single_value]) - [:and, :or, :[], :columns, :columns!, :delete, :update, :add_graph_aliases]
35
- Sequel::Deprecation.deprecate_constant(self, :DATASET_METHODS)
36
- BOOLEAN_SETTINGS = [:typecast_empty_string_to_nil, :typecast_on_assignment, :strict_param_setting, :raise_on_save_failure, :raise_on_typecast_failure, :require_modification, :use_transactions, :use_after_commit_rollback]
37
- Sequel::Deprecation.deprecate_constant(self, :BOOLEAN_SETTINGS)
38
- BEFORE_HOOKS = [:before_create, :before_update, :before_save, :before_destroy, :before_validation]
39
- Sequel::Deprecation.deprecate_constant(self, :BEFORE_HOOKS)
40
- AFTER_HOOKS = [:after_create, :after_update, :after_save, :after_destroy, :after_validation, :after_commit, :after_rollback, :after_destroy_commit, :after_destroy_rollback]
41
- Sequel::Deprecation.deprecate_constant(self, :AFTER_HOOKS)
42
- AROUND_HOOKS = [:around_create, :around_update, :around_save, :around_destroy, :around_validation]
43
- Sequel::Deprecation.deprecate_constant(self, :AROUND_HOOKS)
44
- NORMAL_METHOD_NAME_REGEXP = /\A[A-Za-z_][A-Za-z0-9_]*\z/
45
- Sequel::Deprecation.deprecate_constant(self, :NORMAL_METHOD_NAME_REGEXP)
46
- SETTER_METHOD_REGEXP = /=\z/
47
- Sequel::Deprecation.deprecate_constant(self, :SETTER_METHOD_REGEXP)
48
- ANONYMOUS_MODEL_CLASSES = @Model_cache = {}
49
- Sequel::Deprecation.deprecate_constant(self, :ANONYMOUS_MODEL_CLASSES)
50
- ANONYMOUS_MODEL_CLASSES_MUTEX = Mutex.new
51
- Sequel::Deprecation.deprecate_constant(self, :ANONYMOUS_MODEL_CLASSES_MUTEX)
52
- INHERITED_INSTANCE_VARIABLES = { :@allowed_columns=>:dup, :@dataset_method_modules=>:dup, :@primary_key=>nil, :@use_transactions=>nil, :@raise_on_save_failure=>nil, :@require_modification=>nil, :@restrict_primary_key=>nil, :@simple_pk=>nil, :@simple_table=>nil, :@strict_param_setting=>nil, :@typecast_empty_string_to_nil=>nil, :@typecast_on_assignment=>nil, :@raise_on_typecast_failure=>nil, :@plugins=>:dup, :@setter_methods=>nil, :@use_after_commit_rollback=>nil, :@fast_pk_lookup_sql=>nil, :@fast_instance_delete_sql=>nil, :@finders=>:dup, :@finder_loaders=>:dup, :@db=>nil, :@default_set_fields_options=>:dup, :@require_valid_table=>nil, :@cache_anonymous_models=>nil, :@dataset_module_class=>nil}
53
- Sequel::Deprecation.deprecate_constant(self, :INHERITED_INSTANCE_VARIABLES)
54
-
55
- # Empty instance methods to create that the user can override to get hook/callback behavior.
23
+ # Empty instance methods to create that the user can override.
56
24
  # Just like any other method defined by Sequel, if you override one of these, you should
57
- # call +super+ to get the default behavior (while empty by default, they can also be defined
25
+ # call +super+ to get the default behavior (while empty by default, they are often overridden
58
26
  # by plugins). See the {"Model Hooks" guide}[rdoc-ref:doc/model_hooks.rdoc] for
59
27
  # more detail on hooks.
60
- HOOKS = [:before_create, :before_update, :before_save, :before_destroy, :before_validation,
61
- :after_create, :after_update, :after_save, :after_destroy, :after_validation,
62
- :after_commit, :after_rollback, :after_destroy_commit, :after_destroy_rollback # SEQUEL5: Remove commit/rollback hooks
63
- ]#.freeze # SEQUEL5
28
+ HOOKS = [
29
+ :after_create,
30
+ :after_destroy,
31
+ :after_save,
32
+ :after_update,
33
+ :after_validation,
34
+ :before_create,
35
+ :before_destroy,
36
+ :before_save,
37
+ :before_update,
38
+ :before_validation
39
+ ].freeze
64
40
 
65
- @allowed_columns = nil # SEQUEL5: Remove
66
41
  @cache_anonymous_models = true
67
42
  @db = nil
68
43
  @db_schema = nil
69
44
  @dataset = nil
70
45
  @dataset_method_modules = []
71
- @default_eager_limit_strategy = true
72
46
  @default_set_fields_options = {}
73
- @finders = {} # SEQUEL5: Remove
74
- @finder_loaders = {} # SEQUEL5: Remove
75
47
  @overridable_methods_module = nil
76
48
  @fast_pk_lookup_sql = nil
77
49
  @fast_instance_delete_sql = nil
@@ -80,7 +52,7 @@ module Sequel
80
52
  @raise_on_save_failure = true
81
53
  @raise_on_typecast_failure = false
82
54
  @require_modification = nil
83
- @require_valid_table = nil
55
+ @require_valid_table = true
84
56
  @restrict_primary_key = true
85
57
  @setter_methods = nil
86
58
  @simple_pk = nil
@@ -88,12 +60,17 @@ module Sequel
88
60
  @strict_param_setting = true
89
61
  @typecast_empty_string_to_nil = true
90
62
  @typecast_on_assignment = true
91
- @use_after_commit_rollback = nil
92
63
  @use_transactions = true
93
64
 
94
- Sequel.require %w"default_inflections inflections plugins dataset_module base exceptions errors", "model"
65
+ require_relative "model/default_inflections"
66
+ require_relative "model/inflections"
67
+ require_relative "model/plugins"
68
+ require_relative "model/dataset_module"
69
+ require_relative "model/base"
70
+ require_relative "model/exceptions"
71
+ require_relative "model/errors"
95
72
  if !defined?(::SEQUEL_NO_ASSOCIATIONS) && !ENV.has_key?('SEQUEL_NO_ASSOCIATIONS')
96
- Sequel.require 'associations', 'model'
73
+ require_relative 'model/associations'
97
74
  plugin Model::Associations
98
75
  end
99
76
 
@@ -101,18 +78,6 @@ module Sequel
101
78
 
102
79
  # The setter methods (methods ending with =) that are never allowed
103
80
  # to be called automatically via +set+/+update+/+new+/etc..
104
- RESTRICTED_SETTER_METHODS = instance_methods.map(&:to_s).select{|l| l.end_with?('=')}#.freeze # SEQUEL5
105
-
106
- # SEQUEL5: Remove
107
- class DeprecatedColumnsUpdated # :nodoc:
108
- def initialize(columns_updated)
109
- @columns_updated = columns_updated
110
- end
111
-
112
- def method_missing(*args, &block)
113
- Sequel::Deprecation.deprecate("Accessing @columns_updated directly", "Use the columns_updated plugin and switch to the columns_updated method")
114
- @columns_updated.send(*args, &block)
115
- end
116
- end
81
+ RESTRICTED_SETTER_METHODS = instance_methods.map(&:to_s).select{|l| l.end_with?('=')}.freeze
117
82
  end
118
83
  end
@@ -10,10 +10,11 @@ module Sequel
10
10
 
11
11
  # Set an empty association reflection hash in the model
12
12
  def self.apply(model)
13
- model.instance_eval do
13
+ model.instance_exec do
14
14
  @association_reflections = {}
15
15
  @autoreloading_associations = {}
16
16
  @cache_associations = true
17
+ @default_eager_limit_strategy = true
17
18
  @default_association_options = {}
18
19
  @default_association_type_options = {}
19
20
  @dataset_module_class = DatasetModule
@@ -33,27 +34,27 @@ module Sequel
33
34
 
34
35
  # Name symbol for the _add internal association method
35
36
  def _add_method
36
- :"_add_#{singularize(self[:name])}"
37
+ self[:_add_method]
37
38
  end
38
39
 
39
40
  # Name symbol for the _remove_all internal association method
40
41
  def _remove_all_method
41
- :"_remove_all_#{self[:name]}"
42
+ self[:_remove_all_method]
42
43
  end
43
44
 
44
45
  # Name symbol for the _remove internal association method
45
46
  def _remove_method
46
- :"_remove_#{singularize(self[:name])}"
47
+ self[:_remove_method]
47
48
  end
48
49
 
49
50
  # Name symbol for the _setter association method
50
51
  def _setter_method
51
- :"_#{self[:name]}="
52
+ self[:_setter_method]
52
53
  end
53
54
 
54
55
  # Name symbol for the add association method
55
56
  def add_method
56
- :"add_#{singularize(self[:name])}"
57
+ self[:add_method]
57
58
  end
58
59
 
59
60
  # Name symbol for association method, the same as the name of the association.
@@ -81,9 +82,10 @@ module Sequel
81
82
 
82
83
  # Apply all non-instance specific changes to the given dataset and return it.
83
84
  def apply_dataset_changes(ds)
84
- ds = ds.with_extend(AssociationDatasetMethods).
85
- clone(:association_reflection => self)
86
- self[:extend].each{|m| ds = ds.with_extend(m)}
85
+ ds = ds.with_extend(AssociationDatasetMethods).clone(:association_reflection => self)
86
+ if exts = self[:reverse_extend]
87
+ ds = ds.with_extend(*exts)
88
+ end
87
89
  ds = ds.select(*select) if select
88
90
  if c = self[:conditions]
89
91
  ds = (c.is_a?(Array) && !Sequel.condition_specifier?(c)) ? ds.where(*c) : ds.where(c)
@@ -191,7 +193,7 @@ module Sequel
191
193
 
192
194
  # Name symbol for the dataset association method
193
195
  def dataset_method
194
- :"#{self[:name]}_dataset"
196
+ self[:dataset_method]
195
197
  end
196
198
 
197
199
  # Whether the dataset needs a primary key to function, true by default.
@@ -325,12 +327,6 @@ module Sequel
325
327
  false
326
328
  end
327
329
 
328
- # Alias of predicate_key, only for backwards compatibility.
329
- def eager_loading_predicate_key
330
- Sequel::Deprecation.deprecate("AssociationReflection#eager_loading_predicate_key", "Use #predicate_key instead")
331
- predicate_key
332
- end
333
-
334
330
  # Whether to eagerly graph a lazy dataset, true by default. If this
335
331
  # is false, the association won't respect the :eager_graph option
336
332
  # when loading the association for a single record.
@@ -362,6 +358,7 @@ module Sequel
362
358
  finalize_settings.each do |meth, key|
363
359
  next if has_key?(key)
364
360
 
361
+ # Allow calling private methods to make sure caching is done appropriately
365
362
  send(meth)
366
363
  self[key] = cache.delete(key) if cache.has_key?(key)
367
364
  end
@@ -401,7 +398,7 @@ module Sequel
401
398
  end
402
399
  end
403
400
 
404
- # Show which type of reflection this is, and a guess at what line was used to create the
401
+ # Show which type of reflection this is, and a guess at what code was used to create the
405
402
  # association.
406
403
  def inspect
407
404
  o = self[:orig_opts].dup
@@ -450,9 +447,7 @@ module Sequel
450
447
  predicate_key_methods.map{|k| object.get_column_value(k)}
451
448
  end
452
449
 
453
- # Qualify +col+ with the given table name. If +col+ is an array of columns,
454
- # return an array of qualified columns. Only qualifies Symbols and SQL::Identifier
455
- # values, other values are not modified.
450
+ # Qualify +col+ with the given table name.
456
451
  def qualify(table, col)
457
452
  transform(col) do |k|
458
453
  case k
@@ -505,7 +500,7 @@ module Sequel
505
500
 
506
501
  # Name symbol for the remove_all_ association method
507
502
  def remove_all_method
508
- :"remove_all_#{self[:name]}"
503
+ self[:remove_all_method]
509
504
  end
510
505
 
511
506
  # Whether associated objects need to be removed from the association before
@@ -516,7 +511,7 @@ module Sequel
516
511
 
517
512
  # Name symbol for the remove_ association method
518
513
  def remove_method
519
- :"remove_#{singularize(self[:name])}"
514
+ self[:remove_method]
520
515
  end
521
516
 
522
517
  # Whether to check that an object to be disassociated is already associated to this object, false by default.
@@ -543,7 +538,7 @@ module Sequel
543
538
 
544
539
  # Name symbol for the setter association method
545
540
  def setter_method
546
- :"#{self[:name]}="
541
+ self[:setter_method]
547
542
  end
548
543
 
549
544
  # The range used for slicing when using the :ruby eager limit strategy.
@@ -556,8 +551,10 @@ module Sequel
556
551
 
557
552
  private
558
553
 
559
- # On non-GVL rubies, assume the need to synchronize access. Store the key
560
- # in a special sub-hash that always uses this method to synchronize access.
554
+ # If the key exists in the reflection hash, return it.
555
+ # If the key doesn't exist and association reflections are uncached, then yield to get the value.
556
+ # If the key doesn't exist and association reflection are cached, check the cache and return
557
+ # the value if present, or yield to get the value, cache the value, and return it.
561
558
  def cached_fetch(key)
562
559
  fetch(key) do
563
560
  return yield unless h = self[:cache]
@@ -567,7 +564,7 @@ module Sequel
567
564
  end
568
565
  end
569
566
 
570
- # Cache the value at the given key, synchronizing access.
567
+ # Cache the value at the given key if caching.
571
568
  def cached_set(key, value)
572
569
  return unless h = self[:cache]
573
570
  Sequel.synchronize{h[key] = value}
@@ -576,10 +573,10 @@ module Sequel
576
573
  # The base dataset used for the association, before any order/conditions
577
574
  # options have been applied.
578
575
  def _associated_dataset
579
- associated_class.dataset.clone
576
+ associated_class.dataset
580
577
  end
581
578
 
582
- # Whether for the reciprocal type for the given association can not be
579
+ # Whether for the reciprocal type for the given association cannot be
583
580
  # known in advantage, false by default.
584
581
  def ambiguous_reciprocal_type?
585
582
  false
@@ -1106,7 +1103,7 @@ module Sequel
1106
1103
  end
1107
1104
 
1108
1105
  # Support automatic use of correlated subqueries if :ruby option is best available option,
1109
- # MySQL is not being used, and either the associated class has a non-composite primary key
1106
+ # the database supports them, and either the associated class has a non-composite primary key
1110
1107
  # or the database supports multiple columns in IN.
1111
1108
  def true_eager_graph_limit_strategy
1112
1109
  r = super
@@ -1451,8 +1448,6 @@ module Sequel
1451
1448
 
1452
1449
  # This module contains methods added to all association datasets
1453
1450
  module AssociationDatasetMethods
1454
- Dataset.def_deprecated_opts_setter(self, :model_object, :association_reflection)
1455
-
1456
1451
  # The model object that created the association dataset
1457
1452
  def model_object
1458
1453
  @opts[:model_object]
@@ -1508,7 +1503,7 @@ module Sequel
1508
1503
  # Project.associations
1509
1504
  # => [:portfolio, :milestones]
1510
1505
  # Project.association_reflection(:portfolio)
1511
- # => {:type => :many_to_one, :name => :portfolio, ...}
1506
+ # => #<Sequel::Model::Associations::ManyToOneAssociationReflection Project.many_to_one :portfolio>
1512
1507
  #
1513
1508
  # Associations should not have the same names as any of the columns in the
1514
1509
  # model's current table they reference. If you are dealing with an existing schema that
@@ -1530,7 +1525,7 @@ module Sequel
1530
1525
 
1531
1526
  # Whether association metadata should be cached in the association reflection. If not cached, it will be computed
1532
1527
  # on demand. In general you only want to set this to false when using code reloading. When using code reloading,
1533
- # setting this will make sure that if an associated class is removed or modified, this class will not hang on to
1528
+ # setting this will make sure that if an associated class is removed or modified, this class will not have a reference to
1534
1529
  # the previous class.
1535
1530
  attr_accessor :cache_associations
1536
1531
 
@@ -1605,7 +1600,7 @@ module Sequel
1605
1600
  # singularized unless the type is :many_to_one, :one_to_one, or one_through_one). If this is specified
1606
1601
  # as a string or symbol, you must specify the full class name (e.g. "::SomeModule::MyModel").
1607
1602
  # :class_namespace :: If :class is given as a string or symbol, sets the default namespace in which to look for
1608
- # the class. <tt>:class=>'Foo', :class_namespace=>'Bar'</tt> looks for <tt>::Bar::Foo</tt>.)
1603
+ # the class. <tt>class: 'Foo', class_namespace: 'Bar'</tt> looks for <tt>::Bar::Foo</tt>.)
1609
1604
  # :clearer :: Proc used to define the private _remove_all_* method for doing the database work
1610
1605
  # to remove all objects associated to the current object (*_to_many assocations).
1611
1606
  # :clone :: Merge the current options and block into the options and block used in defining
@@ -1678,8 +1673,7 @@ module Sequel
1678
1673
  # :order_eager_graph :: Whether to add the association's order to the graphed dataset's order when graphing
1679
1674
  # via +eager_graph+. Defaults to true, so set to false to disable.
1680
1675
  # :read_only :: Do not add a setter method (for many_to_one or one_to_one associations),
1681
- # or add_/remove_/remove_all_ methods (for one_to_many and many_to_many associations). Always
1682
- # true for one_through_one associations.
1676
+ # or add_/remove_/remove_all_ methods (for one_to_many and many_to_many associations).
1683
1677
  # :reciprocal :: the symbol name of the reciprocal association,
1684
1678
  # if it exists. By default, Sequel will try to determine it by looking at the
1685
1679
  # associated model's assocations for a association that matches
@@ -1710,7 +1704,7 @@ module Sequel
1710
1704
  # array of symbols for a composite key association.
1711
1705
  # :primary_key_method :: the method symbol or array of method symbols to call on the associated
1712
1706
  # object to get the foreign key values. Defaults to :primary_key option.
1713
- # :qualify :: Whether to use qualifier primary keys when loading the association. The default
1707
+ # :qualify :: Whether to use qualified primary keys when loading the association. The default
1714
1708
  # is true, so you must set to false to not qualify. Qualification rarely causes
1715
1709
  # problems, but it's necessary to disable in some cases, such as when you are doing
1716
1710
  # a JOIN USING operation on the column on Oracle.
@@ -1803,10 +1797,6 @@ module Sequel
1803
1797
  end
1804
1798
 
1805
1799
  opts[:eager_block] = opts[:block] unless opts.include?(:eager_block)
1806
- if !opts.has_key?(:predicate_key) && opts.has_key?(:eager_loading_predicate_key)
1807
- Sequel::Deprecation.deprecate("The :eager_loading_predicate_key association option", "Use the :predicate_key option instead")
1808
- opts[:predicate_key] = opts[:eager_loading_predicate_key]
1809
- end
1810
1800
  opts[:graph_join_type] ||= :left_outer
1811
1801
  opts[:order_eager_graph] = true unless opts.include?(:order_eager_graph)
1812
1802
  conds = opts[:conditions]
@@ -1814,9 +1804,15 @@ module Sequel
1814
1804
  opts[:graph_conditions] = conds if !opts.include?(:graph_conditions) and Sequel.condition_specifier?(conds)
1815
1805
  opts[:graph_conditions] = opts.fetch(:graph_conditions, []).to_a
1816
1806
  opts[:graph_select] = Array(opts[:graph_select]) if opts[:graph_select]
1817
- [:before_add, :before_remove, :after_add, :after_remove, :after_load, :before_set, :after_set, :extend].each do |cb_type|
1818
- opts[cb_type] = Array(opts[cb_type])
1807
+ [:before_add, :before_remove, :after_add, :after_remove, :after_load, :before_set, :after_set].each do |cb_type|
1808
+ opts[cb_type] = Array(opts[cb_type]) if opts[cb_type]
1809
+ end
1810
+
1811
+ if opts[:extend]
1812
+ opts[:extend] = Array(opts[:extend])
1813
+ opts[:reverse_extend] = opts[:extend].reverse
1819
1814
  end
1815
+
1820
1816
  late_binding_class_option(opts, opts.returns_array? ? singularize(name) : name)
1821
1817
 
1822
1818
  # Remove :class entry if it exists and is nil, to work with cached_fetch
@@ -1877,7 +1873,7 @@ module Sequel
1877
1873
  associate(:many_to_one, name, opts, &block)
1878
1874
  end
1879
1875
 
1880
- # Shortcut for adding a one_through_one association, see #associate.
1876
+ # Shortcut for adding a one_through_one association, see #associate
1881
1877
  def one_through_one(name, opts=OPTS, &block)
1882
1878
  associate(:one_through_one, name, opts, &block)
1883
1879
  end
@@ -1887,7 +1883,7 @@ module Sequel
1887
1883
  associate(:one_to_many, name, opts, &block)
1888
1884
  end
1889
1885
 
1890
- # Shortcut for adding a one_to_one association, see #associate.
1886
+ # Shortcut for adding a one_to_one association, see #associate
1891
1887
  def one_to_one(name, opts=OPTS, &block)
1892
1888
  associate(:one_to_one, name, opts, &block)
1893
1889
  end
@@ -1918,14 +1914,29 @@ module Sequel
1918
1914
 
1919
1915
  # Adds the association method to the association methods module.
1920
1916
  def def_association_method(opts)
1921
- association_module_def(opts.association_method, opts) do |*dynamic_opts, &block|
1922
- Sequel::Deprecation.deprecate("Passing multiple arguments to ##{opts.association_method}", "Additional arguments are currently ignored") if dynamic_opts.length > 1
1923
- load_associated_objects(opts, dynamic_opts.length == 0 ? OPTS : dynamic_opts[0], &block)
1917
+ association_module_def(opts.association_method, opts) do |dynamic_opts=OPTS, &block|
1918
+ load_associated_objects(opts, dynamic_opts, &block)
1924
1919
  end
1925
1920
  end
1926
1921
 
1927
1922
  # Define all of the association instance methods for this association.
1928
1923
  def def_association_instance_methods(opts)
1924
+ # Always set the method names in the association reflection, even if they
1925
+ # are not used, for backwards compatibility.
1926
+ opts[:dataset_method] = :"#{opts[:name]}_dataset"
1927
+ if opts.returns_array?
1928
+ sname = singularize(opts[:name])
1929
+ opts[:_add_method] = :"_add_#{sname}"
1930
+ opts[:add_method] = :"add_#{sname}"
1931
+ opts[:_remove_method] = :"_remove_#{sname}"
1932
+ opts[:remove_method] = :"remove_#{sname}"
1933
+ opts[:_remove_all_method] = :"_remove_all_#{opts[:name]}"
1934
+ opts[:remove_all_method] = :"remove_all_#{opts[:name]}"
1935
+ else
1936
+ opts[:_setter_method] = :"_#{opts[:name]}="
1937
+ opts[:setter_method] = :"#{opts[:name]}="
1938
+ end
1939
+
1929
1940
  association_module_def(opts.dataset_method, opts){_dataset(opts)}
1930
1941
  def_association_method(opts)
1931
1942
 
@@ -1933,23 +1944,23 @@ module Sequel
1933
1944
 
1934
1945
  if opts[:setter] && opts[:_setter]
1935
1946
  # This is backwards due to backwards compatibility
1936
- association_module_private_def(opts._setter_method, opts, &opts[:setter])
1937
- association_module_def(opts.setter_method, opts, &opts[:_setter])
1947
+ association_module_private_def(opts[:_setter_method], opts, &opts[:setter])
1948
+ association_module_def(opts[:setter_method], opts, &opts[:_setter])
1938
1949
  end
1939
1950
 
1940
1951
  if adder = opts[:adder]
1941
- association_module_private_def(opts._add_method, opts, &adder)
1942
- association_module_def(opts.add_method, opts){|o,*args| add_associated_object(opts, o, *args)}
1952
+ association_module_private_def(opts[:_add_method], opts, &adder)
1953
+ association_module_def(opts[:add_method], opts){|o,*args| add_associated_object(opts, o, *args)}
1943
1954
  end
1944
1955
 
1945
1956
  if remover = opts[:remover]
1946
- association_module_private_def(opts._remove_method, opts, &remover)
1947
- association_module_def(opts.remove_method, opts){|o,*args| remove_associated_object(opts, o, *args)}
1957
+ association_module_private_def(opts[:_remove_method], opts, &remover)
1958
+ association_module_def(opts[:remove_method], opts){|o,*args| remove_associated_object(opts, o, *args)}
1948
1959
  end
1949
1960
 
1950
1961
  if clearer = opts[:clearer]
1951
- association_module_private_def(opts._remove_all_method, opts, &clearer)
1952
- association_module_def(opts.remove_all_method, opts){|*args| remove_all_associated_objects(opts, *args)}
1962
+ association_module_private_def(opts[:_remove_all_method], opts, &clearer)
1963
+ association_module_def(opts[:remove_all_method], opts){|*args| remove_all_associated_objects(opts, *args)}
1953
1964
  end
1954
1965
  end
1955
1966
 
@@ -1976,7 +1987,10 @@ module Sequel
1976
1987
  join_table = (opts[:join_table] ||= opts.default_join_table)
1977
1988
  opts[:left_key_alias] ||= opts.default_associated_key_alias
1978
1989
  opts[:graph_join_table_join_type] ||= opts[:graph_join_type]
1979
- opts[:after_load].unshift(:array_uniq!) if opts[:uniq]
1990
+ if opts[:uniq]
1991
+ opts[:after_load] ||= []
1992
+ opts[:after_load].unshift(:array_uniq!)
1993
+ end
1980
1994
  opts[:dataset] ||= opts.association_dataset_proc
1981
1995
  opts[:eager_loader] ||= opts.method(:default_eager_loader)
1982
1996
 
@@ -2273,7 +2287,7 @@ module Sequel
2273
2287
 
2274
2288
  # Return a dataset for the association after applying any dynamic callback.
2275
2289
  def _associated_dataset(opts, dynamic_opts)
2276
- ds = send(opts.dataset_method)
2290
+ ds = public_send(opts.dataset_method)
2277
2291
  if callback = dynamic_opts[:callback]
2278
2292
  ds = callback.call(ds)
2279
2293
  end
@@ -2353,7 +2367,8 @@ module Sequel
2353
2367
  raise(Sequel::Error, "model object #{inspect} does not have a primary key") if opts.dataset_need_primary_key? && !pk
2354
2368
  ensure_associated_primary_key(opts, o, *args)
2355
2369
  return if run_association_callbacks(opts, :before_add, o) == false
2356
- return if !send(opts._add_method, o, *args) && opts.handle_silent_modification_failure?
2370
+ # Allow calling private _add method
2371
+ return if !send(opts[:_add_method], o, *args) && opts.handle_silent_modification_failure?
2357
2372
  if array = associations[opts[:name]] and !array.include?(o)
2358
2373
  array.push(o)
2359
2374
  end
@@ -2407,28 +2422,10 @@ module Sequel
2407
2422
  self
2408
2423
  end
2409
2424
 
2410
- # Handle parsing of options when loading associations. For historical
2411
- # reasons, you can pass true/false/nil or a callable argument to
2412
- # associations. That will be going away in Sequel 5, but we'll still
2413
- # support it until then.
2425
+ # If a block is given, assign it as the :callback option in the hash, and return the hash.
2414
2426
  def load_association_objects_options(dynamic_opts, &block)
2415
- dynamic_opts = case dynamic_opts
2416
- when true, false, nil
2417
- Sequel::Deprecation.deprecate("Passing #{dynamic_opts.inspect} an argument to an association loading method", "Pass {:reload=>#{dynamic_opts.inspect}} instead")
2418
- {:reload=>dynamic_opts}
2419
- when Hash
2420
- Hash[dynamic_opts]
2421
- else
2422
- if dynamic_opts.respond_to?(:call)
2423
- Sequel::Deprecation.deprecate("Passing callbable argument #{dynamic_opts.inspect} to an association loading method", "Pass a block to the method to use a callback")
2424
- {:callback=>dynamic_opts}
2425
- else
2426
- Sequel::Deprecation.deprecate("Passing #{dynamic_opts.inspect} an argument to an association loading method", "Pass {:reload=>true} if you would like to reload the association")
2427
- {:reload=>true}
2428
- end
2429
- end
2430
-
2431
- if block_given?
2427
+ if block
2428
+ dynamic_opts = Hash[dynamic_opts]
2432
2429
  dynamic_opts[:callback] = block
2433
2430
  end
2434
2431
 
@@ -2436,7 +2433,7 @@ module Sequel
2436
2433
  end
2437
2434
 
2438
2435
  # Load the associated objects using the dataset, handling callbacks, reciprocals, and caching.
2439
- def load_associated_objects(opts, dynamic_opts=nil, &block)
2436
+ def load_associated_objects(opts, dynamic_opts, &block)
2440
2437
  dynamic_opts = load_association_objects_options(dynamic_opts, &block)
2441
2438
  name = opts[:name]
2442
2439
  if associations.include?(name) && !dynamic_opts[:callback] && !dynamic_opts[:reload]
@@ -2490,7 +2487,8 @@ module Sequel
2490
2487
  # Remove all associated objects from the given association
2491
2488
  def remove_all_associated_objects(opts, *args)
2492
2489
  raise(Sequel::Error, "model object #{inspect} does not have a primary key") if opts.dataset_need_primary_key? && !pk
2493
- send(opts._remove_all_method, *args)
2490
+ # Allow calling private _remove_all method
2491
+ send(opts[:_remove_all_method], *args)
2494
2492
  ret = associations[opts[:name]].each{|o| remove_reciprocal_object(opts, o)} if associations.include?(opts[:name])
2495
2493
  associations[opts[:name]] = []
2496
2494
  ret
@@ -2503,13 +2501,14 @@ module Sequel
2503
2501
  o = remove_check_existing_object_from_pk(opts, o, *args)
2504
2502
  elsif !o.is_a?(klass)
2505
2503
  raise(Sequel::Error, "associated object #{o.inspect} not of correct type #{klass}")
2506
- elsif opts.remove_should_check_existing? && send(opts.dataset_method).where(o.pk_hash).empty?
2504
+ elsif opts.remove_should_check_existing? && public_send(opts.dataset_method).where(o.pk_hash).empty?
2507
2505
  raise(Sequel::Error, "associated object #{o.inspect} is not currently associated to #{inspect}")
2508
2506
  end
2509
2507
  raise(Sequel::Error, "model object #{inspect} does not have a primary key") if opts.dataset_need_primary_key? && !pk
2510
2508
  raise(Sequel::Error, "associated object #{o.inspect} does not have a primary key") if opts.need_associated_primary_key? && !o.pk
2511
2509
  return if run_association_callbacks(opts, :before_remove, o) == false
2512
- return if !send(opts._remove_method, o, *args) && opts.handle_silent_modification_failure?
2510
+ # Allow calling private _remove method
2511
+ return if !send(opts[:_remove_method], o, *args) && opts.handle_silent_modification_failure?
2513
2512
  associations[opts[:name]].delete_if{|x| o === x} if associations.include?(opts[:name])
2514
2513
  remove_reciprocal_object(opts, o)
2515
2514
  run_association_callbacks(opts, :after_remove, o)
@@ -2522,7 +2521,7 @@ module Sequel
2522
2521
  def remove_check_existing_object_from_pk(opts, o, *args)
2523
2522
  key = o
2524
2523
  pkh = opts.associated_class.qualified_primary_key_hash(key)
2525
- raise(Sequel::Error, "no object with key(s) #{key.inspect} is currently associated to #{inspect}") unless o = send(opts.dataset_method).first(pkh)
2524
+ raise(Sequel::Error, "no object with key(s) #{key.inspect} is currently associated to #{inspect}") unless o = public_send(opts.dataset_method).first(pkh)
2526
2525
  o
2527
2526
  end
2528
2527
 
@@ -2540,30 +2539,28 @@ module Sequel
2540
2539
 
2541
2540
  # Run the callback for the association with the object.
2542
2541
  def run_association_callbacks(reflection, callback_type, object)
2543
- # The reason we automatically set raise_error for singular associations is that
2544
- # assignment in ruby always returns the argument instead of the result of the
2545
- # method, so we can't return nil to signal that the association callback prevented
2546
- # the modification
2547
- raise_error = raise_on_save_failure || !reflection.returns_array?
2548
- stop_on_false = [:before_add, :before_remove, :before_set].include?(callback_type)
2549
- reflection[callback_type].each do |cb|
2550
- res = case cb
2551
- when Symbol
2552
- send(cb, object)
2553
- when Proc
2554
- cb.call(self, object)
2555
- else
2556
- raise Error, "callbacks should either be Procs or Symbols"
2557
- end
2558
-
2559
- if res == false and stop_on_false
2560
- Sequel::Deprecation.deprecate("Having #{callback_type} association callback return false to cancel modification", "Instead, call Model#cancel_action inside the association callback")
2561
- raise(HookFailed, "Unable to modify association for #{inspect}: one of the #{callback_type} hooks returned false")
2542
+ return unless cbs = reflection[callback_type]
2543
+
2544
+ begin
2545
+ cbs.each do |cb|
2546
+ res = case cb
2547
+ when Symbol
2548
+ # Allow calling private methods in association callbacks
2549
+ send(cb, object)
2550
+ when Proc
2551
+ cb.call(self, object)
2552
+ else
2553
+ raise Error, "callbacks should either be Procs or Symbols"
2554
+ end
2562
2555
  end
2556
+ rescue HookFailed
2557
+ # The reason we automatically set raise_error for singular associations is that
2558
+ # assignment in ruby always returns the argument instead of the result of the
2559
+ # method, so we can't return nil to signal that the association callback prevented
2560
+ # the modification
2561
+ return false unless raise_on_save_failure || !reflection.returns_array?
2562
+ raise
2563
2563
  end
2564
- rescue HookFailed
2565
- return false unless raise_error
2566
- raise
2567
2564
  end
2568
2565
 
2569
2566
  # Set the given object as the associated object for the given *_to_one association reflection
@@ -2572,7 +2569,8 @@ module Sequel
2572
2569
  return if a && a == o && !set_associated_object_if_same?
2573
2570
  run_association_callbacks(opts, :before_set, o)
2574
2571
  remove_reciprocal_object(opts, a) if a
2575
- send(opts._setter_method, o)
2572
+ # Allow calling private _setter method
2573
+ send(opts[:_setter_method], o)
2576
2574
  associations[opts[:name]] = o
2577
2575
  add_reciprocal_object(opts, o) if o
2578
2576
  run_association_callbacks(opts, :after_set, o)
@@ -2630,37 +2628,35 @@ module Sequel
2630
2628
  # Album.eager_graph(:artist, :genre).all
2631
2629
  # Album.eager(:artist).eager(:genre).all
2632
2630
  # Album.eager_graph(:artist).eager(:genre).all
2633
- # Artist.eager(:albums=>:tracks).all
2634
- # Artist.eager_graph(:albums=>:tracks).all
2635
- # Artist.eager(:albums=>{:tracks=>:genre}).all
2636
- # Artist.eager_graph(:albums=>{:tracks=>:genre}).all
2631
+ # Artist.eager(albums: :tracks).all
2632
+ # Artist.eager_graph(albums: :tracks).all
2633
+ # Artist.eager(albums: {tracks: :genre}).all
2634
+ # Artist.eager_graph(albums: {tracks: :genre}).all
2637
2635
  #
2638
2636
  # You can also pass a callback as a hash value in order to customize the dataset being
2639
2637
  # eager loaded at query time, analogous to the way the :eager_block association option
2640
2638
  # allows you to customize it at association definition time. For example,
2641
2639
  # if you wanted artists with their albums since 1990:
2642
2640
  #
2643
- # Artist.eager(:albums => proc{|ds| ds.where{year > 1990}})
2641
+ # Artist.eager(albums: proc{|ds| ds.where{year > 1990}})
2644
2642
  #
2645
2643
  # Or if you needed albums and their artist's name only, using a single query:
2646
2644
  #
2647
- # Albums.eager_graph(:artist => proc{|ds| ds.select(:name)})
2645
+ # Albums.eager_graph(artist: proc{|ds| ds.select(:name)})
2648
2646
  #
2649
2647
  # To cascade eager loading while using a callback, you substitute the cascaded
2650
2648
  # associations with a single entry hash that has the proc callback as the key and
2651
2649
  # the cascaded associations as the value. This will load artists with their albums
2652
2650
  # since 1990, and also the tracks on those albums and the genre for those tracks:
2653
2651
  #
2654
- # Artist.eager(:albums => {proc{|ds| ds.where{year > 1990}}=>{:tracks => :genre}})
2652
+ # Artist.eager(albums: {proc{|ds| ds.where{year > 1990}}=>{tracks: :genre}})
2655
2653
  module DatasetMethods
2656
- Sequel::Dataset.def_mutation_method(:eager, :eager_graph, :module=>self)
2657
-
2658
2654
  %w'inner left right full'.each do |type|
2659
- class_eval <<END, __FILE__, __LINE__+1
2655
+ class_eval(<<-END, __FILE__, __LINE__+1)
2660
2656
  def association_#{type}_join(*associations)
2661
2657
  _association_join(:#{type}, associations)
2662
2658
  end
2663
- END
2659
+ END
2664
2660
  end
2665
2661
 
2666
2662
  # Adds one or more INNER JOINs to the existing dataset using the keys and conditions
@@ -2741,7 +2737,7 @@ END
2741
2737
  # it avoids problems such as aliasing conflicts and creating cartesian product
2742
2738
  # result sets if multiple one_to_many or many_to_many eager associations are requested.
2743
2739
  #
2744
- # One limitation of using this method is that you cannot filter the dataset
2740
+ # One limitation of using this method is that you cannot filter the current dataset
2745
2741
  # based on values of columns in an associated table, since the associations are loaded
2746
2742
  # in separate queries. To do that you need to load all associations in the
2747
2743
  # same query, and extract an object graph from the results of that query. If you
@@ -2758,7 +2754,8 @@ END
2758
2754
  end
2759
2755
 
2760
2756
  # The secondary eager loading method. Loads all associations in a single query. This
2761
- # method should only be used if you need to filter or order based on columns in associated tables.
2757
+ # method should only be used if you need to filter or order based on columns in associated tables,
2758
+ # or if you have done comparative benchmarking it and determined it is faster.
2762
2759
  #
2763
2760
  # This method uses <tt>Dataset#graph</tt> to create appropriate aliases for columns in all the
2764
2761
  # tables. Then it uses the graph's metadata to build the associations from the single hash, and
@@ -2766,7 +2763,7 @@ END
2766
2763
  #
2767
2764
  # Be very careful when using this with multiple one_to_many or many_to_many associations, as you can
2768
2765
  # create large cartesian products. If you must graph multiple one_to_many and many_to_many associations,
2769
- # make sure your filters are narrow if you have a large database.
2766
+ # make sure your filters are narrow if the datasets are large.
2770
2767
  #
2771
2768
  # Each association's order, if defined, is respected. +eager_graph+ probably
2772
2769
  # won't work correctly on a limited dataset, unless you are
@@ -2890,7 +2887,7 @@ END
2890
2887
  limit_strategy = r.eager_graph_limit_strategy(local_opts[:limit_strategy])
2891
2888
 
2892
2889
  if r[:conditions] && !Sequel.condition_specifier?(r[:conditions]) && !r[:orig_opts].has_key?(:graph_conditions) && !r[:orig_opts].has_key?(:graph_only_conditions) && !r.has_key?(:graph_block)
2893
- Sequel::Deprecation.deprecate("Ignoring :conditions for #{r[:model]} #{r[:name]} association during eager_graph/association_join, consider specifying :graph_block") unless r[:ignore_conditions_warning]
2890
+ raise Error, "Cannot eager_graph association when :conditions specified and not a hash or an array of pairs. Specify :graph_conditions, :graph_only_conditions, or :graph_block for the association. Model: #{r[:model]}, association: #{r[:name]}"
2894
2891
  end
2895
2892
 
2896
2893
  ds = loader.call(:self=>ds, :table_alias=>assoc_table_alias, :implicit_qualifier=>(ta == ds.opts[:eager_graph][:master]) ? first_source : qualifier_from_alias_symbol(ta, first_source), :callback=>callback, :join_type=>local_opts[:join_type], :join_only=>local_opts[:join_only], :limit_strategy=>limit_strategy, :from_self_alias=>ds.opts[:eager_graph][:master])
@@ -2982,6 +2979,7 @@ END
2982
2979
  # Return an expression for filtering by the given association reflection and associated object.
2983
2980
  def association_filter_expression(op, ref, obj)
2984
2981
  meth = :"#{ref[:type]}_association_filter_expression"
2982
+ # Allow calling private association specific method to get filter expression
2985
2983
  send(meth, op, ref, obj) if respond_to?(meth, true)
2986
2984
  end
2987
2985
 
@@ -3042,10 +3040,9 @@ END
3042
3040
  # Eagerly load all specified associations
3043
3041
  def eager_load(a, eager_assoc=@opts[:eager])
3044
3042
  return if a.empty?
3045
- # Key is foreign/primary key name symbol
3043
+ # Key is foreign/primary key name symbol.
3046
3044
  # Value is hash with keys being foreign/primary key values (generally integers)
3047
- # and values being an array of current model objects with that
3048
- # specific foreign/primary key
3045
+ # and values being an array of current model objects with that specific foreign/primary key
3049
3046
  key_hash = {}
3050
3047
  # Reflections for all associations to eager load
3051
3048
  reflections = eager_assoc.keys.map{|assoc| model.association_reflection(assoc) || (raise Sequel::UndefinedAssociation, "Model: #{self}, Association: #{assoc}")}
@@ -3088,7 +3085,7 @@ END
3088
3085
  eager_block, associations = pr_assoc
3089
3086
  end
3090
3087
  loader.call(:key_hash=>key_hash, :rows=>a, :associations=>associations, :self=>self, :eager_block=>eager_block, :id_map=>id_map)
3091
- a.each{|object| object.send(:run_association_callbacks, r, :after_load, object.associations[r[:name]])} unless r[:after_load].empty?
3088
+ a.each{|object| object.send(:run_association_callbacks, r, :after_load, object.associations[r[:name]])} if r[:after_load]
3092
3089
  end
3093
3090
  end
3094
3091
 
@@ -3220,7 +3217,7 @@ END
3220
3217
  after_load_map = @after_load_map = {}
3221
3218
  reflection_map.each do |k, v|
3222
3219
  alias_map[k] = v[:name]
3223
- after_load_map[k] = v[:after_load] unless v[:after_load].empty?
3220
+ after_load_map[k] = v[:after_load] if v[:after_load]
3224
3221
  type_map[k] = if v.returns_array?
3225
3222
  true
3226
3223
  elsif (limit_and_offset = limit_map[k]) && !limit_and_offset.last.nil?
@@ -3261,7 +3258,7 @@ END
3261
3258
  @records_map = records_map
3262
3259
 
3263
3260
  datasets = opts[:graph][:table_aliases].to_a.reject{|ta,ds| ds.nil?}
3264
- column_aliases = opts[:graph_aliases] || opts[:graph][:column_aliases] # SEQUEL5: Remove :graph_aliases support
3261
+ column_aliases = opts[:graph][:column_aliases]
3265
3262
  primary_keys = {}
3266
3263
  column_maps = {}
3267
3264
  models = {}
@@ -3383,7 +3380,7 @@ END
3383
3380
  # Return a suitable hash key for any subhash +h+, which is an array of values by column order.
3384
3381
  # This is only used if the primary key cannot be used.
3385
3382
  def hkey(h)
3386
- h.sort_by{|x| x[0].to_s}
3383
+ h.sort_by{|x| x[0]}
3387
3384
  end
3388
3385
 
3389
3386
  # Return the subhash for the master table by parsing the values out of the main hash +h+
@@ -3428,7 +3425,7 @@ END
3428
3425
  records.each do |record|
3429
3426
  dependency_map.each do |ta, deps|
3430
3427
  assoc_name = alias_map[ta]
3431
- list = record.send(assoc_name)
3428
+ list = record.public_send(assoc_name)
3432
3429
  rec_list = if type_map[ta]
3433
3430
  list.uniq!
3434
3431
  if lo = limit_map[ta]