sequel 4.49.0 → 5.3.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 (484) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +130 -0
  3. data/README.rdoc +195 -136
  4. data/Rakefile +26 -42
  5. data/bin/sequel +6 -9
  6. data/doc/advanced_associations.rdoc +91 -168
  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/release_notes/5.1.0.txt +31 -0
  29. data/doc/release_notes/5.2.0.txt +33 -0
  30. data/doc/release_notes/5.3.0.txt +121 -0
  31. data/doc/schema_modification.rdoc +78 -64
  32. data/doc/security.rdoc +97 -88
  33. data/doc/sharding.rdoc +43 -30
  34. data/doc/sql.rdoc +53 -65
  35. data/doc/testing.rdoc +4 -5
  36. data/doc/thread_safety.rdoc +2 -4
  37. data/doc/transactions.rdoc +18 -17
  38. data/doc/validations.rdoc +48 -45
  39. data/doc/virtual_rows.rdoc +87 -115
  40. data/lib/sequel/adapters/ado/access.rb +7 -13
  41. data/lib/sequel/adapters/ado/mssql.rb +2 -9
  42. data/lib/sequel/adapters/ado.rb +9 -25
  43. data/lib/sequel/adapters/amalgalite.rb +3 -18
  44. data/lib/sequel/adapters/ibmdb.rb +9 -45
  45. data/lib/sequel/adapters/jdbc/db2.rb +8 -37
  46. data/lib/sequel/adapters/jdbc/derby.rb +4 -50
  47. data/lib/sequel/adapters/jdbc/h2.rb +6 -26
  48. data/lib/sequel/adapters/jdbc/hsqldb.rb +2 -27
  49. data/lib/sequel/adapters/jdbc/jtds.rb +2 -9
  50. data/lib/sequel/adapters/jdbc/mssql.rb +1 -11
  51. data/lib/sequel/adapters/jdbc/mysql.rb +11 -15
  52. data/lib/sequel/adapters/jdbc/oracle.rb +4 -26
  53. data/lib/sequel/adapters/jdbc/postgresql.rb +23 -33
  54. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +4 -17
  55. data/lib/sequel/adapters/jdbc/sqlite.rb +1 -7
  56. data/lib/sequel/adapters/jdbc/sqlserver.rb +1 -13
  57. data/lib/sequel/adapters/jdbc/transactions.rb +1 -14
  58. data/lib/sequel/adapters/jdbc.rb +18 -74
  59. data/lib/sequel/adapters/mock.rb +4 -30
  60. data/lib/sequel/adapters/mysql.rb +7 -44
  61. data/lib/sequel/adapters/mysql2.rb +5 -23
  62. data/lib/sequel/adapters/odbc/db2.rb +1 -1
  63. data/lib/sequel/adapters/odbc/mssql.rb +4 -12
  64. data/lib/sequel/adapters/odbc/oracle.rb +1 -1
  65. data/lib/sequel/adapters/odbc.rb +0 -19
  66. data/lib/sequel/adapters/oracle.rb +8 -13
  67. data/lib/sequel/adapters/postgres.rb +28 -150
  68. data/lib/sequel/adapters/postgresql.rb +1 -1
  69. data/lib/sequel/adapters/shared/access.rb +11 -51
  70. data/lib/sequel/adapters/shared/db2.rb +3 -61
  71. data/lib/sequel/adapters/shared/mssql.rb +21 -157
  72. data/lib/sequel/adapters/shared/mysql.rb +61 -227
  73. data/lib/sequel/adapters/shared/oracle.rb +13 -41
  74. data/lib/sequel/adapters/shared/postgres.rb +58 -264
  75. data/lib/sequel/adapters/shared/sqlanywhere.rb +4 -96
  76. data/lib/sequel/adapters/shared/sqlite.rb +22 -101
  77. data/lib/sequel/adapters/sqlanywhere.rb +4 -23
  78. data/lib/sequel/adapters/sqlite.rb +2 -19
  79. data/lib/sequel/adapters/tinytds.rb +5 -15
  80. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +1 -1
  81. data/lib/sequel/adapters/utils/mysql_mysql2.rb +4 -4
  82. data/lib/sequel/adapters/utils/mysql_prepared_statements.rb +3 -6
  83. data/lib/sequel/adapters/utils/replace.rb +0 -5
  84. data/lib/sequel/adapters/utils/stored_procedures.rb +0 -2
  85. data/lib/sequel/adapters/utils/unmodified_identifiers.rb +2 -0
  86. data/lib/sequel/ast_transformer.rb +3 -94
  87. data/lib/sequel/connection_pool/sharded_single.rb +1 -4
  88. data/lib/sequel/connection_pool/sharded_threaded.rb +97 -95
  89. data/lib/sequel/connection_pool/single.rb +0 -2
  90. data/lib/sequel/connection_pool/threaded.rb +94 -110
  91. data/lib/sequel/connection_pool.rb +38 -28
  92. data/lib/sequel/core.rb +42 -101
  93. data/lib/sequel/database/connecting.rb +23 -60
  94. data/lib/sequel/database/dataset.rb +6 -9
  95. data/lib/sequel/database/dataset_defaults.rb +4 -48
  96. data/lib/sequel/database/features.rb +5 -4
  97. data/lib/sequel/database/logging.rb +2 -9
  98. data/lib/sequel/database/misc.rb +36 -55
  99. data/lib/sequel/database/query.rb +8 -13
  100. data/lib/sequel/database/schema_generator.rb +93 -64
  101. data/lib/sequel/database/schema_methods.rb +61 -79
  102. data/lib/sequel/database/transactions.rb +4 -24
  103. data/lib/sequel/database.rb +12 -2
  104. data/lib/sequel/dataset/actions.rb +57 -107
  105. data/lib/sequel/dataset/dataset_module.rb +4 -16
  106. data/lib/sequel/dataset/features.rb +35 -30
  107. data/lib/sequel/dataset/graph.rb +40 -49
  108. data/lib/sequel/dataset/misc.rb +12 -37
  109. data/lib/sequel/dataset/placeholder_literalizer.rb +4 -4
  110. data/lib/sequel/dataset/prepared_statements.rb +23 -51
  111. data/lib/sequel/dataset/query.rb +91 -161
  112. data/lib/sequel/dataset/sql.rb +33 -225
  113. data/lib/sequel/dataset.rb +18 -10
  114. data/lib/sequel/deprecated.rb +18 -27
  115. data/lib/sequel/exceptions.rb +1 -17
  116. data/lib/sequel/extensions/_model_pg_row.rb +0 -7
  117. data/lib/sequel/extensions/_pretty_table.rb +1 -3
  118. data/lib/sequel/extensions/arbitrary_servers.rb +10 -10
  119. data/lib/sequel/extensions/connection_expiration.rb +1 -1
  120. data/lib/sequel/extensions/connection_validator.rb +1 -1
  121. data/lib/sequel/extensions/constraint_validations.rb +11 -11
  122. data/lib/sequel/extensions/core_extensions.rb +39 -49
  123. data/lib/sequel/extensions/core_refinements.rb +39 -45
  124. data/lib/sequel/extensions/current_datetime_timestamp.rb +0 -4
  125. data/lib/sequel/extensions/date_arithmetic.rb +7 -7
  126. data/lib/sequel/extensions/duplicate_columns_handler.rb +12 -9
  127. data/lib/sequel/extensions/empty_array_consider_nulls.rb +2 -2
  128. data/lib/sequel/extensions/eval_inspect.rb +4 -11
  129. data/lib/sequel/extensions/freeze_datasets.rb +1 -69
  130. data/lib/sequel/extensions/from_block.rb +1 -35
  131. data/lib/sequel/extensions/graph_each.rb +2 -2
  132. data/lib/sequel/extensions/identifier_mangling.rb +9 -19
  133. data/lib/sequel/extensions/implicit_subquery.rb +2 -2
  134. data/lib/sequel/extensions/inflector.rb +4 -4
  135. data/lib/sequel/extensions/migration.rb +27 -43
  136. data/lib/sequel/extensions/no_auto_literal_strings.rb +2 -84
  137. data/lib/sequel/extensions/null_dataset.rb +2 -8
  138. data/lib/sequel/extensions/pagination.rb +1 -17
  139. data/lib/sequel/extensions/pg_array.rb +20 -189
  140. data/lib/sequel/extensions/pg_extended_date_support.rb +230 -0
  141. data/lib/sequel/extensions/pg_hstore.rb +11 -50
  142. data/lib/sequel/extensions/pg_hstore_ops.rb +2 -2
  143. data/lib/sequel/extensions/pg_inet.rb +3 -16
  144. data/lib/sequel/extensions/pg_interval.rb +1 -20
  145. data/lib/sequel/extensions/pg_json.rb +7 -27
  146. data/lib/sequel/extensions/pg_loose_count.rb +1 -1
  147. data/lib/sequel/extensions/pg_range.rb +6 -121
  148. data/lib/sequel/extensions/pg_range_ops.rb +1 -3
  149. data/lib/sequel/extensions/pg_row.rb +5 -77
  150. data/lib/sequel/extensions/pg_row_ops.rb +2 -13
  151. data/lib/sequel/extensions/query.rb +3 -4
  152. data/lib/sequel/extensions/round_timestamps.rb +0 -6
  153. data/lib/sequel/extensions/schema_dumper.rb +13 -13
  154. data/lib/sequel/extensions/select_remove.rb +3 -3
  155. data/lib/sequel/extensions/split_array_nil.rb +2 -2
  156. data/lib/sequel/extensions/sql_comments.rb +2 -2
  157. data/lib/sequel/extensions/string_agg.rb +11 -8
  158. data/lib/sequel/extensions/symbol_aref.rb +6 -20
  159. data/lib/sequel/extensions/synchronize_sql.rb +45 -0
  160. data/lib/sequel/model/associations.rb +129 -131
  161. data/lib/sequel/model/base.rb +133 -731
  162. data/lib/sequel/model/default_inflections.rb +1 -1
  163. data/lib/sequel/model/errors.rb +0 -3
  164. data/lib/sequel/model/exceptions.rb +2 -6
  165. data/lib/sequel/model/inflections.rb +1 -26
  166. data/lib/sequel/model/plugins.rb +1 -0
  167. data/lib/sequel/model.rb +27 -62
  168. data/lib/sequel/plugins/active_model.rb +2 -5
  169. data/lib/sequel/plugins/association_dependencies.rb +15 -15
  170. data/lib/sequel/plugins/association_pks.rb +14 -28
  171. data/lib/sequel/plugins/association_proxies.rb +6 -7
  172. data/lib/sequel/plugins/auto_validations.rb +4 -4
  173. data/lib/sequel/plugins/before_after_save.rb +0 -43
  174. data/lib/sequel/plugins/blacklist_security.rb +9 -8
  175. data/lib/sequel/plugins/boolean_readers.rb +3 -3
  176. data/lib/sequel/plugins/boolean_subsets.rb +2 -2
  177. data/lib/sequel/plugins/caching.rb +5 -5
  178. data/lib/sequel/plugins/class_table_inheritance.rb +71 -102
  179. data/lib/sequel/plugins/column_conflicts.rb +2 -2
  180. data/lib/sequel/plugins/column_select.rb +2 -2
  181. data/lib/sequel/plugins/composition.rb +15 -24
  182. data/lib/sequel/plugins/constraint_validations.rb +4 -3
  183. data/lib/sequel/plugins/csv_serializer.rb +13 -20
  184. data/lib/sequel/plugins/dataset_associations.rb +2 -2
  185. data/lib/sequel/plugins/def_dataset_method.rb +5 -5
  186. data/lib/sequel/plugins/defaults_setter.rb +1 -1
  187. data/lib/sequel/plugins/delay_add_association.rb +1 -1
  188. data/lib/sequel/plugins/finder.rb +16 -10
  189. data/lib/sequel/plugins/force_encoding.rb +1 -7
  190. data/lib/sequel/plugins/hook_class_methods.rb +4 -106
  191. data/lib/sequel/plugins/input_transformer.rb +10 -11
  192. data/lib/sequel/plugins/insert_returning_select.rb +1 -9
  193. data/lib/sequel/plugins/instance_filters.rb +5 -5
  194. data/lib/sequel/plugins/instance_hooks.rb +7 -52
  195. data/lib/sequel/plugins/inverted_subsets.rb +3 -1
  196. data/lib/sequel/plugins/json_serializer.rb +19 -19
  197. data/lib/sequel/plugins/lazy_attributes.rb +1 -10
  198. data/lib/sequel/plugins/list.rb +6 -6
  199. data/lib/sequel/plugins/many_through_many.rb +11 -8
  200. data/lib/sequel/plugins/mssql_optimistic_locking.rb +3 -3
  201. data/lib/sequel/plugins/nested_attributes.rb +18 -31
  202. data/lib/sequel/plugins/optimistic_locking.rb +3 -3
  203. data/lib/sequel/plugins/pg_array_associations.rb +8 -2
  204. data/lib/sequel/plugins/pg_row.rb +2 -11
  205. data/lib/sequel/plugins/prepared_statements.rb +13 -66
  206. data/lib/sequel/plugins/prepared_statements_safe.rb +1 -1
  207. data/lib/sequel/plugins/rcte_tree.rb +7 -7
  208. data/lib/sequel/plugins/serialization.rb +15 -33
  209. data/lib/sequel/plugins/serialization_modification_detection.rb +1 -1
  210. data/lib/sequel/plugins/sharding.rb +2 -8
  211. data/lib/sequel/plugins/single_table_inheritance.rb +10 -13
  212. data/lib/sequel/plugins/skip_create_refresh.rb +3 -3
  213. data/lib/sequel/plugins/static_cache.rb +8 -9
  214. data/lib/sequel/plugins/string_stripper.rb +3 -3
  215. data/lib/sequel/plugins/subclasses.rb +1 -1
  216. data/lib/sequel/plugins/subset_conditions.rb +2 -2
  217. data/lib/sequel/plugins/table_select.rb +2 -2
  218. data/lib/sequel/plugins/tactical_eager_loading.rb +4 -4
  219. data/lib/sequel/plugins/timestamps.rb +6 -7
  220. data/lib/sequel/plugins/touch.rb +4 -8
  221. data/lib/sequel/plugins/tree.rb +3 -3
  222. data/lib/sequel/plugins/typecast_on_load.rb +2 -2
  223. data/lib/sequel/plugins/unlimited_update.rb +1 -7
  224. data/lib/sequel/plugins/update_or_create.rb +3 -3
  225. data/lib/sequel/plugins/update_refresh.rb +3 -3
  226. data/lib/sequel/plugins/uuid.rb +7 -11
  227. data/lib/sequel/plugins/validation_class_methods.rb +10 -9
  228. data/lib/sequel/plugins/validation_contexts.rb +4 -4
  229. data/lib/sequel/plugins/validation_helpers.rb +26 -25
  230. data/lib/sequel/plugins/whitelist_security.rb +13 -9
  231. data/lib/sequel/plugins/xml_serializer.rb +24 -25
  232. data/lib/sequel/sql.rb +145 -276
  233. data/lib/sequel/timezones.rb +8 -23
  234. data/lib/sequel/version.rb +2 -2
  235. data/lib/sequel.rb +1 -1
  236. data/spec/adapter_spec.rb +1 -1
  237. data/spec/adapters/db2_spec.rb +2 -103
  238. data/spec/adapters/mssql_spec.rb +89 -68
  239. data/spec/adapters/mysql_spec.rb +111 -478
  240. data/spec/adapters/oracle_spec.rb +1 -9
  241. data/spec/adapters/postgres_spec.rb +459 -664
  242. data/spec/adapters/spec_helper.rb +12 -31
  243. data/spec/adapters/sqlanywhere_spec.rb +2 -77
  244. data/spec/adapters/sqlite_spec.rb +8 -146
  245. data/spec/bin_spec.rb +11 -16
  246. data/spec/core/connection_pool_spec.rb +173 -74
  247. data/spec/core/database_spec.rb +96 -244
  248. data/spec/core/dataset_spec.rb +99 -414
  249. data/spec/core/deprecated_spec.rb +3 -3
  250. data/spec/core/expression_filters_spec.rb +37 -144
  251. data/spec/core/mock_adapter_spec.rb +241 -4
  252. data/spec/core/object_graph_spec.rb +11 -60
  253. data/spec/core/placeholder_literalizer_spec.rb +1 -14
  254. data/spec/core/schema_generator_spec.rb +51 -40
  255. data/spec/core/schema_spec.rb +88 -77
  256. data/spec/core/spec_helper.rb +6 -24
  257. data/spec/core/version_spec.rb +1 -1
  258. data/spec/core_extensions_spec.rb +7 -83
  259. data/spec/core_model_spec.rb +2 -2
  260. data/spec/deprecation_helper.rb +2 -14
  261. data/spec/extensions/accessed_columns_spec.rb +1 -1
  262. data/spec/extensions/active_model_spec.rb +3 -3
  263. data/spec/extensions/after_initialize_spec.rb +1 -1
  264. data/spec/extensions/arbitrary_servers_spec.rb +2 -2
  265. data/spec/extensions/association_dependencies_spec.rb +1 -1
  266. data/spec/extensions/association_pks_spec.rb +30 -92
  267. data/spec/extensions/association_proxies_spec.rb +1 -1
  268. data/spec/extensions/auto_literal_strings_spec.rb +1 -12
  269. data/spec/extensions/auto_validations_spec.rb +1 -1
  270. data/spec/extensions/blacklist_security_spec.rb +1 -1
  271. data/spec/extensions/blank_spec.rb +1 -1
  272. data/spec/extensions/boolean_readers_spec.rb +1 -1
  273. data/spec/extensions/boolean_subsets_spec.rb +1 -1
  274. data/spec/extensions/caching_spec.rb +1 -1
  275. data/spec/extensions/class_table_inheritance_spec.rb +53 -1118
  276. data/spec/extensions/column_conflicts_spec.rb +1 -1
  277. data/spec/extensions/column_select_spec.rb +4 -4
  278. data/spec/extensions/columns_introspection_spec.rb +1 -1
  279. data/spec/extensions/columns_updated_spec.rb +1 -1
  280. data/spec/extensions/composition_spec.rb +8 -30
  281. data/spec/extensions/connection_expiration_spec.rb +3 -3
  282. data/spec/extensions/connection_validator_spec.rb +3 -3
  283. data/spec/extensions/constraint_validations_plugin_spec.rb +1 -1
  284. data/spec/extensions/constraint_validations_spec.rb +1 -1
  285. data/spec/extensions/core_refinements_spec.rb +1 -3
  286. data/spec/extensions/csv_serializer_spec.rb +4 -9
  287. data/spec/extensions/current_datetime_timestamp_spec.rb +1 -1
  288. data/spec/extensions/dataset_associations_spec.rb +2 -1
  289. data/spec/extensions/dataset_source_alias_spec.rb +1 -1
  290. data/spec/extensions/date_arithmetic_spec.rb +3 -3
  291. data/spec/extensions/def_dataset_method_spec.rb +1 -1
  292. data/spec/extensions/defaults_setter_spec.rb +2 -2
  293. data/spec/extensions/delay_add_association_spec.rb +8 -9
  294. data/spec/extensions/dirty_spec.rb +1 -1
  295. data/spec/extensions/duplicate_columns_handler_spec.rb +1 -1
  296. data/spec/extensions/eager_each_spec.rb +2 -2
  297. data/spec/extensions/empty_array_consider_nulls_spec.rb +1 -1
  298. data/spec/extensions/error_splitter_spec.rb +1 -1
  299. data/spec/extensions/error_sql_spec.rb +1 -1
  300. data/spec/extensions/eval_inspect_spec.rb +1 -1
  301. data/spec/extensions/finder_spec.rb +1 -1
  302. data/spec/extensions/force_encoding_spec.rb +2 -5
  303. data/spec/extensions/freeze_datasets_spec.rb +1 -1
  304. data/spec/extensions/graph_each_spec.rb +5 -5
  305. data/spec/extensions/hook_class_methods_spec.rb +1 -194
  306. data/spec/extensions/identifier_mangling_spec.rb +17 -170
  307. data/spec/extensions/implicit_subquery_spec.rb +1 -5
  308. data/spec/extensions/inflector_spec.rb +1 -1
  309. data/spec/extensions/input_transformer_spec.rb +7 -2
  310. data/spec/extensions/insert_returning_select_spec.rb +1 -1
  311. data/spec/extensions/instance_filters_spec.rb +1 -1
  312. data/spec/extensions/instance_hooks_spec.rb +1 -95
  313. data/spec/extensions/inverted_subsets_spec.rb +1 -1
  314. data/spec/extensions/json_serializer_spec.rb +1 -1
  315. data/spec/extensions/lazy_attributes_spec.rb +1 -7
  316. data/spec/extensions/list_spec.rb +5 -6
  317. data/spec/extensions/looser_typecasting_spec.rb +1 -1
  318. data/spec/extensions/many_through_many_spec.rb +25 -33
  319. data/spec/extensions/migration_spec.rb +12 -2
  320. data/spec/extensions/modification_detection_spec.rb +1 -1
  321. data/spec/extensions/mssql_optimistic_locking_spec.rb +1 -1
  322. data/spec/extensions/named_timezones_spec.rb +3 -3
  323. data/spec/extensions/nested_attributes_spec.rb +1 -29
  324. data/spec/extensions/null_dataset_spec.rb +1 -11
  325. data/spec/extensions/optimistic_locking_spec.rb +2 -2
  326. data/spec/extensions/pagination_spec.rb +1 -1
  327. data/spec/extensions/pg_array_associations_spec.rb +22 -26
  328. data/spec/extensions/pg_array_ops_spec.rb +1 -1
  329. data/spec/extensions/pg_array_spec.rb +3 -48
  330. data/spec/extensions/pg_enum_spec.rb +1 -1
  331. data/spec/extensions/pg_extended_date_support_spec.rb +122 -0
  332. data/spec/extensions/pg_hstore_ops_spec.rb +1 -1
  333. data/spec/extensions/pg_hstore_spec.rb +22 -31
  334. data/spec/extensions/pg_inet_ops_spec.rb +1 -1
  335. data/spec/extensions/pg_inet_spec.rb +1 -14
  336. data/spec/extensions/pg_interval_spec.rb +3 -13
  337. data/spec/extensions/pg_json_ops_spec.rb +1 -1
  338. data/spec/extensions/pg_json_spec.rb +1 -13
  339. data/spec/extensions/pg_loose_count_spec.rb +1 -1
  340. data/spec/extensions/pg_range_ops_spec.rb +1 -1
  341. data/spec/extensions/pg_range_spec.rb +3 -88
  342. data/spec/extensions/pg_row_ops_spec.rb +1 -1
  343. data/spec/extensions/pg_row_plugin_spec.rb +1 -1
  344. data/spec/extensions/pg_row_spec.rb +1 -44
  345. data/spec/extensions/pg_static_cache_updater_spec.rb +1 -1
  346. data/spec/extensions/prepared_statements_safe_spec.rb +7 -7
  347. data/spec/extensions/prepared_statements_spec.rb +13 -48
  348. data/spec/extensions/pretty_table_spec.rb +40 -9
  349. data/spec/extensions/query_spec.rb +1 -12
  350. data/spec/extensions/rcte_tree_spec.rb +23 -34
  351. data/spec/extensions/round_timestamps_spec.rb +1 -5
  352. data/spec/extensions/s_spec.rb +1 -1
  353. data/spec/extensions/schema_caching_spec.rb +1 -1
  354. data/spec/extensions/schema_dumper_spec.rb +43 -32
  355. data/spec/extensions/select_remove_spec.rb +1 -1
  356. data/spec/extensions/sequel_4_dataset_methods_spec.rb +1 -1
  357. data/spec/extensions/serialization_modification_detection_spec.rb +1 -1
  358. data/spec/extensions/serialization_spec.rb +5 -17
  359. data/spec/extensions/server_block_spec.rb +1 -1
  360. data/spec/extensions/server_logging_spec.rb +2 -2
  361. data/spec/extensions/sharding_spec.rb +1 -1
  362. data/spec/extensions/shared_caching_spec.rb +1 -28
  363. data/spec/extensions/single_table_inheritance_spec.rb +2 -5
  364. data/spec/extensions/singular_table_names_spec.rb +1 -1
  365. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  366. data/spec/extensions/spec_helper.rb +5 -27
  367. data/spec/extensions/split_array_nil_spec.rb +1 -1
  368. data/spec/extensions/split_values_spec.rb +1 -1
  369. data/spec/extensions/sql_comments_spec.rb +1 -1
  370. data/spec/extensions/sql_expr_spec.rb +1 -1
  371. data/spec/extensions/static_cache_spec.rb +1 -1
  372. data/spec/extensions/string_agg_spec.rb +2 -2
  373. data/spec/extensions/string_date_time_spec.rb +1 -1
  374. data/spec/extensions/string_stripper_spec.rb +1 -1
  375. data/spec/extensions/subclasses_spec.rb +1 -1
  376. data/spec/extensions/subset_conditions_spec.rb +1 -1
  377. data/spec/extensions/symbol_aref_refinement_spec.rb +1 -1
  378. data/spec/extensions/symbol_as_refinement_spec.rb +1 -1
  379. data/spec/extensions/synchronize_sql_spec.rb +124 -0
  380. data/spec/extensions/table_select_spec.rb +4 -4
  381. data/spec/extensions/tactical_eager_loading_spec.rb +1 -6
  382. data/spec/extensions/thread_local_timezones_spec.rb +1 -1
  383. data/spec/extensions/timestamps_spec.rb +5 -7
  384. data/spec/extensions/to_dot_spec.rb +1 -1
  385. data/spec/extensions/touch_spec.rb +1 -1
  386. data/spec/extensions/tree_spec.rb +1 -1
  387. data/spec/extensions/typecast_on_load_spec.rb +1 -1
  388. data/spec/extensions/unlimited_update_spec.rb +1 -1
  389. data/spec/extensions/update_or_create_spec.rb +12 -16
  390. data/spec/extensions/update_primary_key_spec.rb +4 -3
  391. data/spec/extensions/update_refresh_spec.rb +1 -1
  392. data/spec/extensions/uuid_spec.rb +10 -13
  393. data/spec/extensions/validate_associated_spec.rb +1 -1
  394. data/spec/extensions/validation_class_methods_spec.rb +3 -3
  395. data/spec/extensions/validation_contexts_spec.rb +1 -1
  396. data/spec/extensions/validation_helpers_spec.rb +10 -44
  397. data/spec/extensions/whitelist_security_spec.rb +5 -5
  398. data/spec/extensions/xml_serializer_spec.rb +8 -13
  399. data/spec/guards_helper.rb +2 -1
  400. data/spec/integration/associations_test.rb +1 -23
  401. data/spec/integration/database_test.rb +7 -7
  402. data/spec/integration/dataset_test.rb +12 -47
  403. data/spec/integration/eager_loader_test.rb +1 -1
  404. data/spec/integration/migrator_test.rb +1 -1
  405. data/spec/integration/model_test.rb +4 -82
  406. data/spec/integration/plugin_test.rb +7 -23
  407. data/spec/integration/prepared_statement_test.rb +8 -88
  408. data/spec/integration/schema_test.rb +10 -10
  409. data/spec/integration/spec_helper.rb +17 -21
  410. data/spec/integration/timezone_test.rb +5 -5
  411. data/spec/integration/transaction_test.rb +3 -55
  412. data/spec/integration/type_test.rb +9 -9
  413. data/spec/model/association_reflection_spec.rb +24 -9
  414. data/spec/model/associations_spec.rb +124 -303
  415. data/spec/model/base_spec.rb +43 -137
  416. data/spec/model/class_dataset_methods_spec.rb +2 -20
  417. data/spec/model/dataset_methods_spec.rb +1 -20
  418. data/spec/model/eager_loading_spec.rb +48 -17
  419. data/spec/model/hooks_spec.rb +5 -300
  420. data/spec/model/inflector_spec.rb +1 -1
  421. data/spec/model/model_spec.rb +29 -339
  422. data/spec/model/plugins_spec.rb +2 -16
  423. data/spec/model/record_spec.rb +33 -129
  424. data/spec/model/spec_helper.rb +5 -15
  425. data/spec/model/validations_spec.rb +1 -1
  426. data/spec/sequel_warning.rb +1 -12
  427. metadata +19 -65
  428. data/doc/active_record.rdoc +0 -927
  429. data/lib/sequel/adapters/cubrid.rb +0 -160
  430. data/lib/sequel/adapters/do/mysql.rb +0 -69
  431. data/lib/sequel/adapters/do/postgres.rb +0 -46
  432. data/lib/sequel/adapters/do/sqlite3.rb +0 -41
  433. data/lib/sequel/adapters/do.rb +0 -166
  434. data/lib/sequel/adapters/jdbc/as400.rb +0 -92
  435. data/lib/sequel/adapters/jdbc/cubrid.rb +0 -65
  436. data/lib/sequel/adapters/jdbc/firebirdsql.rb +0 -37
  437. data/lib/sequel/adapters/jdbc/informix-sqli.rb +0 -34
  438. data/lib/sequel/adapters/jdbc/jdbcprogress.rb +0 -34
  439. data/lib/sequel/adapters/odbc/progress.rb +0 -12
  440. data/lib/sequel/adapters/shared/cubrid.rb +0 -245
  441. data/lib/sequel/adapters/shared/firebird.rb +0 -261
  442. data/lib/sequel/adapters/shared/informix.rb +0 -63
  443. data/lib/sequel/adapters/shared/progress.rb +0 -40
  444. data/lib/sequel/adapters/swift/mysql.rb +0 -50
  445. data/lib/sequel/adapters/swift/postgres.rb +0 -49
  446. data/lib/sequel/adapters/swift/sqlite.rb +0 -48
  447. data/lib/sequel/adapters/swift.rb +0 -169
  448. data/lib/sequel/adapters/utils/pg_types.rb +0 -4
  449. data/lib/sequel/dataset/mutation.rb +0 -98
  450. data/lib/sequel/extensions/_deprecated_identifier_mangling.rb +0 -117
  451. data/lib/sequel/extensions/empty_array_ignore_nulls.rb +0 -8
  452. data/lib/sequel/extensions/filter_having.rb +0 -65
  453. data/lib/sequel/extensions/hash_aliases.rb +0 -51
  454. data/lib/sequel/extensions/meta_def.rb +0 -37
  455. data/lib/sequel/extensions/query_literals.rb +0 -86
  456. data/lib/sequel/extensions/ruby18_symbol_extensions.rb +0 -26
  457. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +0 -133
  458. data/lib/sequel/extensions/set_overrides.rb +0 -82
  459. data/lib/sequel/no_core_ext.rb +0 -4
  460. data/lib/sequel/plugins/association_autoreloading.rb +0 -11
  461. data/lib/sequel/plugins/identifier_columns.rb +0 -49
  462. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +0 -11
  463. data/lib/sequel/plugins/pg_typecast_on_load.rb +0 -90
  464. data/lib/sequel/plugins/prepared_statements_associations.rb +0 -137
  465. data/lib/sequel/plugins/prepared_statements_with_pk.rb +0 -71
  466. data/lib/sequel/plugins/schema.rb +0 -84
  467. data/lib/sequel/plugins/scissors.rb +0 -37
  468. data/spec/core/dataset_mutation_spec.rb +0 -253
  469. data/spec/extensions/_deprecated_identifier_mangling_spec.rb +0 -314
  470. data/spec/extensions/before_after_save_spec.rb +0 -40
  471. data/spec/extensions/filter_having_spec.rb +0 -42
  472. data/spec/extensions/from_block_spec.rb +0 -21
  473. data/spec/extensions/hash_aliases_spec.rb +0 -26
  474. data/spec/extensions/identifier_columns_spec.rb +0 -19
  475. data/spec/extensions/meta_def_spec.rb +0 -35
  476. data/spec/extensions/no_auto_literal_strings_spec.rb +0 -69
  477. data/spec/extensions/pg_typecast_on_load_spec.rb +0 -70
  478. data/spec/extensions/prepared_statements_associations_spec.rb +0 -212
  479. data/spec/extensions/prepared_statements_with_pk_spec.rb +0 -40
  480. data/spec/extensions/query_literals_spec.rb +0 -185
  481. data/spec/extensions/schema_spec.rb +0 -123
  482. data/spec/extensions/scissors_spec.rb +0 -27
  483. data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -118
  484. data/spec/extensions/set_overrides_spec.rb +0 -75
