Question | Click to View Answer |
Create a new rails project called many_to_many_relationships and cd into the directory. |
$ rails new many_to_many_relationships
$ cd many_to_many_relationships
|
Create a mountain model with a name attribute. Create a climber model with a name attributes. Associate the models with a join table. |
$ rails g model mountain name
$ rails g model climber name
$ rails g migration climbers_mountains mountain_id:integer climber_id:integer
# Update the climbers_mountains migration file as follows:
class ClimbersMountains < ActiveRecord::Migration
def change
create_table :climbers_mountains, :id => false do |t|
t.integer :climber_id
t.integer :mountain_id
end
end
end
|
Associate the models. |
# models/mountain.rb
class Mountain < ActiveRecord::Base
attr_accessible :name
has_and_belongs_to_many :climbers
end
# models/climber.rb
class Climber < ActiveRecord::Base
attr_accessible :name
has_and_belongs_to_many :mountains
end
|
Use Rails console to create a climber and a mountain and associate the climber and the mountain. |
>> antonio = Climber.create!(:name => "Antonio")
>> heavenly = Mountain.create!(:name => "Heavenly")
This command associates antonio and heavenly:
>> antonio.mountains << heavenly
# We can run these commands now that antonio and heavenly are associated:
>> antonio.mountains
>> heavenly.mountains
|
Inspect the join table in the database and see how Rails stores the data. |
$ rails db
sqlite> select * from climbers_mountains;
|
Use Rails console to associate another mountain and climber (use the reverse direction that you used in the previous example). |
>> big_mountain = Mountain.create!(:name => "Big")
>> big_mountain.climbers << antonio
|
Let's say we want to add a duration column to the climbers_mountains table. What are the associated complications with this? |
It is straightforward to generate a migration and add this column to the climbers_models table, but how will we update this attribute? There is no climbers_models Class, so this would be awkward. |
Generate a magazine model with a name attribute. Generate a reader model with a name attribute. Generate a join model with type:string and length:integer attributes. Create the tables in the database. |
$ rails g model magazine name
$ rails g model reader name
$ rails g model subscription type length:integer magazine_id:integer reader_id:integer
$ rake db:migrate
|
Associate the models. |
# models/magazine.rb
class Magazine < ActiveRecord::Base
attr_accessible :name
has_many :subscriptions
has_many :readers, :through => :subscriptions
end
# models/reader.rb
class Reader < ActiveRecord::Base
attr_accessible :name
has_many :subscriptions
has_many :magazines, :through => :subscriptions
end
models/subscription.rb
class Subscription < ActiveRecord::Base
attr_accessible :length, :type
belongs_to :reader
belongs_to :magazine
end
|
Use Rails console to associate a magazine and a reader. Give examples of how the associations can be used. |
>> vogue = Magazine.create!(:name => "Vogue")
>> bob = Reader.create!(:name => "Bob")
>> bob.magazines << vogue
# Now that the models are associated, you can use these commands:
>> bob.magazines
>> vogue.readers
>> bob.subscriptions
>> vogue.subscriptions
|
What is a huge advantage of has_many through relationships over has_and_belongs_to_many? |
Has_many through is much more flexible and gives you access to a join model that you can add columns to and customize like any other model. A join model is much more powerful and has the same features as a has_and_belongs_to_many relationship, so it is almost always better to use a has_many :through relationship. |
What should you do when naming a join model? |
Think of a single word (if possible) that describes the relationship. Don't name it something boring, like climbers_mountains - think of something better like "adventures". Most of these relationships end with "ment", "tion", or "ship". |
What is a good name for a join model between a person model and a company model? |
Employment. Notice that this join model would not be called employee because employee describes the person, not the relationship between the person and the company. Employment is a more accurate description of the relationship between the person and the company. |
What is a good name for a join model for a relationship between a user model and a group model. |
Membership |