Associations
Modeling database relationships
with ActiveRecord
Database Modeling
The “relational” in relational database
Database Types
Database Types

Rails was designed with a relational database bias
Database Types

Rails was designed with a relational database bias
  Though it can work with other tools, we will stick wi...
Database Types

Rails was designed with a relational database bias
  Though it can work with other tools, we will stick wi...
Database Types

Rails was designed with a relational database bias
  Though it can work with other tools, we will stick wi...
Relationship Types
Relationship Types

There are only three types of relationships in SQL
Relationship Types

There are only three types of relationships in SQL
  One to one
Relationship Types

There are only three types of relationships in SQL
  One to one
  One to many
Relationship Types

There are only three types of relationships in SQL
  One to one
  One to many
  Many to many
Relationship Types

There are only three types of relationships in SQL
  One to one
  One to many
  Many to many
    This ...
One to One
        users
id first_name last_name
1   James        Gray
2   Dana         Gray


                            ...
One to One
        users
id first_name last_name
1   James        Gray
2   Dana         Gray


                            ...
One to Many
              articles
id    title              body        comments
1 The CRUD                …     id articl...
One to Many
              articles
id    title              body        comments
1 The CRUD                …     id articl...
One to Many
              articles
id    title              body        comments
1 The CRUD                …     id articl...
photos
Many to Many         id          path
                     1 /images/mac.jpg

     taggings        2 /images/pc.bmp...
photos
Many to Many         id          path
                     1 /images/mac.jpg

     taggings        2 /images/pc.bmp...
photos
Many to Many         id          path
                     1 /images/mac.jpg

     taggings        2 /images/pc.bmp...
Many to Many (Two Tables)
       followings                    users
id follower_id followed_id   id first_name last_name
1...
Many to Many (Two Tables)
       followings                    users
id follower_id followed_id   id first_name last_name
1...
Many to Many (Two Tables)
       followings                    users
id follower_id followed_id   id first_name last_name
1...
Conventions at Work
                         articles
                   id   title   body
                   1 Unique    ...
Conventions at Work
Rails favors conventions             articles
                               id   title   body
       ...
Conventions at Work
Rails favors conventions             articles
With associations:             id   title   body
       ...
Conventions at Work
Rails favors conventions             articles
With associations:             id   title   body
  Auto-...
Conventions at Work
Rails favors conventions             articles
With associations:             id   title   body
  Auto-...
Conventions at Work
Rails favors conventions             articles
With associations:             id   title   body
  Auto-...
Associations, Rails Style
Let’s turn those examples into real Rails code
Rails Macros
Rails Macros
Use belongs_to() on the ID side of a one to one or one
to many
Rails Macros
Use belongs_to() on the ID side of a one to one or one
to many
Use has_one() on the other side of a one to one
Rails Macros
Use belongs_to() on the ID side of a one to one or one
to many
Use has_one() on the other side of a one to on...
Rails Macros
Use belongs_to() on the ID side of a one to one or one
to many
Use has_one() on the other side of a one to on...
Rails Macros
Use belongs_to() on the ID side of a one to one or one
to many
Use has_one() on the other side of a one to on...
One to Many
              articles
id    title              body        comments
1 The CRUD                …     id articl...
One to Many
An article has_many() comments
class Article < ActiveRecord::Base
    has_many :comments
   end




                                        class Comment...
Associated Models
You can query through the association
>> crud = Article.first
   => #<Article id: 1, title: "The CRUD", body: "...", …>
   >> crud.comments.count
   => 3
   >> c...
>> crud = Article.first
   => #<Article id: 1, title: "The CRUD", body: "...", …>
   >> crud.comments.count
   => 3
   >> c...
>> crud = Article.first
   => #<Article id: 1, title: "The CRUD", body: "...", …>
   >> crud.comments.count
   => 3
   >> c...
>> crud = Article.first
   => #<Article id: 1, title: "The CRUD", body: "...", …>
   >> crud.comments.count
   => 3
   >> c...
>> crud = Article.first
   => #<Article id: 1, title: "The CRUD", body: "...", …>
   >> crud.comments.count
   => 3
   >> c...
Adding to an Association
There are multiple ways to add in new models
>>   a = Article.create!(:title => "Needs Comments")
      =>   #<Article id: 3, title: "Needs Comments", body: nil, …>
  ...
>>   a = Article.create!(:title => "Needs Comments")
      =>   #<Article id: 3, title: "Needs Comments", body: nil, …>
  ...
>>   a = Article.create!(:title => "Needs Comments")
      =>   #<Article id: 3, title: "Needs Comments", body: nil, …>
  ...
>>   a = Article.create!(:title => "Needs Comments")
      =>   #<Article id: 3, title: "Needs Comments", body: nil, …>
  ...