@@ -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)
@@ -143,6 +145,7 @@ module Sequel
143
145
  rn = ds.row_number_column
144
146
  limit, offset = limit_and_offset
145
147
  ds = ds.unordered.select_append{|o| o.row_number.function.over(:partition=>predicate_key, :order=>ds.opts[:order]).as(rn)}.from_self
148
+ ds = ds.order(rn) if ds.db.database_type == :mysql
146
149
  ds = if !returns_array?
147
150
  ds.where(rn => offset ? offset+1 : 1)
148
151
  elsif offset
@@ -191,7 +194,7 @@ module Sequel
191
194
 
192
195
  # Name symbol for the dataset association method
193
196
  def dataset_method
194
- :"#{self[:name]}_dataset"
197
+ self[:dataset_method]
195
198
  end
196
199
 
197
200
  # Whether the dataset needs a primary key to function, true by default.
@@ -325,12 +328,6 @@ module Sequel
325
328
  false
326
329
  end
327
330
 
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
331
  # Whether to eagerly graph a lazy dataset, true by default. If this
335
332
  # is false, the association won't respect the :eager_graph option
336
333
  # when loading the association for a single record.
@@ -362,6 +359,7 @@ module Sequel
362
359
  finalize_settings.each do |meth, key|
363
360
  next if has_key?(key)
