sequel 3.21.0 → 3.39.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 (352) hide show
  1. data/CHANGELOG +1061 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +103 -63
  4. data/Rakefile +59 -27
  5. data/bin/sequel +50 -26
  6. data/doc/active_record.rdoc +67 -51
  7. data/doc/advanced_associations.rdoc +189 -75
  8. data/doc/association_basics.rdoc +327 -79
  9. data/doc/cheat_sheet.rdoc +21 -21
  10. data/doc/core_extensions.rdoc +374 -0
  11. data/doc/dataset_basics.rdoc +10 -10
  12. data/doc/dataset_filtering.rdoc +54 -42
  13. data/doc/mass_assignment.rdoc +56 -0
  14. data/doc/migration.rdoc +89 -557
  15. data/doc/model_hooks.rdoc +80 -29
  16. data/doc/object_model.rdoc +547 -0
  17. data/doc/opening_databases.rdoc +114 -53
  18. data/doc/prepared_statements.rdoc +41 -15
  19. data/doc/querying.rdoc +137 -56
  20. data/doc/reflection.rdoc +36 -10
  21. data/doc/release_notes/3.22.0.txt +39 -0
  22. data/doc/release_notes/3.23.0.txt +172 -0
  23. data/doc/release_notes/3.24.0.txt +420 -0
  24. data/doc/release_notes/3.25.0.txt +88 -0
  25. data/doc/release_notes/3.26.0.txt +88 -0
  26. data/doc/release_notes/3.27.0.txt +82 -0
  27. data/doc/release_notes/3.28.0.txt +304 -0
  28. data/doc/release_notes/3.29.0.txt +459 -0
  29. data/doc/release_notes/3.30.0.txt +135 -0
  30. data/doc/release_notes/3.31.0.txt +146 -0
  31. data/doc/release_notes/3.32.0.txt +202 -0
  32. data/doc/release_notes/3.33.0.txt +157 -0
  33. data/doc/release_notes/3.34.0.txt +671 -0
  34. data/doc/release_notes/3.35.0.txt +144 -0
  35. data/doc/release_notes/3.36.0.txt +245 -0
  36. data/doc/release_notes/3.37.0.txt +338 -0
  37. data/doc/release_notes/3.38.0.txt +234 -0
  38. data/doc/release_notes/3.39.0.txt +237 -0
  39. data/doc/schema_modification.rdoc +585 -0
  40. data/doc/sharding.rdoc +99 -8
  41. data/doc/sql.rdoc +154 -112
  42. data/doc/testing.rdoc +169 -0
  43. data/doc/thread_safety.rdoc +17 -0
  44. data/doc/transactions.rdoc +137 -0
  45. data/doc/validations.rdoc +1 -1
  46. data/doc/virtual_rows.rdoc +78 -43
  47. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  48. data/lib/sequel/adapters/ado.rb +40 -18
  49. data/lib/sequel/adapters/amalgalite.rb +17 -9
  50. data/lib/sequel/adapters/db2.rb +175 -86
  51. data/lib/sequel/adapters/dbi.rb +15 -15
  52. data/lib/sequel/adapters/do/mysql.rb +17 -11
  53. data/lib/sequel/adapters/do/postgres.rb +2 -61
  54. data/lib/sequel/adapters/do/sqlite.rb +0 -10
  55. data/lib/sequel/adapters/do.rb +18 -36
  56. data/lib/sequel/adapters/firebird.rb +27 -208
  57. data/lib/sequel/adapters/ibmdb.rb +453 -0
  58. data/lib/sequel/adapters/informix.rb +6 -23
  59. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  60. data/lib/sequel/adapters/jdbc/db2.rb +56 -0
  61. data/lib/sequel/adapters/jdbc/derby.rb +325 -0
  62. data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
  63. data/lib/sequel/adapters/jdbc/h2.rb +73 -31
  64. data/lib/sequel/adapters/jdbc/hsqldb.rb +184 -0
  65. data/lib/sequel/adapters/jdbc/informix.rb +21 -0
  66. data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
  67. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  68. data/lib/sequel/adapters/jdbc/mysql.rb +7 -24
  69. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  70. data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
  71. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  72. data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
  73. data/lib/sequel/adapters/jdbc/sqlserver.rb +66 -0
  74. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  75. data/lib/sequel/adapters/jdbc.rb +279 -97
  76. data/lib/sequel/adapters/mock.rb +372 -0
  77. data/lib/sequel/adapters/mysql.rb +125 -222
  78. data/lib/sequel/adapters/mysql2.rb +65 -56
  79. data/lib/sequel/adapters/odbc/mssql.rb +17 -9
  80. data/lib/sequel/adapters/odbc.rb +28 -9
  81. data/lib/sequel/adapters/openbase.rb +3 -5
  82. data/lib/sequel/adapters/oracle.rb +349 -53
  83. data/lib/sequel/adapters/postgres.rb +368 -138
  84. data/lib/sequel/adapters/shared/access.rb +32 -9
  85. data/lib/sequel/adapters/shared/db2.rb +343 -0
  86. data/lib/sequel/adapters/shared/firebird.rb +221 -0
  87. data/lib/sequel/adapters/shared/informix.rb +53 -0
  88. data/lib/sequel/adapters/shared/mssql.rb +401 -116
  89. data/lib/sequel/adapters/shared/mysql.rb +424 -89
  90. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
  91. data/lib/sequel/adapters/shared/oracle.rb +257 -45
  92. data/lib/sequel/adapters/shared/postgres.rb +675 -279
  93. data/lib/sequel/adapters/shared/progress.rb +5 -8
  94. data/lib/sequel/adapters/shared/sqlite.rb +285 -96
  95. data/lib/sequel/adapters/sqlite.rb +101 -39
  96. data/lib/sequel/adapters/swift/mysql.rb +10 -12
  97. data/lib/sequel/adapters/swift/postgres.rb +13 -79
  98. data/lib/sequel/adapters/swift/sqlite.rb +9 -6
  99. data/lib/sequel/adapters/swift.rb +28 -19
  100. data/lib/sequel/adapters/tinytds.rb +174 -22
  101. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
  102. data/lib/sequel/adapters/utils/pg_types.rb +81 -0
  103. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  104. data/lib/sequel/ast_transformer.rb +194 -0
  105. data/lib/sequel/connection_pool/sharded_single.rb +11 -1
  106. data/lib/sequel/connection_pool/sharded_threaded.rb +33 -2
  107. data/lib/sequel/connection_pool/single.rb +5 -0
  108. data/lib/sequel/connection_pool/threaded.rb +43 -14
  109. data/lib/sequel/connection_pool.rb +10 -2
  110. data/lib/sequel/core.rb +143 -11
  111. data/lib/sequel/database/connecting.rb +38 -28
  112. data/lib/sequel/database/dataset.rb +4 -4
  113. data/lib/sequel/database/dataset_defaults.rb +63 -2
  114. data/lib/sequel/database/logging.rb +7 -2
  115. data/lib/sequel/database/misc.rb +190 -46
  116. data/lib/sequel/database/query.rb +272 -110
  117. data/lib/sequel/database/schema_generator.rb +103 -36
  118. data/lib/sequel/database/schema_methods.rb +300 -67
  119. data/lib/sequel/dataset/actions.rb +344 -90
  120. data/lib/sequel/dataset/features.rb +101 -8
  121. data/lib/sequel/dataset/graph.rb +42 -15
  122. data/lib/sequel/dataset/misc.rb +52 -25
  123. data/lib/sequel/dataset/mutation.rb +12 -7
  124. data/lib/sequel/dataset/prepared_statements.rb +68 -30
  125. data/lib/sequel/dataset/query.rb +305 -54
  126. data/lib/sequel/dataset/sql.rb +720 -292
  127. data/lib/sequel/dataset.rb +8 -0
  128. data/lib/sequel/exceptions.rb +4 -0
  129. data/lib/sequel/extensions/_pretty_table.rb +83 -0
  130. data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
  131. data/lib/sequel/extensions/blank.rb +4 -0
  132. data/lib/sequel/extensions/columns_introspection.rb +72 -0
  133. data/lib/sequel/extensions/constraint_validations.rb +451 -0
  134. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
  135. data/lib/sequel/extensions/eval_inspect.rb +173 -0
  136. data/lib/sequel/extensions/inflector.rb +4 -0
  137. data/lib/sequel/extensions/looser_typecasting.rb +5 -4
  138. data/lib/sequel/extensions/migration.rb +100 -11
  139. data/lib/sequel/extensions/named_timezones.rb +9 -0
  140. data/lib/sequel/extensions/null_dataset.rb +94 -0
  141. data/lib/sequel/extensions/pagination.rb +4 -0
  142. data/lib/sequel/extensions/pg_array.rb +537 -0
  143. data/lib/sequel/extensions/pg_array_ops.rb +263 -0
  144. data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
  145. data/lib/sequel/extensions/pg_hstore.rb +313 -0
  146. data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
  147. data/lib/sequel/extensions/pg_inet.rb +113 -0
  148. data/lib/sequel/extensions/pg_interval.rb +191 -0
  149. data/lib/sequel/extensions/pg_json.rb +208 -0
  150. data/lib/sequel/extensions/pg_range.rb +512 -0
  151. data/lib/sequel/extensions/pg_range_ops.rb +150 -0
  152. data/lib/sequel/extensions/pg_row.rb +572 -0
  153. data/lib/sequel/extensions/pg_row_ops.rb +182 -0
  154. data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
  155. data/lib/sequel/extensions/pretty_table.rb +17 -72
  156. data/lib/sequel/extensions/query.rb +8 -4
  157. data/lib/sequel/extensions/query_literals.rb +79 -0
  158. data/lib/sequel/extensions/schema_caching.rb +76 -0
  159. data/lib/sequel/extensions/schema_dumper.rb +282 -76
  160. data/lib/sequel/extensions/select_remove.rb +39 -0
  161. data/lib/sequel/extensions/server_block.rb +140 -0
  162. data/lib/sequel/extensions/split_array_nil.rb +65 -0
  163. data/lib/sequel/extensions/sql_expr.rb +8 -110
  164. data/lib/sequel/extensions/string_date_time.rb +4 -0
  165. data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
  166. data/lib/sequel/extensions/to_dot.rb +99 -83
  167. data/lib/sequel/model/associations.rb +1263 -409
  168. data/lib/sequel/model/base.rb +624 -171
  169. data/lib/sequel/model/errors.rb +1 -1
  170. data/lib/sequel/model/exceptions.rb +24 -2
  171. data/lib/sequel/model/inflections.rb +1 -1
  172. data/lib/sequel/model.rb +30 -11
  173. data/lib/sequel/no_core_ext.rb +2 -0
  174. data/lib/sequel/plugins/active_model.rb +13 -1
  175. data/lib/sequel/plugins/association_pks.rb +22 -4
  176. data/lib/sequel/plugins/caching.rb +25 -18
  177. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  178. data/lib/sequel/plugins/composition.rb +44 -12
  179. data/lib/sequel/plugins/constraint_validations.rb +198 -0
  180. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  181. data/lib/sequel/plugins/defaults_setter.rb +72 -0
  182. data/lib/sequel/plugins/dirty.rb +214 -0
  183. data/lib/sequel/plugins/eager_each.rb +59 -0
  184. data/lib/sequel/plugins/force_encoding.rb +6 -6
  185. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  186. data/lib/sequel/plugins/identity_map.rb +134 -15
  187. data/lib/sequel/plugins/instance_filters.rb +10 -0
  188. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  189. data/lib/sequel/plugins/json_serializer.rb +58 -6
  190. data/lib/sequel/plugins/list.rb +13 -2
  191. data/lib/sequel/plugins/many_through_many.rb +103 -51
  192. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  193. data/lib/sequel/plugins/nested_attributes.rb +150 -66
  194. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  195. data/lib/sequel/plugins/pg_row.rb +121 -0
  196. data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
  197. data/lib/sequel/plugins/prepared_statements.rb +167 -0
  198. data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
  199. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  200. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  201. data/lib/sequel/plugins/rcte_tree.rb +31 -17
  202. data/lib/sequel/plugins/schema.rb +8 -3
  203. data/lib/sequel/plugins/serialization.rb +98 -49
  204. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  205. data/lib/sequel/plugins/sharding.rb +21 -54
  206. data/lib/sequel/plugins/single_table_inheritance.rb +5 -3
  207. data/lib/sequel/plugins/static_cache.rb +99 -0
  208. data/lib/sequel/plugins/subclasses.rb +29 -3
  209. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  210. data/lib/sequel/plugins/timestamps.rb +1 -1
  211. data/lib/sequel/plugins/tree.rb +3 -3
  212. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  213. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  214. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  215. data/lib/sequel/plugins/validation_helpers.rb +55 -4
  216. data/lib/sequel/plugins/xml_serializer.rb +15 -4
  217. data/lib/sequel/sql.rb +649 -122
  218. data/lib/sequel/timezones.rb +67 -40
  219. data/lib/sequel/version.rb +1 -1
  220. data/spec/adapters/db2_spec.rb +146 -0
  221. data/spec/adapters/firebird_spec.rb +1 -1
  222. data/spec/adapters/mssql_spec.rb +194 -66
  223. data/spec/adapters/mysql_spec.rb +475 -306
  224. data/spec/adapters/oracle_spec.rb +92 -117
  225. data/spec/adapters/postgres_spec.rb +1982 -325
  226. data/spec/adapters/spec_helper.rb +9 -6
  227. data/spec/adapters/sqlite_spec.rb +203 -75
  228. data/spec/core/connection_pool_spec.rb +218 -93
  229. data/spec/core/database_spec.rb +956 -522
  230. data/spec/core/dataset_spec.rb +1631 -1242
  231. data/spec/core/expression_filters_spec.rb +690 -334
  232. data/spec/core/mock_adapter_spec.rb +453 -0
  233. data/spec/core/object_graph_spec.rb +88 -129
  234. data/spec/core/schema_generator_spec.rb +4 -4
  235. data/spec/core/schema_spec.rb +556 -53
  236. data/spec/core/spec_helper.rb +7 -48
  237. data/spec/core_extensions_spec.rb +626 -0
  238. data/spec/extensions/active_model_spec.rb +13 -0
  239. data/spec/extensions/arbitrary_servers_spec.rb +110 -0
  240. data/spec/extensions/association_autoreloading_spec.rb +18 -10
  241. data/spec/extensions/association_dependencies_spec.rb +15 -25
  242. data/spec/extensions/association_pks_spec.rb +66 -32
  243. data/spec/extensions/association_proxies_spec.rb +4 -4
  244. data/spec/extensions/boolean_readers_spec.rb +25 -25
  245. data/spec/extensions/caching_spec.rb +47 -51
  246. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  247. data/spec/extensions/columns_introspection_spec.rb +91 -0
  248. data/spec/extensions/composition_spec.rb +18 -13
  249. data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
  250. data/spec/extensions/constraint_validations_spec.rb +316 -0
  251. data/spec/extensions/dataset_associations_spec.rb +199 -0
  252. data/spec/extensions/defaults_setter_spec.rb +88 -0
  253. data/spec/extensions/dirty_spec.rb +155 -0
  254. data/spec/extensions/eager_each_spec.rb +34 -0
  255. data/spec/extensions/eval_inspect_spec.rb +67 -0
  256. data/spec/extensions/force_encoding_spec.rb +4 -2
  257. data/spec/extensions/hook_class_methods_spec.rb +97 -128
  258. data/spec/extensions/identity_map_spec.rb +142 -24
  259. data/spec/extensions/inflector_spec.rb +0 -4
  260. data/spec/extensions/instance_filters_spec.rb +11 -21
  261. data/spec/extensions/instance_hooks_spec.rb +72 -0
  262. data/spec/extensions/json_serializer_spec.rb +49 -12
  263. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  264. data/spec/extensions/list_spec.rb +49 -40
  265. data/spec/extensions/looser_typecasting_spec.rb +7 -7
  266. data/spec/extensions/many_through_many_spec.rb +368 -254
  267. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  268. data/spec/extensions/migration_spec.rb +140 -35
  269. data/spec/extensions/named_timezones_spec.rb +29 -11
  270. data/spec/extensions/nested_attributes_spec.rb +268 -89
  271. data/spec/extensions/null_dataset_spec.rb +85 -0
  272. data/spec/extensions/optimistic_locking_spec.rb +24 -21
  273. data/spec/extensions/pg_array_ops_spec.rb +112 -0
  274. data/spec/extensions/pg_array_spec.rb +320 -0
  275. data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
  276. data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
  277. data/spec/extensions/pg_hstore_spec.rb +194 -0
  278. data/spec/extensions/pg_inet_spec.rb +47 -0
  279. data/spec/extensions/pg_interval_spec.rb +72 -0
  280. data/spec/extensions/pg_json_spec.rb +99 -0
  281. data/spec/extensions/pg_range_ops_spec.rb +56 -0
  282. data/spec/extensions/pg_range_spec.rb +395 -0
  283. data/spec/extensions/pg_row_ops_spec.rb +58 -0
  284. data/spec/extensions/pg_row_plugin_spec.rb +49 -0
  285. data/spec/extensions/pg_row_spec.rb +323 -0
  286. data/spec/extensions/pg_statement_cache_spec.rb +208 -0
  287. data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
  288. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  289. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  290. data/spec/extensions/prepared_statements_spec.rb +87 -0
  291. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  292. data/spec/extensions/pretty_table_spec.rb +7 -6
  293. data/spec/extensions/query_literals_spec.rb +167 -0
  294. data/spec/extensions/query_spec.rb +9 -3
  295. data/spec/extensions/rcte_tree_spec.rb +50 -43
  296. data/spec/extensions/schema_caching_spec.rb +41 -0
  297. data/spec/extensions/schema_dumper_spec.rb +434 -49
  298. data/spec/extensions/schema_spec.rb +30 -49
  299. data/spec/extensions/select_remove_spec.rb +38 -0
  300. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  301. data/spec/extensions/serialization_spec.rb +86 -48
  302. data/spec/extensions/server_block_spec.rb +90 -0
  303. data/spec/extensions/sharding_spec.rb +69 -143
  304. data/spec/extensions/single_table_inheritance_spec.rb +23 -29
  305. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  306. data/spec/extensions/spec_helper.rb +34 -67
  307. data/spec/extensions/split_array_nil_spec.rb +24 -0
  308. data/spec/extensions/sql_expr_spec.rb +29 -60
  309. data/spec/extensions/static_cache_spec.rb +145 -0
  310. data/spec/extensions/subclasses_spec.rb +14 -0
  311. data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
  312. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  313. data/spec/extensions/timestamps_spec.rb +6 -6
  314. data/spec/extensions/to_dot_spec.rb +8 -11
  315. data/spec/extensions/touch_spec.rb +13 -14
  316. data/spec/extensions/tree_spec.rb +11 -26
  317. data/spec/extensions/typecast_on_load_spec.rb +9 -6
  318. data/spec/extensions/update_primary_key_spec.rb +30 -24
  319. data/spec/extensions/validation_class_methods_spec.rb +58 -67
  320. data/spec/extensions/validation_helpers_spec.rb +31 -37
  321. data/spec/extensions/xml_serializer_spec.rb +29 -4
  322. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
  323. data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
  324. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
  325. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
  326. data/spec/integration/associations_test.rb +659 -21
  327. data/spec/integration/database_test.rb +11 -5
  328. data/spec/integration/dataset_test.rb +717 -129
  329. data/spec/integration/eager_loader_test.rb +38 -54
  330. data/spec/integration/migrator_test.rb +2 -3
  331. data/spec/integration/model_test.rb +81 -2
  332. data/spec/integration/plugin_test.rb +604 -147
  333. data/spec/integration/prepared_statement_test.rb +272 -128
  334. data/spec/integration/schema_test.rb +367 -57
  335. data/spec/integration/spec_helper.rb +42 -32
  336. data/spec/integration/timezone_test.rb +38 -12
  337. data/spec/integration/transaction_test.rb +183 -8
  338. data/spec/integration/type_test.rb +31 -8
  339. data/spec/model/association_reflection_spec.rb +207 -8
  340. data/spec/model/associations_spec.rb +1206 -693
  341. data/spec/model/base_spec.rb +334 -100
  342. data/spec/model/dataset_methods_spec.rb +45 -27
  343. data/spec/model/eager_loading_spec.rb +828 -692
  344. data/spec/model/hooks_spec.rb +355 -67
  345. data/spec/model/model_spec.rb +251 -179
  346. data/spec/model/plugins_spec.rb +24 -13
  347. data/spec/model/record_spec.rb +506 -232
  348. data/spec/model/spec_helper.rb +16 -77
  349. data/spec/model/validations_spec.rb +38 -2
  350. data/spec/rcov.opts +2 -0
  351. metadata +209 -80
  352. data/spec/core/core_sql_spec.rb +0 -451
