sequel 4.7.0 → 4.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +46 -0
  3. data/README.rdoc +25 -1
  4. data/doc/active_record.rdoc +1 -1
  5. data/doc/advanced_associations.rdoc +143 -17
  6. data/doc/association_basics.rdoc +80 -59
  7. data/doc/release_notes/4.8.0.txt +175 -0
  8. data/lib/sequel/adapters/odbc.rb +1 -1
  9. data/lib/sequel/adapters/odbc/mssql.rb +4 -2
  10. data/lib/sequel/adapters/shared/postgres.rb +19 -3
  11. data/lib/sequel/adapters/shared/sqlite.rb +3 -3
  12. data/lib/sequel/ast_transformer.rb +1 -1
  13. data/lib/sequel/dataset/actions.rb +1 -1
  14. data/lib/sequel/dataset/graph.rb +23 -9
  15. data/lib/sequel/dataset/misc.rb +2 -2
  16. data/lib/sequel/dataset/sql.rb +3 -3
  17. data/lib/sequel/extensions/columns_introspection.rb +1 -1
  18. data/lib/sequel/extensions/mssql_emulate_lateral_with_apply.rb +1 -1
  19. data/lib/sequel/extensions/pg_array.rb +1 -1
  20. data/lib/sequel/extensions/pg_array_ops.rb +6 -0
  21. data/lib/sequel/extensions/pg_hstore_ops.rb +7 -0
  22. data/lib/sequel/extensions/pg_json_ops.rb +5 -0
  23. data/lib/sequel/extensions/query.rb +8 -2
  24. data/lib/sequel/extensions/to_dot.rb +1 -1
  25. data/lib/sequel/model/associations.rb +476 -152
  26. data/lib/sequel/plugins/class_table_inheritance.rb +11 -3
  27. data/lib/sequel/plugins/dataset_associations.rb +21 -18
  28. data/lib/sequel/plugins/many_through_many.rb +87 -20
  29. data/lib/sequel/plugins/nested_attributes.rb +12 -0
  30. data/lib/sequel/plugins/pg_array_associations.rb +31 -12
  31. data/lib/sequel/plugins/single_table_inheritance.rb +9 -1
  32. data/lib/sequel/sql.rb +1 -0
  33. data/lib/sequel/version.rb +1 -1
  34. data/spec/adapters/mssql_spec.rb +2 -2
  35. data/spec/adapters/postgres_spec.rb +7 -0
  36. data/spec/core/object_graph_spec.rb +250 -196
  37. data/spec/extensions/core_refinements_spec.rb +1 -1
  38. data/spec/extensions/dataset_associations_spec.rb +100 -6
  39. data/spec/extensions/many_through_many_spec.rb +1002 -19
  40. data/spec/extensions/nested_attributes_spec.rb +24 -0
  41. data/spec/extensions/pg_array_associations_spec.rb +17 -12
  42. data/spec/extensions/pg_array_spec.rb +4 -2
  43. data/spec/extensions/spec_helper.rb +1 -1
  44. data/spec/integration/associations_test.rb +1003 -48
  45. data/spec/integration/dataset_test.rb +12 -5
  46. data/spec/integration/prepared_statement_test.rb +1 -1
  47. data/spec/integration/type_test.rb +1 -1
  48. data/spec/model/associations_spec.rb +467 -130
  49. data/spec/model/eager_loading_spec.rb +332 -5
  50. metadata +5 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4c36878b92e104f343cc1e7c92ff6e94026040c1
4
- data.tar.gz: ee7e4399243acbbfa11e6f427fedb49684b2426f
3
+ metadata.gz: 6c96550377e172f2fe1bbca889e66dbf6f4ba2ea
4
+ data.tar.gz: 09b5f64bdd1e48a538caf87c359f0196c5cecf87
5
5
  SHA512:
6
- metadata.gz: faea6910ec5976db18b931961ed086cd295560a7ea54227b9af0811ecb98e75d61ba34899bf0d762c67182dea1be980daf339cce65aad1e9fe06eb7365c43f84
7
- data.tar.gz: d3f3b358199a9f624387f2218074b2d01e39e9a295504dc988dbb8e792155af32e26ac17ca5bbfd95fc3c2d5b7fc084edeab90fa0123b0c673952ec048d0d574
6
+ metadata.gz: d089308d0d6ae3643cd8d84d6a67ad2f130dbafc8bafc1d0432c6ce0e0f496f50c76fed0db3a503a82afc889be9ba7c5639f971b763d1a0b9def6867939ac743
7
+ data.tar.gz: 11bcfe87e96fbd8c61b336994cd142ceec0d0fe5964ab94ea4d2886e7304843180377c488515d2f87dcaf9839974d988c9805c3872baecc5e7f9c373ea2d70fc
data/CHANGELOG CHANGED
@@ -1,3 +1,49 @@
1
+ === 4.8.0 (2014-03-01)
2
+
3
+ * Add SQL::AliasedExpression#alias alias for #aliaz (jeremyevans)
4
+
5
+ * Handle SQL::Identifier, SQL::QualifiedIdentifier, and SQL::AliasedExpression objects as first argument to Dataset#graph (jeremyevans)
6
+
7
+ * Respect qualification and aliases in symbols passed as first argument to Dataset#graph (dividedmind) (#769)
8
+
9
+ * Recognize new constraint violation error messages in SQLite 3.8.2+ (itswindtw) (#766)
10
+
11
+ * Use limit strategy to correctly handle limited associations in the dataset_associations plugin (jeremyevans)
12
+
13
+ * Handle issues in dataset_associations plugin when dataset uses unqualified identifiers for associations requiring joins (jeremyevans)
14
+
15
+ * Handle fractional seconds in input timestamps in the odbc/mssql adapter (Ross Attrill, jeremyevans)
16
+
17
+ * Return fractional seconds in timestamps in the odbc adapter (jeremyevans)
18
+
19
+ * Support :plain and :phrase options to Dataset#full_text_search on PostgreSQL (jeremyevans)
20
+
21
+ * Use limit strategy to correctly handle filtering by limited associations (jeremyevans)
22
+
23
+ * Simplify queries used for filtering by associations with conditions (jeremyevans)
24
+
25
+ * Use an eager limit strategy by default for *_one associations with orders (jeremyevans)
26
+
27
+ * Support :limit_strategy eager_graph option, for specifying strategy used for limited associations in that eager graph (jeremyevans)
28
+
29
+ * Add eager_graph_with_options to model datasets, for specifying options specific to the eager_graph call (jeremyevans)
30
+
31
+ * Handle offsets on *_many associations when eager graphing when there are no associated results (jeremyevans)
32
+
33
+ * Make Database#register_array_type work without existing scalar conversion proc in the pg_array extension (jeremyevans)
34
+
35
+ * Handle presence validations on foreign keys in associated objects when creating new associated objects in the nested_attributes plugin (jeremyevans)
36
+
37
+ * Respect offsets when eager graphing *_one associations (jeremyevans)
38
+
39
+ * Add association_join to model datasets, for setting up joins based on associations (jeremyevans)
40
+
41
+ * Add one_through_many association to many_through_many plugin, for only returning a single record (jeremyevans)
42
+
43
+ * Add :graph_order association option, useful when :order needs to contain qualified identifiers (jeremyevans)
44
+
45
+ * Add one_through_one association, similar to many_to_many but only returning a single record (jeremyevans)
46
+
1
47
  === 4.7.0 (2014-02-01)
2
48
 
3
49
  * Don't swallow underlying exception if there is an exception closing the cursor on PostgreSQL (jeremyevans) (#761)
@@ -639,12 +639,14 @@ SQL query.
639
639
 
640
640
  === Associations
641
641
 
642
- Associations are used in order to specify relationships between model classes that reflect relationships between tables in the database, which are usually specified using foreign keys. You specify model associations via the +many_to_one+, +one_to_one+, +one_to_many+, and +many_to_many+ class methods:
642
+ Associations are used in order to specify relationships between model classes that reflect relationships between tables in the database, which are usually specified using foreign keys. You specify model associations via class methods:
643
643
 
644
644
  class Post < Sequel::Model
645
645
  many_to_one :author
646
646
  one_to_many :comments
647
+ one_to_one :first_comment, :class=>:Comment, :order=>:id
647
648
  many_to_many :tags
649
+ one_through_one :first_tag, :class=>:Tag, :order=>:name, :right_key=>:tag_id
648
650
  end
649
651
 
650
652
  +many_to_one+ and +one_to_one+ create a getter and setter for each model object:
@@ -745,6 +747,28 @@ You can dynamically customize eager loads for both +eager+ and +eager_graph+ whi
745
747
  # Eagerly load only replies containing 'foo', and the person and tags for those replies
746
748
  Post.eager(:replies=>{proc{|ds| ds.where(Sequel.like(text, '%foo%'))}=>[:person, :tags]}).all
747
749
 
750
+ === Joining with Associations
751
+
752
+ You can use the association_join method to add a join to the model's dataset based on the assocation:
753
+
754
+ Post.association_join(:author)
755
+ # SELECT * FROM posts
756
+ # INNER JOIN authors AS author ON (author.id = posts.author_id)
757
+
758
+ This comes with variants for different join types:
759
+
760
+ Post.association_left_join(:replies)
761
+ # SELECT * FROM posts
762
+ # LEFT JOIN replies ON (replies.post_id = posts.id)
763
+
764
+ Similar to the eager loading methods, you can use multiple associations and nested associations:
765
+
766
+ Post.association_join(:author, :replies=>:person).all
767
+ # SELECT * FROM posts
768
+ # INNER JOIN authors AS author ON (author.id = posts.author_id)
769
+ # INNER JOIN replies ON (replies.post_id = posts.id)
770
+ # INNER JOIN people AS person ON (person.id = replies.person_id)
771
+
748
772
  === Extending the underlying dataset
749
773
 
750
774
  The recommended way to implement table-wide logic by defining methods on the dataset using +dataset_module+:
@@ -396,7 +396,7 @@ ActiveRecord option :: Sequel option
396
396
  <tt>:polymorphic</tt>, <tt>:as</tt>, <tt>:source_type</tt> :: The +sequel_polymorphic+ external plugin
397
397
  <tt>:include</tt> :: <tt>:eager</tt>, <tt>:eager_graph</tt>
398
398
  <tt>:readonly</tt> :: No equivalent, the Sequel <tt>:read_only</tt> option just means the modification methods are not created (it makes the association read only, not records retrieved through the association)
399
- <tt>:through</tt>, <tt>:source</tt> :: Use a +many_to_many+ association, or the +many_through_many+ plugin
399
+ <tt>:through</tt>, <tt>:source</tt> :: Use a +many_to_many+ or +one_through_one+ association, or the +many_through_many+ plugin
400
400
  <tt>:touch</tt> :: The +touch+ plugin
401
401
  <tt>:autosave</tt> :: A +before_save+ or +after_save+ hook
402
402
  <tt>:finder_sql</tt> :: <tt>:dataset</tt> to set a custom dataset
@@ -240,6 +240,145 @@ Using the :eager_loader proc, you should be able to eagerly load all association
240
240
  that can be eagerly loaded, even if Sequel doesn't natively support such eager
241
241
  loading.
242
242
 
243
+ == Limited Associations
244
+
245
+ Sequel supports specifying limits and/or offsets for associations:
246
+
247
+ Artist.one_to_many :first_10_albums, :class=>:Album, :order=>:release_date, :limit=>10
248
+
249
+ For retrieving the associated objects for a single object, this just uses
250
+ a LIMIT:
251
+
252
+ artist.first_10_albums
253
+ # SELECT * FROM albums WHERE (artist_id = 1) LIMIT 10
254
+
255
+ === Eager Loading via eager
256
+
257
+ However, if you want to eagerly load an association, you must use a different
258
+ approach. Sequel has 3 separate strategies for dealing with such cases,
259
+ depending on database support.
260
+
261
+ On PostgreSQL, for *_one associations that don't use an offset, it will by
262
+ default use the distinct on strategy, which uses a DISTINCT ON clause:
263
+
264
+ Artist.one_to_one :first_album, :class=>:Album, :order=>:release_date
265
+ Artist.where(:id=>[1,2]).eager(:first_album).all
266
+ # SELECT DISTINCT ON (albums.artist_id) *
267
+ # FROM albums
268
+ # WHERE (albums.artist_id IN (1, 2))
269
+ # ORDER BY albums.artist_id, release_date
270
+
271
+ Otherwise, if the database supports window functions, it will use a subquery
272
+ with a window function:
273
+
274
+ Artist.where(:id=>[1,2]).eager(:first_10_albums).all
275
+ # SELECT * FROM (
276
+ # SELECT *, row_number() OVER (PARTITION BY tracks.album_id ORDER BY release_date) AS x_sequel_row_number_x
277
+ # FROM tracks
278
+ # WHERE (tracks.album_id IN (1, 2))
279
+ # ) AS t1
280
+ # WHERE (x_sequel_row_number_x <= 10)
281
+
282
+ If the database doesn't support window functions, it will fall back to
283
+ retrieving all records, and then will slice the resulting array to get
284
+ the first 10 after retrieval.
285
+
286
+ === Eager Loading via eager_graph_with_options
287
+
288
+ When eager loading an association via eager_graph (which uses JOINs), the
289
+ situation is similar. Sequel can use a variant of the same 3 strategies,
290
+ but by default it retrieves all records and then does the array slice
291
+ in ruby. As eager_graph does not support options, to use an eager_graph
292
+ limit strategy you have to use the eager_graph_with_options method with
293
+ the :limit_strategy option.
294
+
295
+ The distinct on strategy uses DISTINCT ON in a subquery and JOINs that
296
+ subquery:
297
+
298
+ Artist.eager_graph_with_options(:first_album, :limit_strategy=>true).all
299
+ # SELECT artists.id, artists.name, first_album.id AS first_album_id,
300
+ # first_album.name AS first_album_name, first_album.artist_id,
301
+ # first_album.release_date
302
+ # FROM artists
303
+ # LEFT OUTER JOIN (
304
+ # SELECT DISTINCT ON (albums.artist_id) *
305
+ # FROM albums
306
+ # ORDER BY albums.artist_id, release_date
307
+ # ) AS first_album ON (first_album.artist_id = artists.id)
308
+
309
+ The window function approach JOINs to a nested subquery using a window
310
+ function:
311
+
312
+ Artist.eager_graph_with_options(:first_10_albums, :limit_strategy=>true).all
313
+ # SELECT artists.id, artists.name, first_10_albums.id AS first_10_albums_id,
314
+ # first_10_albums.name AS first_10_albums_name, first_10_albums.artist_id,
315
+ # first_10_albums.release_date
316
+ # FROM artists
317
+ # LEFT OUTER JOIN (
318
+ # SELECT id, name, artist_id, release_date
319
+ # FROM (
320
+ # SELECT *, row_number() OVER (PARTITION BY tracks.album_id ORDER BY release_date) AS x_sequel_row_number_x
321
+ # FROM albums
322
+ # ) AS t1 WHERE (x_sequel_row_number_x <= 10)
323
+ # ) AS first_10_albums ON (first_10_albums.artist_id = artists.id)
324
+
325
+ The reason that Sequel does not automatically use the distinct on or
326
+ window function strategy for eager_graph is that it can perform much worse than the
327
+ default of just doing the array slicing in ruby. If you are only using eager_graph to
328
+ return a few records, it may be cheaper to get all of their associated records and filter
329
+ them in ruby as opposed to computing the set of limited associated records for all rows.
330
+
331
+ It's recommended to only use an eager_graph limit strategy if you have benchmarked
332
+ it against the default behavior and found it is faster for your use case.
333
+
334
+ === Filtering By Associations
335
+
336
+ In order to return correct results, Sequel automatically uses a limit strategy when
337
+ using filtering by associations with limited associations, using a similar approach as
338
+ when using eager to eagerly load.
339
+
340
+ The distinct on strategy:
341
+
342
+ Artist.where(:first_album=>Album[1]).all
343
+ # SELECT *
344
+ # FROM artists
345
+ # WHERE (artists.id IN (
346
+ # SELECT albums.artist_id
347
+ # FROM albums
348
+ # WHERE ((albums.artist_id IS NOT NULL) AND (albums.id IN (
349
+ # SELECT DISTINCT ON (albums.artist_id) albums.id
350
+ # FROM albums
351
+ # ORDER BY albums.artist_id, release_date
352
+ # )) AND (albums.id = 1))))
353
+
354
+ The window function strategy:
355
+
356
+ Artist.where(:first_10_albums=>Album[1]).all
357
+ # SELECT *
358
+ # FROM artists
359
+ # WHERE (artists.id IN (
360
+ # SELECT albums.artist_id
361
+ # FROM albums
362
+ # WHERE ((albums.artist_id IS NOT NULL) AND (albums.id IN (
363
+ # SELECT id FROM (
364
+ # SELECT albums.id, row_number() OVER (PARTITION BY albums.artist_id ORDER BY release_date) AS x_sequel_row_number_x
365
+ # FROM albums
366
+ # ) AS t1
367
+ # WHERE (x_sequel_row_number_x <= 10)
368
+ # )) AND (albums.id = 1))))
369
+
370
+ Note that if the database does not support window functions, filtering by associations
371
+ with limited associations will not work correctly, leading it to return results where
372
+ associated object used as an argument is not within the limit of the association.
373
+
374
+ == Additional Association Types
375
+
376
+ While the above examples for limited associations showed one_to_many and one_to_one associations,
377
+ it's just because those are the simplest examples. Sequel supports all of the same features for
378
+ many_to_many and one_through_one associations that are enabled by default, as well as the
379
+ many_through_many and one_through_many associations that are added by the many_through_many
380
+ plugin.
381
+
243
382
  == ActiveRecord associations
244
383
 
245
384
  Sequel supports all of associations that ActiveRecord supports, though some
@@ -361,27 +500,14 @@ Sequel::Model:
361
500
 
362
501
  class Invoice < Sequel::Model
363
502
  many_to_one :client
364
-
365
- # has_one :through equivalent 1
366
- # eager load with :eager=>:firm option on :client association, and eager loading :client
367
- def firm
368
- client.firm if client
369
- end
370
-
371
- # has_one :through equivalent 2
372
- # eager load the usual way
373
- many_to_many :firms, :join_table=>:clients, :left_key=>:id, :left_primary_key=>:client_id, :right_key=>:firm_id
374
- def firm
375
- firms.first
376
- end
377
-
378
- # has_one :through equivalent 3
379
- # eager loading requires custom :eager_loader proc
380
- many_to_one :firm, :dataset=>proc{Firm.join(:clients, :firm_id=>:id, :id=>client_id).select_all(:firms)}
503
+ one_through_one :firm, :join_table=>:clients, :left_key=>:id, :left_primary_key=>:client_id, :right_key=>:firm_id
381
504
  end
382
505
 
383
506
  Firm.first.invoices
384
507
 
508
+ To handle cases where there are multiple join tables, use the many_through_many
509
+ plugin that ships with Sequel.
510
+
385
511
  === Polymorphic Associations
386
512
 
387
513
  Sequel discourages the use of polymorphic associations, which is the reason they
@@ -41,14 +41,23 @@ As is the code to add a related album to an artist:
41
41
 
42
42
  @artist.add_album(:name=>'RF')
43
43
 
44
+ It also makes it easier to creating queries that use joins based on the association:
45
+
46
+ Artist.association_join(:albums)
47
+ # SELECT * FROM artists
48
+ # INNER JOIN albums ON (albums.artist_id = artists.id)
49
+
44
50
  == The Types of Associations
45
51
 
46
- Sequel has four different association types built in:
52
+ Sequel has five different association types built in:
47
53
 
48
54
  * many_to_one
49
55
  * one_to_many
50
56
  * one_to_one
51
57
  * many_to_many
58
+ * one_through_one
59
+
60
+ It ships with additional association types via plugins.
52
61
 
53
62
  === many_to_one
54
63
 
@@ -68,13 +77,19 @@ table for each row in the associated table.
68
77
  many_to_one :artist
69
78
  end
70
79
 
71
- === one_to_many
80
+ === one_to_many and one_to_one
72
81
 
73
82
  The one_to_many association is used when the table for the associated class
74
83
  contains a foreign key that references the primary key in the table for the
75
84
  current class. It is named because for each row in the current table there
76
85
  can be many rows in the associated table:
77
86
 
87
+ The one_to_one association can be thought of as a subset of the one_to_many association,
88
+ but where there can only be either 0 or 1 records in the associated table. This is
89
+ useful if there is a unique constraint on the foreign key field in the associated table.
90
+ It's also useful if you want to impose an order on the association and just want the
91
+ first record returned.
92
+
78
93
  # Database schema:
79
94
  # artists albums
80
95
  # :id <----\ :id
@@ -84,27 +99,12 @@ can be many rows in the associated table:
84
99
  class Artist
85
100
  # Uses plural form of associated model name
86
101
  one_to_many :albums
87
- end
88
-
89
- === one_to_one
90
-
91
- The one_to_one association can be thought of as a subset of the one_to_many association,
92
- but where there can only be either 0 or 1 records in the associated table.
93
- It is the least frequently used of the four associations. If you assume
94
- each artist cannot be associated with more than one album:
95
102
 
96
- # Database schema:
97
- # artists albums
98
- # :id <----\ :id
99
- # :name \----- :artist_id
100
- # :name
101
-
102
- class Artist
103
103
  # Uses singular form of associated model name
104
104
  one_to_one :album
105
105
  end
106
-
107
- === many_to_many
106
+
107
+ === many_to_many and one_through_one
108
108
 
109
109
  The many_to_many association allows each row in the current table to be associated
110
110
  to many rows in the associated table, and each row in the associated table to
@@ -112,6 +112,14 @@ many rows in the current table, by using a join table to associate the two table
112
112
  If you assume each artist can have multiple albums and each album can have multiple
113
113
  artists:
114
114
 
115
+ The one_through_one association can be thought of as a subset of the many_to_many
116
+ association, but where there can only be 0 or 1 records in the associated table.
117
+ This is useful if there is a unique constraint on the foreign key in the join table
118
+ that refrences the current table. It's also useful if you want to impose an order
119
+ on the association and just want the first record returned. The one_through_one
120
+ association is so named because it sets up a one-to-one association through a
121
+ single join table.
122
+
115
123
  # Database schema:
116
124
  # albums
117
125
  # :id <----\
@@ -124,14 +132,15 @@ artists:
124
132
  class Artist
125
133
  # Uses plural form of associated model name
126
134
  many_to_many :albums
127
- end
128
- class Album
129
- many_to_many :artists
135
+
136
+ # Uses plural form of associated model name
137
+ one_through_one :album
130
138
  end
131
139
 
132
140
  === Differences Between many_to_one and one_to_one
133
141
 
134
- If you want to setup a 1-1 relationship between two models, you have to use
142
+ If you want to setup a 1-1 relationship between two models, where the
143
+ foreign key in one table references the associated table directly, you have to use
135
144
  many_to_one in one model, and one_to_one in the other model. How do you
136
145
  know which to use in which model?
137
146
 
@@ -293,6 +302,8 @@ Examples:
293
302
  @artist.remove_album(@album)
294
303
  @artist.remove_all_albums
295
304
 
305
+ one_through_one associations do not have any modification methods added.
306
+
296
307
  == Caching
297
308
 
298
309
  Associations are cached after being retrieved:
@@ -334,7 +345,7 @@ ending in +_dataset+ that returns a dataset representing the objects in the asso
334
345
  @album.artist_id
335
346
  # 10
336
347
  @album.artist_dataset
337
- # SELECT * FROM artists WHERE (id = 10)
348
+ # SELECT * FROM artists WHERE (id = 10) LIMIT 1
338
349
 
339
350
  @artist.id
340
351
  # 20
@@ -400,7 +411,7 @@ can combine the approaches:
400
411
  @artist.albums_dataset.where(:publisher=>@publisher)
401
412
 
402
413
  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:
414
+ the other associations:
404
415
 
405
416
  Album.one_to_one :album_info
406
417
  # The album related to that AlbumInfo instance
@@ -414,6 +425,10 @@ This doesn't just work for +many_to_one+ associations, it also works for
414
425
  # All albums related to that Tag instance
415
426
  Album.where(:tags=>Tag[4])
416
427
 
428
+ Album.one_through_one :tag
429
+ # All albums related to that Tag instance
430
+ Album.where(:tag=>Tag[4])
431
+
417
432
  Note that for +one_to_many+ and +many_to_many+ associations, you still
418
433
  use the plural form even though only a single model object is given.
419
434
 
@@ -474,10 +489,7 @@ This will return all albums that whose popular tags would include
474
489
  at least one of those tags.
475
490
 
476
491
  Note that filtering by associations does not work for associations
477
- that use blocks with instance-specific code, or associations that
478
- have a limit or offset. This includes many_to_one/one_to_one
479
- associations that would return multiple values if they were not
480
- limited to a single value.
492
+ that use blocks with instance-specific code.
481
493
 
482
494
  == Name Collisions
483
495
 
@@ -966,7 +978,7 @@ Use an array with two arguments for the value to specify a limit and an offset.
966
978
  This probably doesn't make a lot of sense for *_to_one associations, though you
967
979
  could use it to specify an offset.
968
980
 
969
- ==== :join_table [+many_to_many+]
981
+ ==== :join_table [+many_to_many+, +one_through_one+]
970
982
 
971
983
  Name of table that includes the foreign keys to both the current model and the
972
984
  associated model, as a symbol. Defaults to the name of current model and name
@@ -977,7 +989,7 @@ Here's an example of the defaults:
977
989
  Album.many_to_many :artists # :join_table=>:albums_artists
978
990
  Person.many_to_many :colleges # :join_table=>:colleges_people
979
991
 
980
- ==== :left_key [+many_to_many+]
992
+ ==== :left_key [+many_to_many+, +one_through_one+]
981
993
 
982
994
  Foreign key in join table that points to current model's primary key, as a
983
995
  symbol. Defaults to :"#{model_name.underscore}_id".
@@ -986,10 +998,11 @@ symbol. Defaults to :"#{model_name.underscore}_id".
986
998
 
987
999
  Can use an array of symbols for a composite key association.
988
1000
 
989
- ==== :right_key [+many_to_many+]
1001
+ ==== :right_key [+many_to_many+, +one_through_one+]
990
1002
 
991
1003
  Foreign key in join table that points to associated model's primary key, as a
992
- symbol. Defaults to :"#{association_name.singularize}_id".
1004
+ symbol. Defaults to :"#{association_name.singularize}_id" for +many_to_many+
1005
+ and :"#{association_name}_id" for +one_through_one+.
993
1006
 
994
1007
  Album.many_to_many :tags # :right_key=>:tag_id
995
1008
 
@@ -1065,7 +1078,7 @@ A module or array of modules to extend the dataset with. These are used to
1065
1078
  set up association extensions. For more information , please see the
1066
1079
  {Advanced Associations page}[rdoc-ref:doc/advanced_associations.rdoc].
1067
1080
 
1068
- ==== :primary_key
1081
+ ==== :primary_key [+many_to_one+, +one_to_one+, +one_to_many+]
1069
1082
 
1070
1083
  The column that the :key option references, as a symbol. For +many_to_one+
1071
1084
  associations, this column is in the associated table. For +one_to_one+ and
@@ -1077,7 +1090,7 @@ array of symbols for a composite key association.
1077
1090
  Artist.one_to_many :albums # :primary_key=>:arid
1078
1091
  Album.one_to_many :artist # :primary_key=>:arid
1079
1092
 
1080
- ==== :left_primary_key [+many_to_many+]
1093
+ ==== :left_primary_key [+many_to_many+, +one_through_one+]
1081
1094
 
1082
1095
  Column in current table that :left_key option points to, as a symbol.
1083
1096
  Defaults to primary key of current table.
@@ -1087,7 +1100,7 @@ Defaults to primary key of current table.
1087
1100
 
1088
1101
  Can use an array of symbols for a composite key association.
1089
1102
 
1090
- ==== :right_primary_key [+many_to_many+]
1103
+ ==== :right_primary_key [+many_to_many+, +one_through_one+]
1091
1104
 
1092
1105
  Column in associated table that :right_key points to, as a symbol.
1093
1106
  Defaults to primary key of the associated table.
@@ -1097,7 +1110,7 @@ Defaults to primary key of the associated table.
1097
1110
 
1098
1111
  Can use an array of symbols for a composite key association.
1099
1112
 
1100
- ==== :join_table_block [+many_to_many+]
1113
+ ==== :join_table_block [+many_to_many+, +one_through_one+]
1101
1114
 
1102
1115
  A proc that can be used to modify the dataset used in the add/remove/remove_all
1103
1116
  methods. It's separate from the association block, as that is called on a
@@ -1389,12 +1402,14 @@ needed, as one of the other eager_graph related association options is usually s
1389
1402
  If specified, should be a proc that accepts a single hash argument, which will contain
1390
1403
  at least the following keys:
1391
1404
 
1392
- :self :: The dataset that is doing the eager loading
1393
- :table_alias :: An alias to use for the table to graph for this association.
1394
- :implicit_qualifier :: The alias that was used for the current table (since you can cascade associations).
1395
1405
  :callback :: A callback proc used to dynamically modify the dataset to graph into the
1396
1406
  current dataset, before such graphing is done. This is nil if no callback
1397
1407
  proc is used.
1408
+ :implicit_qualifier :: The alias that was used for the current table (since you can cascade associations).
1409
+ :join_type :: Override the join type to use when graphing.
1410
+ :limit_strategy :: The limit strategy symbol to use when graphing (for limited associations only)
1411
+ :self :: The dataset that is doing the eager loading
1412
+ :table_alias :: An alias to use for the table to graph for this association.
1398
1413
 
1399
1414
  Example:
1400
1415
 
@@ -1413,7 +1428,15 @@ Sequel has to do some guess work when attempting to add the association's
1413
1428
  order to an eager_graphed dataset. In most cases it does so correctly, but
1414
1429
  if it has problems, you'll probably want to set this option to false.
1415
1430
 
1416
- ==== :graph_join_table_conditions [+many_to_many+]
1431
+ ==== :graph_order
1432
+
1433
+ Override the order added when using eager_graph, instead of using the one
1434
+ defined in :order. This is useful if :order contains qualified identifiers,
1435
+ as the qualifiers may not match the aliases automatically used by eager_graph.
1436
+ This should contain unqualified identifiers, and eager_graph will automatically
1437
+ qualify them with the appropriate alias.
1438
+
1439
+ ==== :graph_join_table_conditions [+many_to_many+, +one_through_one+]
1417
1440
 
1418
1441
  The additional conditions to use on the SQL join for the join table when
1419
1442
  eagerly loading the association via eager_graph. Should be a hash or an array
@@ -1428,7 +1451,7 @@ has received a specific degree:
1428
1451
  :join_table=>:degrees_received,
1429
1452
  :graph_join_table_conditions=>{:degree=>'BS'}
1430
1453
 
1431
- ==== :graph_join_table_block [+many_to_many+]
1454
+ ==== :graph_join_table_block [+many_to_many+, +one_through_one+]
1432
1455
 
1433
1456
  The block to pass to join_table for the join table when eagerly loading the
1434
1457
  association via eager_graph. This is used for similar reasons as :graph_block,
@@ -1450,7 +1473,7 @@ has received a bachelor's degree (degree starting with B):
1450
1473
  This should be done when graphing the join table, instead of when graphing the
1451
1474
  final table, as :degree is a column of the join table.
1452
1475
 
1453
- ==== :graph_join_table_join_type [+many_to_many+]
1476
+ ==== :graph_join_table_join_type [+many_to_many+, +one_through_one+]
1454
1477
 
1455
1478
  The type of SQL join to use for the join table when eagerly loading the
1456
1479
  association via eager_graph. Defaults to the :graph_join_type option or
@@ -1458,7 +1481,7 @@ association via eager_graph. Defaults to the :graph_join_type option or
1458
1481
  you want to use a different join type when JOINing to the join table then
1459
1482
  you want to use for JOINing to the final table
1460
1483
 
1461
- ==== :graph_join_table_only_conditions [+many_to_many+]
1484
+ ==== :graph_join_table_only_conditions [+many_to_many+, +one_through_one+]
1462
1485
 
1463
1486
  The conditions to use on the SQL join for the join table when eagerly loading
1464
1487
  the association via eager_graph, instead of the default conditions specified
@@ -1525,12 +1548,12 @@ Like the :primary_key option, but :primary_key references the method name, while
1525
1548
  Like the :key option, but :key references the column
1526
1549
  name, while :key_method references the method name.
1527
1550
 
1528
- ==== :left_primary_key_column [+many_to_many+]
1551
+ ==== :left_primary_key_column [+many_to_many+, +one_through_one+]
1529
1552
 
1530
1553
  Like the :left_primary_key option, but :left_primary_key references the method name, while
1531
1554
  :left_primary_key_column references the underlying column.
1532
1555
 
1533
- ==== :right_primary_key_method [+many_to_many+]
1556
+ ==== :right_primary_key_method [+many_to_many+, +one_through_one+]
1534
1557
 
1535
1558
  Like the :right_primary_key option, but :right_primary_key references the column
1536
1559
  name, while :right_primary_key_method references the method name.
@@ -1678,7 +1701,7 @@ instances.
1678
1701
  ==== :cartesian_product_number
1679
1702
 
1680
1703
  The number of joins completed by this association that could cause more
1681
- than one row for each row in the current table (default: 0 for *_to_one
1704
+ than one row for each row in the current table (default: 0 for *_one
1682
1705
  associations, 1 for *_to_many associations).
1683
1706
 
1684
1707
  This should only be modified in specific cases. For example, if you have
@@ -1703,40 +1726,38 @@ plugin.
1703
1726
 
1704
1727
  ==== :eager_limit_strategy
1705
1728
 
1706
- This setting determines what strategy to use for loading the associations
1729
+ This setting determines what strategy to use for eager loading the associations
1707
1730
  that use the :limit setting to limit the number of returned records. You
1708
1731
  can't use LIMIT directly, since you want a limit for each group of
1709
1732
  associated records, not a LIMIT on the total number of records returned
1710
1733
  by the dataset.
1711
1734
 
1712
1735
  By default, if a *_to_many association uses a limit or offset, or a
1713
- one_to_one association uses an offset, Sequel will choose to use an
1736
+ one_*_one association uses an offset or an order, Sequel will choose to use an
1714
1737
  eager limit strategy. The default strategy depends on the database
1715
1738
  being used. For databases which support window functions, a window
1716
1739
  function will be used. Other databases will just have an ruby array
1717
1740
  slice done on the entire record set.
1718
1741
 
1719
- For one_to_one associations without offsets, no strategy is used by default
1720
- because none is needed for a true one_to_one association (since there
1742
+ For one_*_one associations without an offset or order, no strategy is used by default
1743
+ because none is needed for a true one-to-one association (since there
1721
1744
  is only one associated record per current record). However, if you are
1722
1745
  using a one_to_one association where the relationship is really one_to_many,
1723
1746
  and using an order to pick the first matching row, then if you don't
1724
- specify an :eager_limit_strategy option, you'll be loading all related
1747
+ use an limit strategy, you'll be loading all related
1725
1748
  rows just to have Sequel ignore all rows after the first. By using a
1726
1749
  strategy to change the query to only return one associated record per
1727
1750
  current record, you can get much better database performance.
1728
1751
 
1729
1752
  In general, Sequel picks an appropriate strategy, so it is not usually
1730
- necessary to specify a specific strategy. The exception is for one_to_one
1731
- associations where there is more than one associated record per current
1732
- record. For those, you should probably specify true to this option to have
1733
- Sequel pick an appropriate strategy.
1753
+ necessary to specify a specific strategy.
1734
1754
 
1735
- You can also specify a symbol to manually choose a strategy. The available
1736
- strategies are:
1755
+ You can specify true for this option to have Sequel choose which strategy
1756
+ to use (this is the default). You can specify a symbol to manually choose
1757
+ a strategy. The available strategies are:
1737
1758
 
1738
1759
  :distinct_on :: Uses DISTINCT ON to ensure only the first matching record
1739
- is loaded (only used for one_to_one associations without
1760
+ is loaded (only used for one_*_one associations without
1740
1761
  offsets on PostgreSQL).
1741
1762
  :window_function :: Uses a ROW_NUMBER window functions to ensure the
1742
1763
  correctly limited/offset records are returned.