364
361
 
362
+ # Allow calling private methods to make sure caching is done appropriately
365
363
  send(meth)
366
364
  self[key] = cache.delete(key) if cache.has_key?(key)
367
365
  end
@@ -401,7 +399,7 @@ module Sequel
401
399
  end
402
400
  end
403
401
 
404
- # Show which type of reflection this is, and a guess at what line was used to create the
402
+ # Show which type of reflection this is, and a guess at what code was used to create the
405
403
  # association.
406
404
  def inspect
407
405
  o = self[:orig_opts].dup
@@ -450,9 +448,7 @@ module Sequel
450
448
  predicate_key_methods.map{|k| object.get_column_value(k)}
451
449
  end
452
450
 
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.
451
+ # Qualify +col+ with the given table name.
456
452
  def qualify(table, col)
457
453
  transform(col) do |k|
458
454
  case k
@@ -505,7 +501,7 @@ module Sequel
505
501
 
506
502
  # Name symbol for the remove_all_ association method
507
503
  def remove_all_method
508
- :"remove_all_#{self[:name]}"
504
+ self[:remove_all_method]
509
505
  end
510
506
 
511
507
  # Whether associated objects need to be removed from the association before
@@ -516,7 +512,7 @@ module Sequel
516
512
 
517
513
  # Name symbol for the remove_ association method
