Migrations Lab - Solution
This is related to the lesson on migrations.
There are a several steps in this lab. First we'll add the Activity
model and corresponding database table.
1. Generate the model and migration files. In terminal, run:
rails generate model Activity
2. Check out the generated files:
- app/models/activity.rb
- db/migrate/*_create_activities.rb
3. Add the table columns into the migration file:
t.integer :salesperson_id
t.integer :contact_id
t.string :note
The Activity
model is a join model between Salesperson
and Contact
(based on our domain model). To support that relationship, the activities
table needs foreign keys for salesperson_id
and contact_id
. It also needs a note
column to save what type of activity it was.
4. Execute the migration file to create the table. In terminal, run:
rails db:migrate
Now that the table exists, we can formalize the associations with code.
A salesperson might call a contact, email a contact, meet with a contact, etc. So a salesperson has many activities; likewise a contact has many activities.
In the Salesperson
model (app/models/salesperson.rb
), add the association code:
class Salesperson < ApplicationRecord
has_many :activities
end
Same for the Contact
model (app/models/contact.rb
):
class Contact < ApplicationRecord
has_many :activities
end
And last, we write the inverse associations. Each individual activity only has one salesperson and one contact - for example, a specific call is between 1 salesperson and 1 contact. So that Activity
model has the belongs_to
association:
In the Activity
model (app/models/activity.rb
), add the association code:
class Activity < ApplicationRecord
belongs_to :contact
belongs_to :salesperson
end
5. Insert 2 activities into the activities
table. This is dependent on their already being records in the associated tables.
brian = Salesperson.where({last_name: "Eng", first_name: "Brian"})[0]
contact = Contact.where({first_name: "Tim", last_name: "Cook"})[0]
values = {
salesperson_id: brian.id,
contact_id: contact.id,
note: "Grabbed tacos"
}
activity = Activity.new(values)
activity.save
ben = Salesperson.where({last_name: "Block", first_name: "Ben"})[0]
contact = Contact.where({first_name: "Elon", last_name: "Musk"})[0]
values = {
salesperson_id: ben.id,
contact_id: contact.id,
note: "Liked a tweet"
}
activity = Activity.new(values)
activity.save
6. Loop through the salespeople and display their activities and related contacts. Something like this:
Brian Eng
Grabbed tacos - Tim Cook
Ben Block
Liked a tweet - Elon Musk
First get all the salespeople rows:
salespeople = Salesperson.all
Next loop through them and display the salesperson name:
for salesperson in salespeople
puts "#{salesperson.first_name} #{salesperson.last_name}"
end
For each salesperson, loop through their activities and display the activity and the associated contact for the activity:
for salesperson in salespeople
puts "#{salesperson.first_name} #{salesperson.last_name}"
activities = salesperson.activities
for activity in activities
contact = activity.contact
puts "#{activity.note} - #{contact.first_name} #{contact.last_name}"
end
end