Reputation: 213
I was reading another question on here regarding referencing columns from two separate tables but was a little confused if it addressed my issue. What's going on is I have two tables, Destination and Booking. The Destination table has a column for location_id, and the Booking has a column for location, and I am trying to reference location in Booking table from location_id column in Destination table.
Here is my table for Booking(migration)
class CreateBookings < ActiveRecord::Migration[6.1]
def change
create_table :bookings do |t|
t.string :name
t.string :start_date
t.string :end_date
t.string :email
t.integer :location
t.timestamps
end
end
end
and here is my table(Migration) for Destination
class CreateDestinations < ActiveRecord::Migration[6.1]
def change
create_table :destinations do |t|
t.string :address
t.string :city
t.string :state
t.string :zip
t.integer :location_id
t.timestamps
end
end
end
My Models are setup currently as
class Booking < ApplicationRecord
# belongs_to :reservation, optional: true
has_many :destinations, :class_name => 'Destination', :foreign_key=> 'location_id'
validates :name, :start_date, :end_date, :email, presence: true
end
and
class Destination < ApplicationRecord
has_many :bookings, :class_name => 'Booking', :foreign_key=> 'location'
end
Am I currently referencing the columns correctly, or is there something else I should be doing?
Upvotes: 0
Views: 904
Reputation: 1601
Caveat: Based on your question I'm assuming you want a booking to have a destination. If you want a destination to many bookings and vise-versa, Sean's answer is great.
I think you're misunderstanding how foreign keys / associations work in databases.
It sounds like you want a column in the bookings table to "reference" a value column in the destinations table (or maybe the opposite), as in:
bookings.location -> destinations.location_id
or maybe destinations.location_id -> bookings.location
.
That's not typically what we mean by "reference" in a relational database. Instead, when you say that a table (for example, a 'comments' table) references another table (for example, a comments table references a user table), what we typically mean is that we're storing the primary key column of the referenced table (e.g. the user's id) in a column in the first table (e.g. comments.user_id --> users.id
).
From an english language standpoint I expect that you want a booking to refer to a destination, so I'm going to assuming we want a the booking table to reference/refer to the destinations table, like this:
booking.location -> destinations.id
In Ruby on Rails, the convention is to name a column that stores an association with the same as the table it references, plus _id
, like so the convention would be this:
booking.destination_id -> destinations.id
A common way to create this in a migration would be with:
add_reference :bookings, :destination
When adding a reference in a database you almost always want to index by that value (so that you can do Bookings.where(destination_id: @destination.id)
and not kill your database). I am also a strong advocate for letting your database enforce referential integrity for you, so (if your database supports it) i'd recommend the following:
add_reference :destinations, :booking, index: true, foreign_key: true
This would prevent someone from deleting a destination that has a booking associated with it.
Upvotes: 1
Reputation: 3985
How you should write your migrations depends on the association between your models. Foreign keys go onto tables that have a belongs_to
association.
Can a single Booking have multiple Destinations? If the answer is no, you need to change the association in your Booking model to belongs_to :destination
and then put a :destination_id
on your bookings table (you can give it a custom name like :location_id
if you want but the convention is to use the model name).
If a single Booking can have multiple Destinations, and surely a single Destination can have multiple Bookings, then you have a many-to-many relationship. In that case you will not put foreign keys on the destinations table, nor the bookings table. Instead you will need a join table between them and that's where the foreign keys go.
Rails gives 2 different ways to declare many-to-many relationships. See https://guides.rubyonrails.org/association_basics.html#choosing-between-has-many-through-and-has-and-belongs-to-many.
If you want to use has_and_belongs_to_many
, your models would look like this:
class Booking < ApplicationRecord
has_and_belongs_to_many :destinations
end
class Destination < ApplicationRecord
has_and_belongs_to_many :bookings
end
And the migration would look like this:
class CreateBookingsAndDestinations < ActiveRecord::Migration[6.0]
def change
create_table :bookings do |t|
# ...
end
create_table :destinations do |t|
# ...
end
create_table :bookings_destinations, id: false do |t|
t.belongs_to :booking
t.belongs_to :destination
end
end
end
Upvotes: 1