518
514
  def remove_method
519
- :"remove_#{singularize(self[:name])}"
515
+ self[:remove_method]
520
516
  end
521
517
 
522
518
  # Whether to check that an object to be disassociated is already associated to this object, false by default.
@@ -543,7 +539,7 @@ module Sequel
543
539
 
544
540
  # Name symbol for the setter association method
545
541
  def setter_method
546
- :"#{self[:name]}="
542
+ self[:setter_method]
547
543
  end
548
544
 
549
545
  # The range used for slicing when using the :ruby eager limit strategy.
@@ -556,8 +552,10 @@ module Sequel
556
552
 
557
553
  private
558
554
 
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.
555
+ # If the key exists in the reflection hash, return it.
556
+ # If the key doesn't exist and association reflections are uncached, then yield to get the value.
557
+ # If the key doesn't exist and association reflection are cached, check the cache and return
558
+ # the value if present, or yield to get the value, cache the value, and return it.
561
559
  def cached_fetch(key)
562
560
  fetch(key) do
563
561
  return yield unless h = self[:cache]
@@ -567,7 +565,7 @@ module Sequel
567
565
  end
568
566
  end
569
567
 
570
- # Cache the value at the given key, synchronizing access.
568
+ # Cache the value at the given key if caching.
571
569
  def cached_set(key, value)