@@ -247,7 +247,7 @@ example is a tree structure:
247
247
 
248
248
  class Node
249
249
  many_to_one :parent, :class=>self
250
- one_to_many :children :key=>:parent_id, :class=>self
250
+ one_to_many :children, :key=>:parent_id, :class=>self
251
251
  end
252
252
 
253
253
  For many_to_many self_referential associations, it's fairly similar. Here's
@@ -293,32 +293,6 @@ Examples:
293
293
  @artist.remove_album(@album)
294
294
  @artist.remove_all_albums
295
295
 
296
- == Dataset Method
297
-
298
- In addition to the above methods, associations also add a instance method
299
- ending in +_dataset+ that returns a dataset representing the objects in the associated table:
300
-
301
- @album.artist_id
302
- # 10
303
- @album.artist_dataset
304
- # SELECT * FROM artists WHERE (id = 10)
305
-
306
- @artist.id
307
- # 20
308
- @artist.albums_dataset
309
- # SELECT * FROM albums WHERE (artist_id = 20)
310
-
311
- The association dataset is just like any other Sequel dataset, in that
312
- it can be further filtered, ordered, etc.:
313
-
314
- @artist.albums_dataset.
315
- filter(:name.like('A%')).
316
- order(:copies_sold).
317
- limit(10)
318
- # SELECT * FROM albums
319
- # WHERE ((artist_id = 20) AND (name LIKE 'A%'))
320
- # ORDER BY copies_sold LIMIT 10
321
-
322
296
  == Caching
