aboutsummaryrefslogtreecommitdiffstats
path: root/guides/source/association_basics.md
diff options
context:
space:
mode:
authorwangjohn <wangjohn@mit.edu>2013-04-02 13:36:25 -0400
committerwangjohn <wangjohn@mit.edu>2013-04-02 14:48:42 -0400
commitde12a6a0efa51ab9d47bad0c94486cdbd1da900b (patch)
tree00ba6a0bc347be5c3b2ae5f98af2fdd918e31be7 /guides/source/association_basics.md
parent2a27485c68aba36c33897ae96f15fda9abb5a6a4 (diff)
downloadrails-de12a6a0efa51ab9d47bad0c94486cdbd1da900b.tar.gz
rails-de12a6a0efa51ab9d47bad0c94486cdbd1da900b.tar.bz2
rails-de12a6a0efa51ab9d47bad0c94486cdbd1da900b.zip
Changed the guides to use distinct instead of uniq for associations (see
commit a1bb6c8b which changes the naming). I've also provided an example of how distinctness when inserting into an association can be achieved.
Diffstat (limited to 'guides/source/association_basics.md')
-rw-r--r--guides/source/association_basics.md36
1 files changed, 30 insertions, 6 deletions
diff --git a/guides/source/association_basics.md b/guides/source/association_basics.md
index 18d9f5c562..8d203d265a 100644
--- a/guides/source/association_basics.md
+++ b/guides/source/association_basics.md
@@ -1648,9 +1648,10 @@ The `select` method lets you override the SQL `SELECT` clause that is used to re
WARNING: If you specify your own `select`, be sure to include the primary key and foreign key columns of the associated model. If you do not, Rails will throw an error.
-##### `uniq`
+##### `distinct`
-Use the `uniq` method to keep the collection free of duplicates. This is mostly useful together with the `:through` option.
+Use the `distinct` method to keep the collection free of duplicates. This is
+mostly useful together with the `:through` option.
```ruby
class Person < ActiveRecord::Base
@@ -1666,14 +1667,15 @@ person.posts.inspect # => [#<Post id: 5, name: "a1">, #<Post id: 5, name: "a1">]
Reading.all.inspect # => [#<Reading id: 12, person_id: 5, post_id: 5>, #<Reading id: 13, person_id: 5, post_id: 5>]
```
-In the above case there are two readings and `person.posts` brings out both of them even though these records are pointing to the same post.
+In the above case there are two readings and `person.posts` brings out both of
+them even though these records are pointing to the same post.
-Now let's set `uniq`:
+Now let's set `distinct`:
```ruby
class Person
has_many :readings
- has_many :posts, -> { uniq }, through: :readings
+ has_many :posts, -> { distinct }, through: :readings
end
person = Person.create(name: 'Honda')
@@ -1684,7 +1686,29 @@ person.posts.inspect # => [#<Post id: 7, name: "a1">]
Reading.all.inspect # => [#<Reading id: 16, person_id: 7, post_id: 7>, #<Reading id: 17, person_id: 7, post_id: 7>]
```
-In the above case there are still two readings. However `person.posts` shows only one post because the collection loads only unique records.
+In the above case there are still two readings. However `person.posts` shows
+only one post because the collection loads only unique records.
+
+If you want to make sure that, upon insertion, all of the records in the
+persisted association are distinct (so that you can be sure that when you
+inspect the association that you will never find duplicate records), you should
+add a unique index on the table itself. For example, if you have a table named
+``person_posts`` and you want to make sure all the posts are unique, you could
+add the following in a migration:
+
+```ruby
+add_index :person_posts, :post, :unique => true
+```
+
+Note that checking for uniqueness using something like ``include?`` is subject
+to race conditions. Do not attempt to use ``include?`` to enforce distinctness
+in an association. For instance, using the post example from above, the
+following code would be racy because multiple users could be attempting this
+at the same time:
+
+```ruby
+person.posts << post unless person.posts.include?(post)
+```
#### When are Objects Saved?