572
570
  return unless h = self[:cache]
573
571
  Sequel.synchronize{h[key] = value}
@@ -576,10 +574,10 @@ module Sequel
576
574
  # The base dataset used for the association, before any order/conditions
577
575
  # options have been applied.
578
576
  def _associated_dataset
579
- associated_class.dataset.clone
577
+ associated_class.dataset
580
578
  end
581
579
 
582
- # Whether for the reciprocal type for the given association can not be
580
+ # Whether for the reciprocal type for the given association cannot be
583
581
  # known in advantage, false by default.
584
582
  def ambiguous_reciprocal_type?
585
583
  false
@@ -1106,7 +1104,7 @@ module Sequel
1106
1104
  end
1107
1105
 
1108
1106
  # 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
1107
+ # the database supports them, and either the associated class has a non-composite primary key
1110
1108
  # or the database supports multiple columns in IN.
1111
1109
  def true_eager_graph_limit_strategy
1112
1110
  r = super
@@ -1451,8 +1449,6 @@ module Sequel
1451
1449
 
1452
1450
  # This module contains methods added to all association datasets
1453
1451
  module AssociationDatasetMethods
1454
- Dataset.def_deprecated_opts_setter(self, :model_object, :association_reflection)
1455
-
1456
1452
  # The model object that created the association dataset