323
297
 
324
298
  Associations are cached after being retrieved:
@@ -352,23 +326,155 @@ instance method:
352
326
  @album.artists # [<Artist ...>, ...]
353
327
  @album.associations[:artists] # [<Artist ...>, ...]
354
328
 
355
- Note that while the association method caches associated objects, if you
356
- retrieve access through the association dataset directly, the results
357
- will not be cached:
329
+ == Dataset Method
330
+
331
+ In addition to the above methods, associations also add a instance method
332
+ ending in +_dataset+ that returns a dataset representing the objects in the associated table:
333
+
334
+ @album.artist_id
335
+ # 10
336
+ @album.artist_dataset
337
+ # SELECT * FROM artists WHERE (id = 10)
338
+
339
+ @artist.id
340
+ # 20
341
+ @artist.albums_dataset
342
+ # SELECT * FROM albums WHERE (artist_id = 20)
343
+
344
+ The association dataset is just like any other Sequel dataset, in that
345
+ it can be further filtered, ordered, etc.:
346
+
347
+ @artist.albums_dataset.
348
+ where(Sequel.like(:name, 'A%')).
349
+ order(:copies_sold).
350
+ limit(10)
351
+ # SELECT * FROM albums
352
+ # WHERE ((artist_id = 20) AND (name LIKE 'A%'))
353
+ # ORDER BY copies_sold LIMIT 10
354
+
355
+ Records retrieved using the +_dataset+ method are not cached in the
356
+ associations cache.
358
357
 