Deleting Associated Models
To delete associated models, find normally
and call destroy()
>> a.comments
   => [#<Comment id: 6, article_id: 3, body: "create!()", …>,
     #<Comment id: 7, article_id: 3, body: "<<...
>> a.comments
   => [#<Comment id: 6, article_id: 3, body: "create!()", …>,
     #<Comment id: 7, article_id: 3, body: "<<...
>> a.comments
   => [#<Comment id: 6, article_id: 3, body: "create!()", …>,
     #<Comment id: 7, article_id: 3, body: "<<...
>> a.comments
   => [#<Comment id: 6, article_id: 3, body: "create!()", …>,
     #<Comment id: 7, article_id: 3, body: "<<...
Using Associations Correctly
Using Associations Correctly

 You should very rarely need to refer to an ID
Using Associations Correctly

 You should very rarely need to refer to an ID
   Let Rails worry about that for you
Using Associations Correctly

 You should very rarely need to refer to an ID
   Let Rails worry about that for you
 It’s s...
Using Associations Correctly

 You should very rarely need to refer to an ID
   Let Rails worry about that for you
 It’s s...
Using Associations Correctly

 You should very rarely need to refer to an ID
   Let Rails worry about that for you
 It’s s...
One to One
        users
id first_name last_name
1   James        Gray
2   Dana         Gray


                            ...
One to One
A user has_one() photo
class User < ActiveRecord::Base
    has_one :photo
   end




                                     class Photo < ActiveRec...
Model Attributes
Just assign a belongs_to()/has_one() to set it
(or call build_photo()/create_photo())
>>   james = User.find_by_first_name("James")
 =>   #<User id: 1, first_name: "James", last_name: "Gray", …>
 >>   james.phot...
>>   james = User.find_by_first_name("James")
 =>   #<User id: 1, first_name: "James", last_name: "Gray", …>
 >>   james.phot...
photos
Many to Many         id          path
                     1 /images/mac.jpg

     taggings        2 /images/pc.bmp...
Many to Many
Photos have many tags
class Photo < ActiveRecord::Base
                                       has_many :taggings
                               ...
class Photo < ActiveRecord::Base
                                       has_many :taggings
                               ...
has_many :through
The nested association is mostly managed by
Rails for you
>> mac = Photo.first
     => #<Photo id: 1, user_id: 1, path: "/images/mac.jpg", …>
     >> mac.taggings
     => [#<Tagging...
>> mac = Photo.first
     => #<Photo id: 1, user_id: 1, path: "/images/mac.jpg", …>
     >> mac.taggings
     => [#<Tagging...
>> mac = Photo.first
     => #<Photo id: 1, user_id: 1, path: "/images/mac.jpg", …>
     >> mac.taggings
     => [#<Tagging...
>> mac = Photo.first
     => #<Photo id: 1, user_id: 1, path: "/images/mac.jpg", …>
     >> mac.taggings
     => [#<Tagging...
Many to Many (Two Tables)
       followings                    users
id follower_id followed_id   id first_name last_name
1...
Many to Many (Two Tables)
Users have many followers
class Following < ActiveRecord::Base
 belongs_to :follower, :class_name => "User",
                :foreign_key => :follow...
class Following < ActiveRecord::Base
 belongs_to :follower, :class_name => "User",
                :foreign_key => :follow...
class Following < ActiveRecord::Base
 belongs_to :follower, :class_name => "User",
                :foreign_key => :follow...
class Following < ActiveRecord::Base
 belongs_to :follower, :class_name => "User",
                :foreign_key => :follow...
Two-way Relationships
Once you get the relationships right, Rails can
still manage the messy details
>> james = User.find_by_first_name("James")
    => #<User id: 1, first_name: "James", last_name: "Gray", …>
    >> james.foll...
>> james = User.find_by_first_name("James")
    => #<User id: 1, first_name: "James", last_name: "Gray", …>
    >> james.foll...
>> james = User.find_by_first_name("James")
    => #<User id: 1, first_name: "James", last_name: "Gray", …>
    >> james.foll...
Extras
Rails associations have quite a few options
Finder Options
and Dependance
Finder Options
and Dependance
Set :conditions, :order, etc. on associations
Finder Options
and Dependance
Set :conditions, :order, etc. on associations
  Example: :order => “created_at DESC”
Finder Options
and Dependance
Set :conditions, :order, etc. on associations
  Example: :order => “created_at DESC”
Specify...
Finder Options
and Dependance
Set :conditions, :order, etc. on associations
  Example: :order => “created_at DESC”
Specify...
Finder Options
and Dependance
Set :conditions, :order, etc. on associations
  Example: :order => “created_at DESC”
Specify...
Polymorphic Associations
Polymorphic Associations

Rails has a special type of “Polymorphic Association”
Polymorphic Associations

Rails has a special type of “Polymorphic Association”
Models are linked with a type and an ID
Polymorphic Associations

Rails has a special type of “Polymorphic Association”
Models are linked with a type and an ID
Th...
Polymorphic Associations

Rails has a special type of “Polymorphic Association”
Models are linked with a type and an ID
Th...
Questions?
Fleshing out the
Data Layer Lab
Your book has instructions on how to add new
models and associate them with existing tables
Upcoming SlideShare
Loading in...5
×

Associations in Rails

11,603

Published on

This was the sixth speech of a three day Rails training I gave in Tulsa, OK in the spring 2010.

Published in: Technology
0 Comments
17 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
11,603
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
247
Comments
0
Likes
17
Embeds 0
No embeds

No notes for slide





































































































  • Associations in Rails

    1. 1. Associations Modeling database relationships with ActiveRecord
    2. 2. Database Modeling The “relational” in relational database
    3. 3. Database Types
    4. 4. Database Types Rails was designed with a relational database bias
    5. 5. Database Types Rails was designed with a relational database bias Though it can work with other tools, we will stick with this primary focus
    6. 6. Database Types Rails was designed with a relational database bias Though it can work with other tools, we will stick with this primary focus ActiveRecord can work with the SQL these databases use to make queries
    7. 7. Database Types Rails was designed with a relational database bias Though it can work with other tools, we will stick with this primary focus ActiveRecord can work with the SQL these databases use to make queries One of the ways it does that is to manage the relationships of data in separate tables
    8. 8. Relationship Types
    9. 9. Relationship Types There are only three types of relationships in SQL
    10. 10. Relationship Types There are only three types of relationships in SQL One to one
    11. 11. Relationship Types There are only three types of relationships in SQL One to one One to many
    12. 12. Relationship Types There are only three types of relationships in SQL One to one One to many Many to many
    13. 13. Relationship Types There are only three types of relationships in SQL One to one One to many Many to many This doesn’t really exist, but it can be simulated
    14. 14. One to One users id first_name last_name 1 James Gray 2 Dana Gray photos id user_id path 1 1 /images/james.png
    15. 15. One to One users id first_name last_name 1 James Gray 2 Dana Gray photos id user_id path 1 1 /images/james.png
    16. 16. One to Many articles id title body comments 1 The CRUD … id article_id body 2 Associations … 1 1 First! 2 1 Tard. 3 1 Am not! 4 2 Viagra 5 2 Spam!
    17. 17. One to Many articles id title body comments 1 The CRUD … id article_id body 2 Associations … 1 1 First! 2 1 Tard. 3 1 Am not! 4 2 Viagra 5 2 Spam!
    18. 18. One to Many articles id title body comments 1 The CRUD … id article_id body 2 Associations … 1 1 First! 2 1 Tard. 3 1 Am not! 4 2 Viagra 5 2 Spam!
    19. 19. photos Many to Many id path 1 /images/mac.jpg taggings 2 /images/pc.bmp id photo_id tag_id 1 1 1 tags id name 2 1 2 1 computer 3 1 3 2 sexy 4 2 4 3 lickable 4 junk
    20. 20. photos Many to Many id path 1 /images/mac.jpg taggings 2 /images/pc.bmp id photo_id tag_id 1 1 1 tags id name 2 1 2 1 computer 3 1 3 2 sexy 4 2 4 3 lickable 4 junk
    21. 21. photos Many to Many id path 1 /images/mac.jpg taggings 2 /images/pc.bmp id photo_id tag_id 1 1 1 tags id name 2 1 2 1 computer 3 1 3 2 sexy 4 2 4 3 lickable 4 junk
    22. 22. Many to Many (Two Tables) followings users id follower_id followed_id id first_name last_name 1 1 4 1 James Gray 2 2 4 2 Dana Gray 3 3 1 3 Super Man 4 4 1 4 Bat Man 5 5 1 5 Spider Man
    23. 23. Many to Many (Two Tables) followings users id follower_id followed_id id first_name last_name 1 1 4 1 James Gray 2 2 4 2 Dana Gray 3 3 1 3 Super Man 4 4 1 4 Bat Man 5 5 1 5 Spider Man
    24. 24. Many to Many (Two Tables) followings users id follower_id followed_id id first_name last_name 1 1 4 1 James Gray 2 2 4 2 Dana Gray 3 3 1 3 Super Man 4 4 1 4 Bat Man 5 5 1 5 Spider Man
    25. 25. Conventions at Work articles id title body 1 Unique … comments id article_id body 1 1 First!
    26. 26. Conventions at Work Rails favors conventions articles id title body 1 Unique … comments id article_id body 1 1 First!
    27. 27. Conventions at Work Rails favors conventions articles With associations: id title body 1 Unique … comments id article_id body 1 1 First!
    28. 28. Conventions at Work Rails favors conventions articles With associations: id title body Auto-incremented ID 1 Unique … fields comments id article_id body 1 1 First!
    29. 29. Conventions at Work Rails favors conventions articles With associations: id title body Auto-incremented ID 1 Unique … fields Table name is plural comments for the collection id article_id body 1 1 First!
    30. 30. Conventions at Work Rails favors conventions articles With associations: id title body Auto-incremented ID 1 Unique … fields Table name is plural comments for the collection id article_id body Foreign key is a singular item plus _id 1 1 First!
    31. 31. Associations, Rails Style Let’s turn those examples into real Rails code
    32. 32. Rails Macros
    33. 33. Rails Macros Use belongs_to() on the ID side of a one to one or one to many
    34. 34. Rails Macros Use belongs_to() on the ID side of a one to one or one to many Use has_one() on the other side of a one to one
    35. 35. Rails Macros Use belongs_to() on the ID side of a one to one or one to many Use has_one() on the other side of a one to one Use has_many() on the other side of a one to many
    36. 36. Rails Macros Use belongs_to() on the ID side of a one to one or one to many Use has_one() on the other side of a one to one Use has_many() on the other side of a one to many Use two belongs_to() calls for the join model of a many to many
    37. 37. Rails Macros Use belongs_to() on the ID side of a one to one or one to many Use has_one() on the other side of a one to one Use has_many() on the other side of a one to many Use two belongs_to() calls for the join model of a many to many Use has_many() and has_many(…, :through => …) for the data models of a many to many
    38. 38. One to Many articles id title body comments 1 The CRUD … id article_id body 2 Associations … 1 1 First! 2 1 Tard. 3 1 Am not! 4 2 Viagra 5 2 Spam!
    39. 39. One to Many An article has_many() comments
    40. 40. class Article < ActiveRecord::Base has_many :comments end class Comment < ActiveRecord::Base belongs_to :article end One to Many An article has_many() comments
    41. 41. Associated Models You can query through the association
    42. 42. >> crud = Article.first => #<Article id: 1, title: "The CRUD", body: "...", …> >> crud.comments.count => 3 >> crud.comments => [#<Comment id: 1, article_id: 1, body: "First!", …>, #<Comment id: 2, article_id: 1, body: "Tard.", …>, #<Comment id: 3, article_id: 1, body: "Am not!", …>] >> crud.comments.last => #<Comment id: 3, article_id: 1, body: "Am not!", …> >> crud.comments.last.article => #<Article id: 1, title: "The CRUD", body: "...", …> Associated Models You can query through the association
    43. 43. >> crud = Article.first => #<Article id: 1, title: "The CRUD", body: "...", …> >> crud.comments.count => 3 >> crud.comments => [#<Comment id: 1, article_id: 1, body: "First!", …>, #<Comment id: 2, article_id: 1, body: "Tard.", …>, #<Comment id: 3, article_id: 1, body: "Am not!", …>] >> crud.comments.last => #<Comment id: 3, article_id: 1, body: "Am not!", …> >> crud.comments.last.article => #<Article id: 1, title: "The CRUD", body: "...", …> Associated Models You can query through the association
    44. 44. >> crud = Article.first => #<Article id: 1, title: "The CRUD", body: "...", …> >> crud.comments.count => 3 >> crud.comments => [#<Comment id: 1, article_id: 1, body: "First!", …>, #<Comment id: 2, article_id: 1, body: "Tard.", …>, #<Comment id: 3, article_id: 1, body: "Am not!", …>] >> crud.comments.last => #<Comment id: 3, article_id: 1, body: "Am not!", …> >> crud.comments.last.article => #<Article id: 1, title: "The CRUD", body: "...", …> Associated Models You can query through the association
    45. 45. >> crud = Article.first => #<Article id: 1, title: "The CRUD", body: "...", …> >> crud.comments.count => 3 >> crud.comments => [#<Comment id: 1, article_id: 1, body: "First!", …>, #<Comment id: 2, article_id: 1, body: "Tard.", …>, #<Comment id: 3, article_id: 1, body: "Am not!", …>] >> crud.comments.last => #<Comment id: 3, article_id: 1, body: "Am not!", …> >> crud.comments.last.article => #<Article id: 1, title: "The CRUD", body: "...", …> Associated Models You can query through the association
    46. 46. >> crud = Article.first => #<Article id: 1, title: "The CRUD", body: "...", …> >> crud.comments.count => 3 >> crud.comments => [#<Comment id: 1, article_id: 1, body: "First!", …>, #<Comment id: 2, article_id: 1, body: "Tard.", …>, #<Comment id: 3, article_id: 1, body: "Am not!", …>] >> crud.comments.last => #<Comment id: 3, article_id: 1, body: "Am not!", …> >> crud.comments.last.article => #<Article id: 1, title: "The CRUD", body: "...", …> Associated Models You can query through the association
    47. 47. Adding to an Association There are multiple ways to add in new models
    48. 48. >> a = Article.create!(:title => "Needs Comments") => #<Article id: 3, title: "Needs Comments", body: nil, …> >> a.comments => [] >> a.comments.create!(:body => "create!()") => #<Comment id: 6, article_id: 3, body: "create!()", …> >> a.comments << Comment.new(:body => "<<") => [#<Comment id: 6, article_id: 3, body: "create!()", …>, #<Comment id: 7, article_id: 3, body: "<<", …>] >> c = a.comments.build(:body => "build()") => #<Comment id: nil, article_id: 3, body: "build()", created_at: nil, updated_at: nil> >> c.save! => true >> a.comments => [#<Comment id: 6, article_id: 3, body: "create!()", …>, #<Comment id: 7, article_id: 3, body: "<<", …>, #<Comment id: 8, article_id: 3, body: "build()", …>] Adding to an Association There are multiple ways to add in new models
    49. 49. >> a = Article.create!(:title => "Needs Comments") => #<Article id: 3, title: "Needs Comments", body: nil, …> >> a.comments => [] >> a.comments.create!(:body => "create!()") => #<Comment id: 6, article_id: 3, body: "create!()", …> >> a.comments << Comment.new(:body => "<<") => [#<Comment id: 6, article_id: 3, body: "create!()", …>, #<Comment id: 7, article_id: 3, body: "<<", …>] >> c = a.comments.build(:body => "build()") => #<Comment id: nil, article_id: 3, body: "build()", created_at: nil, updated_at: nil> >> c.save! => true >> a.comments => [#<Comment id: 6, article_id: 3, body: "create!()", …>, #<Comment id: 7, article_id: 3, body: "<<", …>, #<Comment id: 8, article_id: 3, body: "build()", …>] Adding to an Association There are multiple ways to add in new models
    50. 50. >> a = Article.create!(:title => "Needs Comments") => #<Article id: 3, title: "Needs Comments", body: nil, …> >> a.comments => [] >> a.comments.create!(:body => "create!()") => #<Comment id: 6, article_id: 3, body: "create!()", …> >> a.comments << Comment.new(:body => "<<") => [#<Comment id: 6, article_id: 3, body: "create!()", …>, #<Comment id: 7, article_id: 3, body: "<<", …>] >> c = a.comments.build(:body => "build()") => #<Comment id: nil, article_id: 3, body: "build()", created_at: nil, updated_at: nil> >> c.save! => true >> a.comments => [#<Comment id: 6, article_id: 3, body: "create!()", …>, #<Comment id: 7, article_id: 3, body: "<<", …>, #<Comment id: 8, article_id: 3, body: "build()", …>] Adding to an Association There are multiple ways to add in new models
    51. 51. >> a = Article.create!(:title => "Needs Comments") => #<Article id: 3, title: "Needs Comments", body: nil, …> >> a.comments => [] >> a.comments.create!(:body => "create!()") => #<Comment id: 6, article_id: 3, body: "create!()", …> >> a.comments << Comment.new(:body => "<<") => [#<Comment id: 6, article_id: 3, body: "create!()", …>, #<Comment id: 7, article_id: 3, body: "<<", …>] >> c = a.comments.build(:body => "build()") => #<Comment id: nil, article_id: 3, body: "build()", created_at: nil, updated_at: nil> >> c.save! => true >> a.comments => [#<Comment id: 6, article_id: 3, body: "create!()", …>, #<Comment id: 7, article_id: 3, body: "<<", …>, #<Comment id: 8, article_id: 3, body: "build()", …>] Adding to an Association There are multiple ways to add in new models
    52. 52. Deleting Associated Models To delete associated models, find normally and call destroy()
    53. 53. >> a.comments => [#<Comment id: 6, article_id: 3, body: "create!()", …>, #<Comment id: 7, article_id: 3, body: "<<", …>, #<Comment id: 8, article_id: 3, body: "build()", …>] >> c = a.comments.find(8) => #<Comment id: 8, article_id: 3, body: "build()", …> >> c.destroy if c => #<Comment id: 8, article_id: 3, body: "build()", …> >> a.comments(true) => [#<Comment id: 6, article_id: 3, body: "create!()", …>, #<Comment id: 7, article_id: 3, body: "<<", …>] Deleting Associated Models To delete associated models, find normally and call destroy()
    54. 54. >> a.comments => [#<Comment id: 6, article_id: 3, body: "create!()", …>, #<Comment id: 7, article_id: 3, body: "<<", …>, #<Comment id: 8, article_id: 3, body: "build()", …>] >> c = a.comments.find(8) => #<Comment id: 8, article_id: 3, body: "build()", …> >> c.destroy if c => #<Comment id: 8, article_id: 3, body: "build()", …> >> a.comments(true) => [#<Comment id: 6, article_id: 3, body: "create!()", …>, #<Comment id: 7, article_id: 3, body: "<<", …>] Deleting Associated Models To delete associated models, find normally and call destroy()
    55. 55. >> a.comments => [#<Comment id: 6, article_id: 3, body: "create!()", …>, #<Comment id: 7, article_id: 3, body: "<<", …>, #<Comment id: 8, article_id: 3, body: "build()", …>] >> c = a.comments.find(8) => #<Comment id: 8, article_id: 3, body: "build()", …> >> c.destroy if c => #<Comment id: 8, article_id: 3, body: "build()", …> >> a.comments(true) => [#<Comment id: 6, article_id: 3, body: "create!()", …>, #<Comment id: 7, article_id: 3, body: "<<", …>] Deleting Associated Models To delete associated models, find normally and call destroy()
    56. 56. >> a.comments => [#<Comment id: 6, article_id: 3, body: "create!()", …>, #<Comment id: 7, article_id: 3, body: "<<", …>, #<Comment id: 8, article_id: 3, body: "build()", …>] >> c = a.comments.find(8) => #<Comment id: 8, article_id: 3, body: "build()", …> >> c.destroy if c => #<Comment id: 8, article_id: 3, body: "build()", …> >> a.comments(true) => [#<Comment id: 6, article_id: 3, body: "create!()", …>, #<Comment id: 7, article_id: 3, body: "<<", …>] Deleting Associated Models To delete associated models, find normally and call destroy()
    57. 57. Using Associations Correctly
    58. 58. Using Associations Correctly You should very rarely need to refer to an ID
    59. 59. Using Associations Correctly You should very rarely need to refer to an ID Let Rails worry about that for you
    60. 60. Using Associations Correctly You should very rarely need to refer to an ID Let Rails worry about that for you It’s safer to scope as many queries as possible through the association
    61. 61. Using Associations Correctly You should very rarely need to refer to an ID Let Rails worry about that for you It’s safer to scope as many queries as possible through the association There’s less chance to affect the wrong data
    62. 62. Using Associations Correctly You should very rarely need to refer to an ID Let Rails worry about that for you It’s safer to scope as many queries as possible through the association There’s less chance to affect the wrong data It adds security against users trying to spoof ID’s
    63. 63. One to One users id first_name last_name 1 James Gray 2 Dana Gray photos id user_id path 1 1 /images/james.png
    64. 64. One to One A user has_one() photo
    65. 65. class User < ActiveRecord::Base has_one :photo end class Photo < ActiveRecord::Base belongs_to :user end One to One A user has_one() photo
    66. 66. Model Attributes Just assign a belongs_to()/has_one() to set it (or call build_photo()/create_photo())
    67. 67. >> james = User.find_by_first_name("James") => #<User id: 1, first_name: "James", last_name: "Gray", …> >> james.photo = Photo.new(:path => "/images/james.png") => #<Photo id: 1, user_id: 1, path: "/images/james.png", …> Model Attributes Just assign a belongs_to()/has_one() to set it (or call build_photo()/create_photo())
    68. 68. >> james = User.find_by_first_name("James") => #<User id: 1, first_name: "James", last_name: "Gray", …> >> james.photo = Photo.new(:path => "/images/james.png") => #<Photo id: 1, user_id: 1, path: "/images/james.png", …> Model Attributes Just assign a belongs_to()/has_one() to set it (or call build_photo()/create_photo())
    69. 69. photos Many to Many id path 1 /images/mac.jpg taggings 2 /images/pc.bmp id photo_id tag_id 1 1 1 tags id name 2 1 2 1 computer 3 1 3 2 sexy 4 2 4 3 lickable 4 junk
    70. 70. Many to Many Photos have many tags
    71. 71. class Photo < ActiveRecord::Base has_many :taggings has_many :tags, :through => :taggings end class Tagging < ActiveRecord::Base belongs_to :photo belongs_to :tag end class Tag < ActiveRecord::Base has_many :taggings has_many :photos, :through => :taggings end Many to Many Photos have many tags
    72. 72. class Photo < ActiveRecord::Base has_many :taggings has_many :tags, :through => :taggings end class Tagging < ActiveRecord::Base belongs_to :photo belongs_to :tag end class Tag < ActiveRecord::Base has_many :taggings has_many :photos, :through => :taggings end Many to Many Photos have many tags
    73. 73. has_many :through The nested association is mostly managed by Rails for you
    74. 74. >> mac = Photo.first => #<Photo id: 1, user_id: 1, path: "/images/mac.jpg", …> >> mac.taggings => [#<Tagging id: 1, photo_id: 1, tag_id: 1, …>, #<Tagging id: 2, photo_id: 1, tag_id: 2, …>, #<Tagging id: 3, photo_id: 1, tag_id: 3, …>] >> mac.tags => [#<Tag id: 1, name: "computer", …>, #<Tag id: 2, name: "sexy", …>, #<Tag id: 3, name: "lickable", …>] >> pc = Photo.last => #<Photo id: 2, user_id: nil, path: "/images/pc.bmp", …> >> comp = Tag.find_or_create_by_name("computer") => #<Tag id: 1, name: "computer", …> >> pc.taggings.create!(:tag => comp) => #<Tagging id: 5, photo_id: 2, tag_id: 1, …> has_many :through The nested association is mostly managed by Rails for you
    75. 75. >> mac = Photo.first => #<Photo id: 1, user_id: 1, path: "/images/mac.jpg", …> >> mac.taggings => [#<Tagging id: 1, photo_id: 1, tag_id: 1, …>, #<Tagging id: 2, photo_id: 1, tag_id: 2, …>, #<Tagging id: 3, photo_id: 1, tag_id: 3, …>] >> mac.tags => [#<Tag id: 1, name: "computer", …>, #<Tag id: 2, name: "sexy", …>, #<Tag id: 3, name: "lickable", …>] >> pc = Photo.last => #<Photo id: 2, user_id: nil, path: "/images/pc.bmp", …> >> comp = Tag.find_or_create_by_name("computer") => #<Tag id: 1, name: "computer", …> >> pc.taggings.create!(:tag => comp) => #<Tagging id: 5, photo_id: 2, tag_id: 1, …> has_many :through The nested association is mostly managed by Rails for you
    76. 76. >> mac = Photo.first => #<Photo id: 1, user_id: 1, path: "/images/mac.jpg", …> >> mac.taggings => [#<Tagging id: 1, photo_id: 1, tag_id: 1, …>, #<Tagging id: 2, photo_id: 1, tag_id: 2, …>, #<Tagging id: 3, photo_id: 1, tag_id: 3, …>] >> mac.tags => [#<Tag id: 1, name: "computer", …>, #<Tag id: 2, name: "sexy", …>, #<Tag id: 3, name: "lickable", …>] >> pc = Photo.last => #<Photo id: 2, user_id: nil, path: "/images/pc.bmp", …> >> comp = Tag.find_or_create_by_name("computer") => #<Tag id: 1, name: "computer", …> >> pc.taggings.create!(:tag => comp) => #<Tagging id: 5, photo_id: 2, tag_id: 1, …> has_many :through The nested association is mostly managed by Rails for you
    77. 77. >> mac = Photo.first => #<Photo id: 1, user_id: 1, path: "/images/mac.jpg", …> >> mac.taggings => [#<Tagging id: 1, photo_id: 1, tag_id: 1, …>, #<Tagging id: 2, photo_id: 1, tag_id: 2, …>, #<Tagging id: 3, photo_id: 1, tag_id: 3, …>] >> mac.tags => [#<Tag id: 1, name: "computer", …>, #<Tag id: 2, name: "sexy", …>, #<Tag id: 3, name: "lickable", …>] >> pc = Photo.last => #<Photo id: 2, user_id: nil, path: "/images/pc.bmp", …> >> comp = Tag.find_or_create_by_name("computer") => #<Tag id: 1, name: "computer", …> >> pc.taggings.create!(:tag => comp) => #<Tagging id: 5, photo_id: 2, tag_id: 1, …> has_many :through The nested association is mostly managed by Rails for you
    78. 78. Many to Many (Two Tables) followings users id follower_id followed_id id first_name last_name 1 1 4 1 James Gray 2 2 4 2 Dana Gray 3 3 1 3 Super Man 4 4 1 4 Bat Man 5 5 1 5 Spider Man
    79. 79. Many to Many (Two Tables) Users have many followers
    80. 80. class Following < ActiveRecord::Base belongs_to :follower, :class_name => "User", :foreign_key => :follower_id belongs_to :followed, :class_name => "User", :foreign_key => :followed_id end class User < ActiveRecord::Base has_many :other_followings, :class_name => "Following", :foreign_key => :followed_id has_many :followers, :through => :other_followings has_many :self_followings, :class_name => "Following", :foreign_key => :follower_id has_many :followed_by, :through => :self_followings, :source => :followed end Many to Many (Two Tables) Users have many followers
    81. 81. class Following < ActiveRecord::Base belongs_to :follower, :class_name => "User", :foreign_key => :follower_id belongs_to :followed, :class_name => "User", :foreign_key => :followed_id end class User < ActiveRecord::Base has_many :other_followings, :class_name => "Following", :foreign_key => :followed_id has_many :followers, :through => :other_followings has_many :self_followings, :class_name => "Following", :foreign_key => :follower_id has_many :followed_by, :through => :self_followings, :source => :followed end Many to Many (Two Tables) Users have many followers
    82. 82. class Following < ActiveRecord::Base belongs_to :follower, :class_name => "User", :foreign_key => :follower_id belongs_to :followed, :class_name => "User", :foreign_key => :followed_id end class User < ActiveRecord::Base has_many :other_followings, :class_name => "Following", :foreign_key => :followed_id has_many :followers, :through => :other_followings has_many :self_followings, :class_name => "Following", :foreign_key => :follower_id has_many :followed_by, :through => :self_followings, :source => :followed end Many to Many (Two Tables) Users have many followers
    83. 83. class Following < ActiveRecord::Base belongs_to :follower, :class_name => "User", :foreign_key => :follower_id belongs_to :followed, :class_name => "User", :foreign_key => :followed_id end class User < ActiveRecord::Base has_many :other_followings, :class_name => "Following", :foreign_key => :followed_id has_many :followers, :through => :other_followings has_many :self_followings, :class_name => "Following", :foreign_key => :follower_id has_many :followed_by, :through => :self_followings, :source => :followed end Many to Many (Two Tables) Users have many followers
    84. 84. Two-way Relationships Once you get the relationships right, Rails can still manage the messy details
    85. 85. >> james = User.find_by_first_name("James") => #<User id: 1, first_name: "James", last_name: "Gray", …> >> james.followers => [#<User id: 3, first_name: "Super", last_name: "Man", …>, #<User id: 4, first_name: "Bat", last_name: "Man", …>, #<User id: 5, first_name: "Spider", last_name: "Man", …>] >> james.followed_by => [#<User id: 4, first_name: "Bat", last_name: "Man", …>] >> bat = User.find_by_first_name("Bat") => #<User id: 4, first_name: "Bat", last_name: "Man", …> >> bat.followers => [#<User id: 1, first_name: "James", last_name: "Gray", …>, #<User id: 2, first_name: "Dana", last_name: "Gray", …>] Two-way Relationships Once you get the relationships right, Rails can still manage the messy details
    86. 86. >> james = User.find_by_first_name("James") => #<User id: 1, first_name: "James", last_name: "Gray", …> >> james.followers => [#<User id: 3, first_name: "Super", last_name: "Man", …>, #<User id: 4, first_name: "Bat", last_name: "Man", …>, #<User id: 5, first_name: "Spider", last_name: "Man", …>] >> james.followed_by => [#<User id: 4, first_name: "Bat", last_name: "Man", …>] >> bat = User.find_by_first_name("Bat") => #<User id: 4, first_name: "Bat", last_name: "Man", …> >> bat.followers => [#<User id: 1, first_name: "James", last_name: "Gray", …>, #<User id: 2, first_name: "Dana", last_name: "Gray", …>] Two-way Relationships Once you get the relationships right, Rails can still manage the messy details
    87. 87. >> james = User.find_by_first_name("James") => #<User id: 1, first_name: "James", last_name: "Gray", …> >> james.followers => [#<User id: 3, first_name: "Super", last_name: "Man", …>, #<User id: 4, first_name: "Bat", last_name: "Man", …>, #<User id: 5, first_name: "Spider", last_name: "Man", …>] >> james.followed_by => [#<User id: 4, first_name: "Bat", last_name: "Man", …>] >> bat = User.find_by_first_name("Bat") => #<User id: 4, first_name: "Bat", last_name: "Man", …> >> bat.followers => [#<User id: 1, first_name: "James", last_name: "Gray", …>, #<User id: 2, first_name: "Dana", last_name: "Gray", …>] Two-way Relationships Once you get the relationships right, Rails can still manage the messy details
    88. 88. Extras Rails associations have quite a few options
    89. 89. Finder Options and Dependance
    90. 90. Finder Options and Dependance Set :conditions, :order, etc. on associations
    91. 91. Finder Options and Dependance Set :conditions, :order, etc. on associations Example: :order => “created_at DESC”
    92. 92. Finder Options and Dependance Set :conditions, :order, etc. on associations Example: :order => “created_at DESC” Specify what happens to associations with destroy()
    93. 93. Finder Options and Dependance Set :conditions, :order, etc. on associations Example: :order => “created_at DESC” Specify what happens to associations with destroy() :dependent => :destroy forwards destroy()
    94. 94. Finder Options and Dependance Set :conditions, :order, etc. on associations Example: :order => “created_at DESC” Specify what happens to associations with destroy() :dependent => :destroy forwards destroy() :dependent => :nullify breaks the link
    95. 95. Polymorphic Associations
    96. 96. Polymorphic Associations Rails has a special type of “Polymorphic Association”
    97. 97. Polymorphic Associations Rails has a special type of “Polymorphic Association” Models are linked with a type and an ID
    98. 98. Polymorphic Associations Rails has a special type of “Polymorphic Association” Models are linked with a type and an ID This makes it possible to link one model to multiple different kinds of other models
    99. 99. Polymorphic Associations Rails has a special type of “Polymorphic Association” Models are linked with a type and an ID This makes it possible to link one model to multiple different kinds of other models For example, you might use a Comment model to allows users to comment on multiple things (products and reviews for example)
    100. 100. Questions?
    101. 101. Fleshing out the Data Layer Lab Your book has instructions on how to add new models and associate them with existing tables
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×