1457
1453
  def model_object
1458
1454
  @opts[:model_object]
@@ -1508,7 +1504,7 @@ module Sequel
1508
1504
  # Project.associations
1509
1505
  # => [:portfolio, :milestones]
1510
1506
  # Project.association_reflection(:portfolio)
1511
- # => {:type => :many_to_one, :name => :portfolio, ...}
1507
+ # => #<Sequel::Model::Associations::ManyToOneAssociationReflection Project.many_to_one :portfolio>
1512
1508
  #
1513
1509
  # Associations should not have the same names as any of the columns in the
1514
1510
  # model's current table they reference. If you are dealing with an existing schema that
@@ -1530,7 +1526,7 @@ module Sequel
1530
1526
 
1531
1527
  # Whether association metadata should be cached in the association reflection. If not cached, it will be computed
1532
1528
  # 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
1529
+ # setting this will make sure that if an associated class is removed or modified, this class will not have a reference to
1534
1530
  # the previous class.
1535
1531
  attr_accessor :cache_associations
1536
1532
 
@@ -1605,7 +1601,7 @@ module Sequel
1605
1601
  # singularized unless the type is :many_to_one, :one_to_one, or one_through_one). If this is specified
1606
1602
  # as a string or symbol, you must specify the full class name (e.g. "::SomeModule::MyModel").
1607
1603
  # :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>.)
1604
+ # the class. <tt>class: 'Foo', class_namespace: 'Bar'</tt> looks for <tt>::Bar::Foo</tt>.)
1609
1605
  # :clearer :: Proc used to define the private _remove_all_* method for doing the database work
1610
1606
  # to remove all objects associated to the current object (*_to_many assocations).
1611
1607
  # :clone :: Merge the current options and block into the options and block used in defining
@@ -1678,8 +1674,7 @@ module Sequel
1678
1674
  # :order_eager_graph :: Whether to add the association's order to the graphed dataset's order when graphing
1679
1675
  # via +eager_graph+. Defaults to true, so set to false to disable.
1680
1676
  # :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.
1677
+ # or add_/remove_/remove_all_ methods (for one_to_many and many_to_many associations).
1683
1678
  # :reciprocal :: the symbol name of the reciprocal association,
1684
1679
  # if it exists. By default, Sequel will try to determine it by looking at the
1685
1680
  # associated model's assocations for a association that matches
@@ -1710,7 +1705,7 @@ module Sequel
1710
1705
  # array of symbols for a composite key association.
1711
1706
  # :primary_key_method :: the method symbol or array of method symbols to call on the associated
1712
1707
  # 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
1708
+ # :qualify :: Whether to use qualified primary keys when loading the association. The default
1714
1709
  # is true, so you must set to false to not qualify. Qualification rarely causes
1715
1710
  # problems, but it's necessary to disable in some cases, such as when you are doing
1716
1711
  # a JOIN USING operation on the column on Oracle.
@@ -1803,10 +1798,6 @@ module Sequel
1803
1798
  end
1804
1799
 
1805
1800
  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
1801
  opts[:graph_join_type] ||= :left_outer
1811
1802
  opts[:order_eager_graph] = true unless opts.include?(:order_eager_graph)
1812
1803
  conds = opts[:conditions]
@@ -1814,9 +1805,15 @@ module Sequel
1814
1805
  opts[:graph_conditions] = conds if !opts.include?(:graph_conditions) and Sequel.condition_specifier?(conds)
1815
1806
  opts[:graph_conditions] = opts.fetch(:graph_conditions, []).to_a
1816
1807
  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])
1808
+ [:before_add, :before_remove, :after_add, :after_remove, :after_load, :before_set, :after_set].each do |cb_type|
1809
+ opts[cb_type] = Array(opts[cb_type]) if opts[cb_type]
1810
+ end
1811
+
1812
+ if opts[:extend]
1813
+ opts[:extend] = Array(opts[:extend])
1814
+ opts[:reverse_extend] = opts[:extend].reverse
1819
1815
  end
1816
+
1820
1817
  late_binding_class_option(opts, opts.returns_array? ? singularize(name) : name)
1821
1818
 
1822
1819
  # Remove :class entry if it exists and is nil, to work with cached_fetch
@@ -1877,7 +1874,7 @@ module Sequel
1877
1874
  associate(:many_to_one, name, opts, &block)
1878
1875
  end
1879
1876
 
1880
- # Shortcut for adding a one_through_one association, see #associate.
1877
+ # Shortcut for adding a one_through_one association, see #associate
1881
1878
  def one_through_one(name, opts=OPTS, &block)
1882
1879
  associate(:one_through_one, name, opts, &block)
1883
1880
  end
@@ -1887,7 +1884,7 @@ module Sequel
1887
1884
  associate(:one_to_many, name, opts, &block)
1888
1885
  end
1889
1886
 
1890
- # Shortcut for adding a one_to_one association, see #associate.
1887
+ # Shortcut for adding a one_to_one association, see #associate
1891
1888
  def one_to_one(name, opts=OPTS, &block)
1892
1889
  associate(:one_to_one, name, opts, &block)
1893
1890
  end
@@ -1918,14 +1915,29 @@ module Sequel
1918
1915
 
1919
1916
  # Adds the association method to the association methods module.
1920
1917
  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)
1918
+ association_module_def(opts.association_method, opts) do |dynamic_opts=OPTS, &block|
1919
+ load_associated_objects(opts, dynamic_opts, &block)
1924
1920
  end
1925
1921
  end
1926
1922
 
1927
1923
  # Define all of the association instance methods for this association.
1928
1924
  def def_association_instance_methods(opts)
1925
+ # Always set the method names in the association reflection, even if they
1926
+ # are not used, for backwards compatibility.
1927
+ opts[:dataset_method] = :"#{opts[:name]}_dataset"
1928
+ if opts.returns_array?
1929
+ sname = singularize(opts[:name])
1930
+ opts[:_add_method] = :"_add_#{sname}"
1931
+ opts[:add_method] = :"add_#{sname}"
1932
+ opts[:_remove_method] = :"_remove_#{sname}"
1933
+ opts[:remove_method] = :"remove_#{sname}"
1934
+ opts[:_remove_all_method] = :"_remove_all_#{opts[:name]}"
1935
+ opts[:remove_all_method] = :"remove_all_#{opts[:name]}"
1936
+ else
1937
+ opts[:_setter_method] = :"_#{opts[:name]}="
1938
+ opts[:setter_method] = :"#{opts[:name]}="
1939
+ end
1940
+
1929
1941
  association_module_def(opts.dataset_method, opts){_dataset(opts)}
1930
1942
  def_association_method(opts)
1931
1943
 
@@ -1933,23 +1945,23 @@ module Sequel
1933
1945
 
1934
1946
  if opts[:setter] && opts[:_setter]
1935
1947
  # 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])
1948
+ association_module_private_def(opts[:_setter_method], opts, &opts[:setter])
1949
+ association_module_def(opts[:setter_method], opts, &opts[:_setter])
1938
1950
  end
1939
1951
 
1940
1952
  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)}