359
358
  @album.artists_dataset.all # [<Artist ...>, ...]
360
359
  @album.associations[:artists] # nil
361
360
 
361
+ == Dynamic Association Modification
362
+
363
+ Similar to the +_dataset+ method, you can provide a block to the association
364
+ method to customize the dataset that will be used to retrieve the records. So
365
+ you can apply a filter in either of these two ways:
366
+
367
+ @artist.albums_dataset.where(Sequel.like(:name, 'A%'))
368
+ @artist.albums{|ds| ds.where(Sequel.like(:name, 'A%'))}
369
+
370
+ While they both apply the same filter, using the +_dataset+ method does not
371
+ apply any of the association callbacks or handle association reciprocals (see
372
+ below for details about callbacks and reciprocals). Using a block instead handles
373
+ all those things, and also caches its results in the associations cache (ignoring
374
+ any previously cached value).
375
+
376
+ == Filtering By Associations
377
+
378
+ In addition to using the association method to get associated objects, you
379
+ can also use associated objects in filters. For example, to get
380
+ all albums for a given artist, you would usually do:
381
+
382
+ @artist.albums
383
+ # or @artist.albums_dataset for a dataset
384
+
385
+ You can also do the following:
386
+
387
+ Album.where(:artist=>@artist).all
388
+ # or leave off the .all for a dataset
389
+
390
+ For filtering by a single association, this isn't very useful. However, unlike
391
+ using the association method, using a filter allows you to filter by multiple
392
+ associations:
393
+
394
+ Album.where(:artist=>@artist, :publisher=>@publisher)
395
+
396
+ This will return all albums by that artist and published by that publisher.
397
+ This isn't possible using just the association method approach, though you
398
+ can combine the approaches:
399
+
400
+ @artist.albums_dataset.where(:publisher=>@publisher)
401
+
402
+ This doesn't just work for +many_to_one+ associations, it also works for
403
+ +one_to_one+, +one_to_many+, and +many_to_many+ associations:
404
+
405
+ Album.one_to_one :album_info
406
+ # The album related to that AlbumInfo instance
407
+ Album.where(:album_info=>AlbumInfo[2])
408
+
409
+ Album.one_to_many :tracks
410
+ # The album related to that Track instance
411
+ Album.where(:tracks=>Track[3])
412
+
413
+ Album.many_to_many :tags
414
+ # All albums related to that Tag instance
415
+ Album.where(:tags=>Tag[4])
416
+
417
+ Note that for +one_to_many+ and +many_to_many+ associations, you still
418
+ use the plural form even though only a single model object is given.
419
+
420
+ You can also exclude by associations:
421
+
422
+ Album.exclude(:artist=>@artist).all
423
+
424
+ This will return all albums not by that artist.
425
+
426
+ You can also provide an array with multiple model objects:
427
+
428
+ Album.where(:artist=>[@artist1, @artist2]).all
429
+
430
+ Similar to using an array of integers or strings, this will return
431
+ all albums whose artist is one of those two artists. You can also
432
+ use +exclude+ if you want all albums not by either of those artists:
433
+
434
+ Album.exclude(:artist=>[@artist1, @artist2]).all
435
+
436
+ If you are using a +one_to_many+ or +many_to_many+ association, you
437
+ may want to return records where the records matches all of multiple
438
+ records, instead of matching any of them. For example:
439
+
440
+ Album.where(:tags=>[@tag1, @tag2])
441
+
442
+ This matches albums that are associated with either @tag1 or @tag2 or
443
+ both. If you only want ones that you are associated with both, you can
444
+ use separate filter calls:
445
+
446
+ Album.where(:tags=>@tag1).where(:tags=>@tag2)
447
+
448
+ Or the the array form of condition specifiers:
449
+
450
+ Album.where([[:tags, @tag1], [:tags, @tag2]])
451
+
452
+ These will return albums associated with both @tag1 and @tag2.
453
+
454
+ You can also provide a dataset value when filtering by associations:
455
+
456
+ Album.where(:artist=>Artist.where(Sequel.like(:name, 'A%'))).all
457
+
458
+ This will return all albums whose artist starts with 'A'. Like
459
+ the other forms, this can be inverted:
460
+
461
+ Album.exclude(:artist=>Artist.where(Sequel.like(:name, 'A%'))).all
462
+
463
+ This will return all albums whose artist does not start with 'A'.
464
+
465
+ Note that filtering by associations only works correctly for simple
466
+ associations (ones without conditions).
467
+
362
468
  == Name Collisions
363
469
 
364
470
  Because associations create instance methods, it's possible to override
365
- existing instance methods if you name an extension the same as an
471
+ existing instance methods if you name an association the same as an
366
472
  existing method. For example, <tt>values</tt> and <tt>associations</tt>
367
473
  would be bad association names.
368
474
 
369
475
  == Database Schema
370
476
 
371
- Creating an association, doesn't modify the database schema. Sequel
477
+ Creating an association doesn't modify the database schema. Sequel
372
478
  assumes your associations reflect the existing database schema. If not,
373
479
  you should modify your schema before creating the associations.
374
480
 
@@ -451,6 +557,8 @@ wanted to add an albums_artists join table to create the following schema:
451
557
 
452
558
  You could use the following Sequel code:
453
559
 
560
+ DB.create_join_table(:album_id=>:albums, :artist_id=>:artists)
561
+ # or
454
562
  DB.create_table(:albums_artists) do
455
563
  foreign_key :album_id, :albums
456
564
  foreign_key :artist_id, :artists
@@ -499,6 +607,19 @@ To fix this, you need to specify the full model class name using the
499
607
  end
500
608
  end
501
609
 
610
+ If both classes are in the same module, but the default class name
611
+ used is not correct, you need to specify the full class name with the
612
+ :class option:
613
+
614
+ module App1
615
+ class AlbumArtist < Sequel::Model
616
+ one_to_many :albums
617
+ end
618
+ class Album < Sequel::Model
619
+ many_to_one :artist, :class=>"App1::AlbumArtist"
620
+ end
621
+ end
622
+
502
623
  == Method Details
503
624
 
504
625
  In all of these methods, _association_ is replaced by the symbol you
@@ -606,7 +727,7 @@ The <i>association</i>_dataset method returns a dataset that represents
606
727
  all associated objects. This dataset is like any other Sequel dataset,
607
728
  in that it can be filtered, ordered, etc.:
608
729
 
609
- ds = @artist.albums_dataset.filter(:name.like('A%')).order(:copies_sold)
730
+ ds = @artist.albums_dataset.where(Sequel.like(:name, 'A%')).order(:copies_sold)
610
731
 
611
732
  Unlike most other Sequel datasets, association datasets have a couple of
612
733
  added methods:
@@ -717,7 +838,7 @@ that returns all albums of an artist that went gold (sold at least
717
838
  500,000 copies):
718
839
 
719
840
  Artist.one_to_many :gold_albums, :class=>:Album do |ds|
720
- ds.filter{copies_sold > 500000}
841
+ ds.where{copies_sold > 500000}
721
842
  end
722
843
 
723
844
  ==== :class
@@ -736,7 +857,7 @@ default class guessed will be wrong:
736
857
 
737
858
  # guesses GoldAlbum
738
859
  Artist.one_to_many :gold_albums do |ds|
739
- ds.filter{copies_sold > 500000}
860
+ ds.where{copies_sold > 500000}
740
861
  end
741
862
 
742
863
  You can specify the :class option using the class itself, a Symbol,
@@ -761,13 +882,13 @@ symbol. Defaults to :"#{self.name.underscore}_id".
761
882
 
762
883
  Artist.one_to_many :albums # :key=>:artist_id