1953
+ association_module_private_def(opts[:_add_method], opts, &adder)
1954
+ association_module_def(opts[:add_method], opts){|o,*args| add_associated_object(opts, o, *args)}
1943
1955
  end
1944
1956
 
1945
1957
  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)}
1958
+ association_module_private_def(opts[:_remove_method], opts, &remover)
1959
+ association_module_def(opts[:remove_method], opts){|o,*args| remove_associated_object(opts, o, *args)}
1948
1960
  end
1949
1961
 
1950
1962
  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)}
1963
+ association_module_private_def(opts[:_remove_all_method], opts, &clearer)
1964
+ association_module_def(opts[:remove_all_method], opts){|*args| remove_all_associated_objects(opts, *args)}
1953
1965
  end
1954
1966
  end
1955
1967
 
@@ -1976,7 +1988,10 @@ module Sequel
1976
1988
  join_table = (opts[:join_table] ||= opts.default_join_table)
1977
1989
  opts[:left_key_alias] ||= opts.default_associated_key_alias
1978
1990
  opts[:graph_join_table_join_type] ||= opts[:graph_join_type]
1979
- opts[:after_load].unshift(:array_uniq!) if opts[:uniq]
1991
+ if opts[:uniq]
1992
+ opts[:after_load] ||= []
1993
+ opts[:after_load].unshift(:array_uniq!)
1994
+ end
1980
1995
  opts[:dataset] ||= opts.association_dataset_proc
1981
1996
  opts[:eager_loader] ||= opts.method(:default_eager_loader)
1982
1997
 
@@ -2273,7 +2288,7 @@ module Sequel
2273
2288
 
2274
2289
  # Return a dataset for the association after applying any dynamic callback.
2275
2290
  def _associated_dataset(opts, dynamic_opts)
2276
- ds = send(opts.dataset_method)
2291
+ ds = public_send(opts.dataset_method)
2277
2292
  if callback = dynamic_opts[:callback]
2278
2293
  ds = callback.call(ds)
2279
2294
  end
@@ -2353,7 +2368,8 @@ module Sequel
2353
2368
  raise(Sequel::Error, "model object #{inspect} does not have a primary key") if opts.dataset_need_primary_key? && !pk
2354
2369
  ensure_associated_primary_key(opts, o, *args)
2355
2370
  return if run_association_callbacks(opts, :before_add, o) == false
2356
- return if !send(opts._add_method, o, *args) && opts.handle_silent_modification_failure?
2371
+ # Allow calling private _add method
2372
+ return if !send(opts[:_add_method], o, *args) && opts.handle_silent_modification_failure?
2357
2373
  if array = associations[opts[:name]] and !array.include?(o)
2358
2374
  array.push(o)
2359
2375
  end
@@ -2407,28 +2423,10 @@ module Sequel
2407
2423
  self
2408
2424
  end
2409
2425
 
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.
2426
+ # If a block is given, assign it as the :callback option in the hash, and return the hash.
2414
2427
  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?
2428
+ if block
2429
+ dynamic_opts = Hash[dynamic_opts]
2432
2430
  dynamic_opts[:callback] = block
2433
2431
  end
2434
2432
 
@@ -2436,7 +2434,7 @@ module Sequel
2436
2434
  end
2437
2435
 
2438
2436
  # Load the associated objects using the dataset, handling callbacks, reciprocals, and caching.
2439
- def load_associated_objects(opts, dynamic_opts=nil, &block)
2437
+ def load_associated_objects(opts, dynamic_opts, &block)
2440
2438
  dynamic_opts = load_association_objects_options(dynamic_opts, &block)
2441
2439
  name = opts[:name]
2442
2440
  if associations.include?(name) && !dynamic_opts[:callback] && !dynamic_opts[:reload]
@@ -2490,7 +2488,8 @@ module Sequel
2490
2488
  # Remove all associated objects from the given association
2491
2489
  def remove_all_associated_objects(opts, *args)
2492
2490
  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)
2491
+ # Allow calling private _remove_all method
2492
+ send(opts[:_remove_all_method], *args)
2494
2493
  ret = associations[opts[:name]].each{|o| remove_reciprocal_object(opts, o)} if associations.include?(opts[:name])
2495
2494
  associations[opts[:name]] = []
2496
2495
  ret
@@ -2503,13 +2502,14 @@ module Sequel
2503
2502
  o = remove_check_existing_object_from_pk(opts, o, *args)
2504
2503
  elsif !o.is_a?(klass)
2505
2504
  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?
2505
+ elsif opts.remove_should_check_existing? && public_send(opts.dataset_method).where(o.pk_hash).empty?
2507
2506
  raise(Sequel::Error, "associated object #{o.inspect} is not currently associated to #{inspect}")
2508
2507
  end
2509
2508
  raise(Sequel::Error, "model object #{inspect} does not have a primary key") if opts.dataset_need_primary_key? && !pk
2510
2509
  raise(Sequel::Error, "associated object #{o.inspect} does not have a primary key") if opts.need_associated_primary_key? && !o.pk
2511
2510
  return if run_association_callbacks(opts, :before_remove, o) == false
2512
- return if !send(opts._remove_method, o, *args) && opts.handle_silent_modification_failure?
2511
+ # Allow calling private _remove method
2512
+ return if !send(opts[:_remove_method], o, *args) && opts.handle_silent_modification_failure?
2513
2513
  associations[opts[:name]].delete_if{|x| o === x} if associations.include?(opts[:name])
2514
2514
  remove_reciprocal_object(opts, o)
2515
2515
  run_association_callbacks(opts, :after_remove, o)
@@ -2522,7 +2522,7 @@ module Sequel
2522
2522
  def remove_check_existing_object_from_pk(opts, o, *args)
2523
2523
  key = o
2524
2524
  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)
2525
+ 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
2526
  o
2527
2527
  end
2528
2528
 
@@ -2540,30 +2540,28 @@ module Sequel
2540
2540
 
2541
2541
  # Run the callback for the association with the object.
2542
2542
  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")
2543
+ return unless cbs = reflection[callback_type]
2544
+
2545
+ begin
2546
+ cbs.each do |cb|
2547
+ case cb
2548
+ when Symbol
2549
+ # Allow calling private methods in association callbacks
2550
+ send(cb, object)
2551
+ when Proc
2552
+ cb.call(self, object)
2553
+ else
2554
+ raise Error, "callbacks should either be Procs or Symbols"
2555
+ end
2562
2556
  end
2557
+ rescue HookFailed
2558
+ # The reason we automatically set raise_error for singular associations is that
2559
+ # assignment in ruby always returns the argument instead of the result of the
2560
+ # method, so we can't return nil to signal that the association callback prevented
2561
+ # the modification
2562
+ return false unless raise_on_save_failure || !reflection.returns_array?
2563
+ raise
2563
2564
  end
2564
- rescue HookFailed
2565
- return false unless raise_error
2566
- raise
2567
2565
  end
2568
2566
 
2569
2567
  # Set the given object as the associated object for the given *_to_one association reflection
@@ -2572,7 +2570,8 @@ module Sequel
2572
2570
  return if a && a == o && !set_associated_object_if_same?
2573
2571
  run_association_callbacks(opts, :before_set, o)
2574
2572
  remove_reciprocal_object(opts, a) if a
2575
- send(opts._setter_method, o)
2573
+ # Allow calling private _setter method
2574
+ send(opts[:_setter_method], o)
2576
2575
  associations[opts[:name]] = o
2577
2576
  add_reciprocal_object(opts, o) if o
2578
2577
  run_association_callbacks(opts, :after_set, o)