763
884
 
764
- In both cases an array of symbols for a composite key association:
885
+ In both cases an array of symbols can be used for a composite key association:
765
886
 
766
887
  Apartment.many_to_one :building # :key=>[:city, :address]
767
888
 
768
889
  ==== :conditions
769
890
 
770
- The conditions to use to filter the association, can be any argument passed to filter.
891
+ The conditions to use to filter the association, can be any argument passed to +where+.
771
892
  If you use a hash or an array of two element arrays, this will also be used as a
772
893
  filter when using eager_graph to load the association.
773
894
 
@@ -800,7 +921,7 @@ columns that have the same name in both the join table and the associated
800
921
  table. Example:
801
922
 
802
923
  Artist.one_to_many :albums, :select=>[:id, :name]
803
- Album.many_to_many :tags, :select=>[:tags.*, :albums_tags__number]
924
+ Album.many_to_many :tags, :select=>[Sequel.expr(:tags).*, :albums_tags__number]
804
925
 
805
926
  ==== :limit
806
927
 
@@ -817,8 +938,6 @@ Use an array with two arguments for the value to specify a limit and an offset.
817
938
  This probably doesn't make a lot of sense for *_to_one associations, though you
818
939
  could use it to specify an offset.
819
940
 
820
- This option is ignored when eager loading.
821
-
822
941
  ==== :join_table [+many_to_many+]
823
942
 
824
943
  Name of table that includes the foreign keys to both the current model and the
@@ -833,7 +952,7 @@ Here's an example of the defaults:
833
952
  ==== :left_key [+many_to_many+]
834
953
 
835
954
  Foreign key in join table that points to current model's primary key, as a
836
- symbol. Defaults to :"#{self.name.underscore}_id".
955
+ symbol. Defaults to :"#{model_name.underscore}_id".
837
956
 
838
957
  Album.many_to_many :tags # :left_key=>:album_id
839
958
 
@@ -842,9 +961,9 @@ Can use an array of symbols for a composite key association.
842
961
  ==== :right_key [+many_to_many+]
843
962
 
844
963
  Foreign key in join table that points to associated model's primary key, as a
845
- symbol. Defaults to :"#{name.to_s.singularize}_id".
964
+ symbol. Defaults to :"#{association_name.singularize}_id".
846
965
 
847
- Album.many_to_many :tags # :left_key=>:tag_id
966
+ Album.many_to_many :tags # :right_key=>:tag_id
848
967
 
849
968
  Can use an array of symbols for a composite key association.
850
969
 
@@ -895,7 +1014,7 @@ Here's an example of an association of songs to artists through lyrics, where
895
1014
  the artist can perform any one of four tasks for the lyric:
896
1015
 
897
1016
  Album.one_to_many :songs, :dataset=>(proc do
898
- Song.select(:songs.*).
1017
+ Song.select_all(:songs).
899
1018
  join(Lyric, :id=>:lyricid,
900
1019
  id=>[:composer_id, :arranger_id, :vocalist_id, :lyricist_id])
901
1020
  end)
@@ -914,8 +1033,8 @@ set up association extensions. For more information , please see the
914
1033
  ==== :primary_key
915
1034
 
916
1035
  The column that the :key option references, as a symbol. For +many_to_one+
917
- associations, this column in the associated table. For +one_to_one+ and
918
- +one_to_many+ associations, this column in the current table. In both cases,
1036
+ associations, this column is in the associated table. For +one_to_one+ and
1037
+ +one_to_many+ associations, this column is in the current table. In both cases,
919
1038
  it defaults to the primary key of the table. Can use an
920
1039
  array of symbols for a composite key association.
921
1040
 
@@ -939,7 +1058,7 @@ Column in associated table that :right_key points to, as a symbol.
939
1058
  Defaults to primary key of the associated table.
940
1059
 
941
1060
  Tag.set_primary_key :tid
942
- Album.many_to_many :tags # :left_primary_key=>:tid
1061
+ Album.many_to_many :tags # :right_primary_key=>:tid
943
1062
 
944
1063
  Can use an array of symbols for a composite key association.
945
1064
 
@@ -952,7 +1071,7 @@ applies to the join table. It can be used to make sure additional columns are
952
1071
  used when inserting, or that filters are used when deleting.
953
1072
 
954
1073
  Artist.many_to_many :lead_guitar_albums, :join_table_block=>proc do |ds|
955
- ds.filter(:instrument_id=>5).set_overrides(:instrument_id=>5)
1074
+ ds.where(:instrument_id=>5).set_overrides(:instrument_id=>5)
956
1075
  end
957
1076
 
958
1077
  === Callback Options
@@ -1024,8 +1143,6 @@ Called after removing an object from the association:
1024
1143
 
1025
1144
  Called before the _<i>association</i>= method is called to modify the objects:
1026
1145
 
1027
- Called before removing an object from the association:
1028
-
1029
1146
  class Album
1030
1147
  # Don't associate the album with an artist if the year the album was
1031
1148
  # released is less than the year the artist/band started.
@@ -1049,13 +1166,12 @@ Called after the _<i>association</i>= method is called to modify the objects:
1049
1166
 
1050
1167
  ==== :after_load
1051
1168
 
1052
- Called after retrieving the associated records from the database. Not called
1053
- when eager loading via eager_graph, but called when eager loading via eager.
1169
+ Called after retrieving the associated records from the database.
1054
1170
 
1055
1171
  class Artist
1056
1172
  # Cache all album names to a single string when retrieving the
1057
1173
  # albums.
1058
- one_to_many :albums, :after_add=>:cache_album_names
1174
+ one_to_many :albums, :after_load=>:cache_album_names
1059
1175
 
1060
1176
  attr_reader :album_names
1061
1177
 
@@ -1067,8 +1183,7 @@ when eager loading via eager_graph, but called when eager loading via eager.
1067
1183
  end
1068
1184
 
1069
1185
  Generally used if you know you will always want a certain action done
1070
- when retrieving the association. However, you need to be careful if you
1071
- also plan on using eager_graph to eagerly load the association.
1186
+ when retrieving the association.
1072
1187
 
1073
1188
  For +one_to_many+ and +many_to_many+ associations, both the argument to
1074
1189
  symbol callbacks and the second argument to proc callbacks will be an
@@ -1112,13 +1227,9 @@ For many details and examples of custom eager loaders, please see the
1112
1227
  ==== :eager_loader_key
1113
1228
 
1114
1229
  A symbol for the key column to use to populate the key hash for the eager
1115
- loader. It can be necessary to specify this for custom eager loaders
1116
- where the default key that would be used does not exist, as in that case, Sequel
1117
- would think that the key values are all NULL, and would not attempt to
1118
- eagerly load any associated objects for that association. If you have a
1119
- custom eager loader and aren't sure of a good value to use here, and you
1120
- aren't using the key_hash (first argument to the eager_loader proc), then
1121
- you can probably use the primary key column of the model.
1230
+ loader. Generally does not need to be set manually, defaults to the key
1231
+ method used. Can be set to nil to not populate the key hash (better for
1232
+ performance if a custom eager loader does not use the key_hash).
1122
1233
 
1123
1234
  ==== :eager_block
1124
1235
 
@@ -1137,7 +1248,7 @@ association based on dependent associations:
1137
1248
 
1138
1249
  Artist.one_to_many :albums_with_short_tracks, :class=>:Album,
1139
1250
  :eager_graph=>:tracks do |ds|
1140
- ds.filter{tracks__seconds < 120}
1251
+ ds.where{tracks__seconds < 120}
1141
1252
  end
1142
1253
  Artist.one_to_many :albums_by_track_name, :class=>:Album,
1143
1254
  :eager_graph=>:tracks do |ds|
@@ -1169,13 +1280,13 @@ via eager_graph. This is useful to specify conditions that can't be specified
1169
1280
  in a hash or array of two element arrays.
1170
1281
 
1171
1282
  Artist.one_to_many :gold_albums, :class=>:Album,
1172
- :graph_block=>proc{|j,lj,js| :copies_sold.qualify(j) > 500000}
1283
+ :graph_block=>proc{|j,lj,js| Sequel.qualify(j, :copies_sold) > 500000}
1173
1284
 
1174
1285
  ==== :graph_join_type
1175
1286
 
1176
1287
  The type of SQL join to use when eagerly loading the association via
1177
1288
  eager_graph. Defaults to :left_outer. This is useful if you want to
1178
- ensure that all return only artists that have albums:
1289
+ ensure that only artists that have albums are returned:
1179
1290
 
1180
1291
  Artist.one_to_many :albums, :graph_join_type=>:inner
1181
1292
  # Will exclude artists without an album
@@ -1201,8 +1312,8 @@ where the artist's name differs in case:
1201
1312
 
1202
1313
  Artist.one_to_many :albums, :key=>:artist_name,
1203
1314
  :graph_only_conditions=>nil,
1204
- :graph_block=>proc{|j,lj,js| {:lower.sql_function(artist_name.qualify(j))=>
1205
- :lower.sql_function(name.qualify(lj))}}
1315
+ :graph_block=>proc{|j,lj,js| {Sequel.function(:lower, Sequel.qualify(j, :artist_name))=>
1316
+ Sequel.function(:lower, Sequel.qualify(lj, :name))}}
1206
1317
 
1207
1318
  Note how :graph_only_conditions is set to nil to ignore any existing conditions,
1208
1319
  and :graph_block is used to set up the case insensitive comparison.
@@ -1218,25 +1329,46 @@ a JOIN USING or NATURAL JOIN for the graph:
1218
1329
  Artist.one_to_many :albums, :key=>:artist_name,
1219
1330
  :graph_only_conditions=>nil, :graph_join_type=>:natural
1220
1331
 
1332
+ ==== :graph_alias_base
1333
+
1334
+ The base name to use for the table alias when eager graphing. Defaults to the name
1335
+ of the association. If the alias name has already been used in the query, Sequel will create
1336
+ a unique alias by appending a numeric suffix (e.g. alias_0, alias_1, ...) until the alias is
1337
+ unique.
1338
+
1339
+ This is mostly useful if you have associations with the same name in many models, and you want
1340
+ to be able to easily tell which table alias corresponds to which association when eagerly
1341
+ graphing multiple associations with the same name.
1342
+
1343
+ You can override this option on a per-graph basis by specifying the association as an
1344
+ SQL::AliasedExpression instead of a symbol:
1345
+
1346
+ Album.eager_graph(Sequel.as(:artist, :a))
1347
+
1221
1348
  ==== :eager_grapher
1222
1349
 
1223
1350
  Sets up a custom grapher to use when eager loading the objects via eager_graph.
1224
- This is the eager_graph analogue to the :eager_loader option.
1351
+ This is the eager_graph analogue to the :eager_loader option. This isn't generally
1352
+ needed, as one of the other eager_graph related association options is usually sufficient.
1225
1353
 
1226
- If specified, should be a proc that accepts three three arguments: a dataset,
1227
- an alias to use for the table to graph for this association, and the alias that
1228
- was used for the current table (since you can cascade associations). Should
1229
- return a modified copy of the dataset with the association graphed into it.
1354
+ If specified, should be a proc that accepts a single hash argument, which will contain
1355
+ at least the following keys:
1356
+
1357
+ :self :: The dataset that is doing the eager loading
1358
+ :table_alias :: An alias to use for the table to graph for this association.
1359
+ :implicit_qualifier :: The alias that was used for the current table (since you can cascade associations).
1360
+ :callback :: A callback proc used to dynamically modify the dataset to graph into the
1361
+ current dataset, before such graphing is done. This is nil if no callback
1362
+ proc is used.
1363
+
1364
+ Example:
1230
1365
 
1231
1366
  Artist.one_to_many :self_title_albums, :class=>:Album,