@@ -2630,37 +2629,35 @@ module Sequel
2630
2629
  # Album.eager_graph(:artist, :genre).all
2631
2630
  # Album.eager(:artist).eager(:genre).all
2632
2631
  # 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
2632
+ # Artist.eager(albums: :tracks).all
2633
+ # Artist.eager_graph(albums: :tracks).all
2634
+ # Artist.eager(albums: {tracks: :genre}).all
2635
+ # Artist.eager_graph(albums: {tracks: :genre}).all
2637
2636
  #
2638
2637
  # You can also pass a callback as a hash value in order to customize the dataset being
2639
2638
  # eager loaded at query time, analogous to the way the :eager_block association option
2640
2639
  # allows you to customize it at association definition time. For example,
2641
2640
  # if you wanted artists with their albums since 1990:
2642
2641
  #
2643
- # Artist.eager(:albums => proc{|ds| ds.where{year > 1990}})
2642
+ # Artist.eager(albums: proc{|ds| ds.where{year > 1990}})
2644
2643
  #
2645
2644
  # Or if you needed albums and their artist's name only, using a single query:
2646
2645
  #
2647
- # Albums.eager_graph(:artist => proc{|ds| ds.select(:name)})
2646
+ # Albums.eager_graph(artist: proc{|ds| ds.select(:name)})
2648
2647
  #
2649
2648
  # To cascade eager loading while using a callback, you substitute the cascaded
2650
2649
  # associations with a single entry hash that has the proc callback as the key and
2651
2650
  # the cascaded associations as the value. This will load artists with their albums
2652
2651
  # since 1990, and also the tracks on those albums and the genre for those tracks:
2653
2652
  #
2654
- # Artist.eager(:albums => {proc{|ds| ds.where{year > 1990}}=>{:tracks => :genre}})
2653
+ # Artist.eager(albums: {proc{|ds| ds.where{year > 1990}}=>{tracks: :genre}})
2655
2654
  module DatasetMethods
2656
- Sequel::Dataset.def_mutation_method(:eager, :eager_graph, :module=>self)
2657
-
2658
2655
  %w'inner left right full'.each do |type|
2659
- class_eval <<END, __FILE__, __LINE__+1
2656
+ class_eval(<<-END, __FILE__, __LINE__+1)
2660
2657
  def association_#{type}_join(*associations)
2661
2658
  _association_join(:#{type}, associations)
2662
2659
  end
2663
- END
2660
+ END
2664
2661
  end
2665
2662
 
2666
2663
  # Adds one or more INNER JOINs to the existing dataset using the keys and conditions
@@ -2741,7 +2738,7 @@ END
2741
2738
  # it avoids problems such as aliasing conflicts and creating cartesian product
2742
2739
  # result sets if multiple one_to_many or many_to_many eager associations are requested.
2743
2740
  #
2744
- # One limitation of using this method is that you cannot filter the dataset
2741
+ # One limitation of using this method is that you cannot filter the current dataset
2745
2742
  # based on values of columns in an associated table, since the associations are loaded
2746
2743
  # in separate queries. To do that you need to load all associations in the
2747
2744
  # same query, and extract an object graph from the results of that query. If you
@@ -2758,7 +2755,8 @@ END
2758
2755
  end
2759
2756
 
2760
2757
  # 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.
2758
+ # method should only be used if you need to filter or order based on columns in associated tables,
2759
+ # or if you have done comparative benchmarking it and determined it is faster.
2762
2760
  #
2763
2761
  # This method uses <tt>Dataset#graph</tt> to create appropriate aliases for columns in all the
2764
2762
  # tables. Then it uses the graph's metadata to build the associations from the single hash, and
@@ -2766,7 +2764,7 @@ END
2766
2764
  #
2767
2765
  # Be very careful when using this with multiple one_to_many or many_to_many associations, as you can
2768
2766
  # 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.
2767
+ # make sure your filters are narrow if the datasets are large.
2770
2768
  #
2771
2769
  # Each association's order, if defined, is respected. +eager_graph+ probably
2772
2770
  # won't work correctly on a limited dataset, unless you are
@@ -2890,7 +2888,7 @@ END
2890
2888
  limit_strategy = r.eager_graph_limit_strategy(local_opts[:limit_strategy])
2891
2889
 
2892
2890
  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]
2891
+ 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
2892
  end
2895
2893
 
2896
2894
  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 +2980,7 @@ END
2982
2980
  # Return an expression for filtering by the given association reflection and associated object.
2983
2981
  def association_filter_expression(op, ref, obj)
2984
2982
  meth = :"#{ref[:type]}_association_filter_expression"
2983
+ # Allow calling private association specific method to get filter expression
2985
2984
  send(meth, op, ref, obj) if respond_to?(meth, true)
2986
2985
  end
2987
2986
 
@@ -3042,10 +3041,9 @@ END
3042
3041
  # Eagerly load all specified associations
3043
3042
  def eager_load(a, eager_assoc=@opts[:eager])
3044
3043
  return if a.empty?
3045
- # Key is foreign/primary key name symbol
3044
+ # Key is foreign/primary key name symbol.
3046
3045
  # 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
3046
+ # and values being an array of current model objects with that specific foreign/primary key
3049
3047
  key_hash = {}
3050
3048
  # Reflections for all associations to eager load
3051
3049
  reflections = eager_assoc.keys.map{|assoc| model.association_reflection(assoc) || (raise Sequel::UndefinedAssociation, "Model: #{self}, Association: #{assoc}")}
@@ -3088,7 +3086,7 @@ END
3088
3086
  eager_block, associations = pr_assoc
3089
3087
  end
3090
3088
  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?
3089
+ a.each{|object| object.send(:run_association_callbacks, r, :after_load, object.associations[r[:name]])} if r[:after_load]
3092
3090
  end
3093
3091
  end
3094
3092
 
@@ -3220,7 +3218,7 @@ END
3220
3218
  after_load_map = @after_load_map = {}
3221
3219
  reflection_map.each do |k, v|
3222
3220
  alias_map[k] = v[:name]
3223
- after_load_map[k] = v[:after_load] unless v[:after_load].empty?
3221
+ after_load_map[k] = v[:after_load] if v[:after_load]
3224
3222
  type_map[k] = if v.returns_array?
3225
3223
  true
3226
3224
  elsif (limit_and_offset = limit_map[k]) && !limit_and_offset.last.nil?
@@ -3261,7 +3259,7 @@ END
3261
3259
  @records_map = records_map
3262
3260
 
3263
3261
  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
3262
+ column_aliases = opts[:graph][:column_aliases]
3265
3263
  primary_keys = {}
3266
3264
  column_maps = {}
3267
3265
  models = {}
@@ -3383,7 +3381,7 @@ END
3383
3381
  # Return a suitable hash key for any subhash +h+, which is an array of values by column order.
3384
3382
  # This is only used if the primary key cannot be used.
3385
3383
  def hkey(h)
3386
- h.sort_by{|x| x[0].to_s}
3384
+ h.sort_by{|x| x[0]}
3387
3385
  end
3388
3386
 
3389
3387
  # Return the subhash for the master table by parsing the values out of the main hash +h+
@@ -3428,7 +3426,7 @@ END
3428
3426
  records.each do |record|
3429
3427
  dependency_map.each do |ta, deps|
3430
3428
  assoc_name = alias_map[ta]
3431
- list = record.send(assoc_name)
3429
+ list = record.public_send(assoc_name)
3432
3430
  rec_list = if type_map[ta]
3433
3431
  list.uniq!
3434
3432
  if lo = limit_map[ta]