1232
- :eager_grapher=>(proc do |ds, ta, iq|
1233
- ds.graph(Album, {:artist_id=>:id, :name=>:name},
1234
- :table_alias=>ta, :implicit_qualifier=>iq)
1367
+ :eager_grapher=>(proc do |eo|
1368
+ eo[:self].graph(Album, {:artist_id=>:id, :name=>:name},
1369
+ :table_alias=>eo[:table_alias], :implicit_qualifier=>eo[:implicit_qualifier])
1235
1370
  end)
1236
1371
 
1237
- This isn't generally needed, as one of the other eager_graph related
1238
- association options is usually sufficient.
1239
-
1240
1372
  ==== :order_eager_graph
1241
1373
 
1242
1374
  Whether to add the order to the dataset's order when graphing via eager_graph.
@@ -1278,7 +1410,7 @@ has received a bachelor's degree (degree starting with B):
1278
1410
 
1279
1411
  Person.many_to_many :bachelor_degree_colleges, :class=>:College,
1280
1412
  :join_table=>:degrees_received,
1281
- :graph_join_table_block=>proc{|j,lj,js| :degree.qualify(j).like('B%')}
1413
+ :graph_join_table_block=>proc{|j,lj,js| Sequel.qualify(j, :degree).like('B%')}
1282
1414
 
1283
1415
  This should be done when graphing the join table, instead of when graphing the
1284
1416
  final table, as :degree is a column of the join table.
@@ -1300,6 +1432,74 @@ by the foreign/primary keys. This option causes the
1300
1432
  you want to replace the default foreign/primary key conditions that Sequel
1301
1433
  would use when eagerly graphing.
1302
1434
 
1435
+ === Column Naming Conflict Options
1436
+
1437
+ Sequel's association support historically called methods on model objects
1438
+ to get primary key or foreign key values instead of accessing the column
1439
+ values directly, in order to allow advanced features such as associations
1440
+ based on virtual column keys. Unfortunately, that causes issues if columns
1441
+ are used with names that clash with existing method names, which can happen
1442
+ if you want to name the association the same name as an existing column, or
1443
+ if the column has the same name as an already defined method such as
1444
+ <tt>object_id</tt>.
1445
+
1446
+ Sequel has added the following options that allow you to work around the
1447
+ issue by either specifying the column name symbol or the method name symbol
1448
+ to use. In most cases, these methods are designed to be used with column
1449
+ aliases defined with <tt>Model.def_column_alias</tt>:
1450
+
1451
+ # Example schema:
1452
+ # albums artists
1453
+ # :id /--> :id
1454
+ # :artist --/ :name
1455
+ # :name
1456
+ class Album < Sequel::Model
1457
+ def_column_alias(:artist_id, :artist)
1458
+ many_to_one :artist, :key=>:artist_id, :key_column=>:artist
1459
+ end
1460
+
1461
+ # Example schema:
1462
+ # things objs
1463
+ # :id /--> :id
1464
+ # :object_id --/ :name
1465
+ # :name
1466
+ class Thing < Sequel::Model
1467
+ def_column_alias(:obj_id, :object_id)
1468
+ end
1469
+ class Obj < Sequel::Model
1470
+ one_to_many :things, :key=>:object_id, :key_method=>:obj_id
1471
+ end
1472
+
1473
+ ==== :key_column [+many_to_one+]
1474
+
1475
+ Like the :key option, but :key references the method name, while
1476
+ :key_column references the underlying column.
1477
+
1478
+ ==== :primary_key_method [+many_to_one+]
1479
+
1480
+ Like the :primary_key option, but :primary_key references the column
1481
+ name, while :primary_key_method references the method name.
1482
+
1483
+ ==== :primary_key_column [+one_to_many+, +one_to_one+]
1484
+
1485
+ Like the :primary_key option, but :primary_key references the method name, while
1486
+ :primary_key_column references the underlying column.
1487
+
1488
+ ==== :key_method [+one_to_many+, +one_to_one+]
1489
+
1490
+ Like the :key option, but :key references the column
1491
+ name, while :key_method references the method name.
1492
+
1493
+ ==== :left_primary_key_column [+many_to_many+]
1494
+
1495
+ Like the :left_primary_key option, but :left_primary_key references the method name, while
1496
+ :left_primary_key_column references the underlying column.
1497
+
1498
+ ==== :right_primary_key_method [+many_to_many+]
1499
+
1500
+ Like the :right_primary_key option, but :right_primary_key references the column
1501
+ name, while :right_primary_key_method references the method name.
1502
+
1303
1503
  === Advanced Options
1304
1504
 
1305
1505
  ==== :reciprocal
@@ -1399,3 +1599,51 @@ associations depends on another plugin that defines instance methods of
1399
1599
  the same name. In that case, the instance methods of the dependent
1400
1600
  plugin would override the association methods created by the main
1401
1601
  plugin.
1602
+
1603
+ ==== :eager_limit_strategy
1604
+
1605
+ This setting determines what strategy to use for loading the associations
1606
+ that use the :limit setting to limit the number of returned records. You
1607
+ can't use LIMIT directly, since you want a limit for each associated
1608
+ record, not a LIMIT on the number of records returned by the dataset.
1609
+
1610
+ By default, no strategy is used for one_to_one associations, and
1611
+ the :ruby strategy is used for *_many associations, which does a simple
1612
+ array slice after loading the associated records. That doesn't provide
1613
+ a performance advantage, since all records are still loaded from the
1614
+ database, but it at least makes sure the cached records are accurately
1615
+ limited as they would be in the lazy load case.
1616
+
1617
+ The reason no strategy is used by default for one_to_one associations
1618
+ is that none is needed for a true one_to_one association (since there
1619
+ is only one associated record per current record). However, if you are
1620
+ using a one_to_one association where the relationship is really one_to_many,
1621
+ and using an order to pick the first matching row, then if you don't
1622
+ specify an :eager_limit_strategy option, you'll be loading all related
1623
+ rows just to have Sequel ignore all rows after the first. By using a
1624
+ strategy to change the query to only return one associated record per
1625
+ current record, you can get much better database performance.
1626
+
1627
+ You can set a value of +true+ for this option to have Sequel select what
1628
+ it thinks is the best way of limiting the records for your database. You
1629
+ can also specify a symbol to manually choose a strategy. The available
1630
+ strategies are:
1631
+
1632
+ :distinct_on :: Uses DISTINCT ON to ensure only the first matching record
1633
+ is loaded (one_to_one associations only). This is used by
1634
+ default on PostgreSQL.
1635
+ :window_function :: Uses window functions if the database supports it.
1636
+ This is used by default on databases that support window
1637
+ functions.
1638
+ :correlated_subquery :: Uses a correlated subquery to get the information.
1639
+ This is never used by default as if you aren't careful,
1640
+ it can result in pathologically long running times.
1641
+ This will not work correctly for associations where
1642
+ the associated table has a composite primary key if
1643
+ the database doesn't support using IN
1644
+ with multiple columns. This will also not work on MySQL
1645
+ because MySQL has problems using IN with a correlated
1646
+ subquery that contains a limit.
1647
+ :ruby :: Uses ruby array slicing to emulate database limiting (*_many
1648
+ associations only). This is the default if the database doesn't
1649
+ support window functions.