Reputation: 901
Just learning rails...
I have the following models:
class TimeSlot < ActiveRecord::Base
has_and_belongs_to_many :users
end
class User < ActiveRecord::
has_and_belongs_to_many :time_slots
end
I also have a model to join the two:
class TimeSlotsUsers < ActiveRecord::Base
attr_accessible :time_slot_id, :user_id
end
In the console, I create a user object and I want to associate it with a TimeSlot. I have an variable ts
that is a TimeSlot object, and u
that is a user object. Both already exist in the database. When I do ts.users << u
, I get a error saying "ActiveRecord::StatementInvalid: SQLite3::ConstraintException: time_slots_users.created_at may not be NULL: INSERT INTO "time_slots_users" ("time_slot_id", "user_id") VALUES (1, 1).
Why would created_at be null? Isn't it being automatically created when the record in TimeSlotsUsers is created? Do I need to use a has-many through relationship instead?
Upvotes: 1
Views: 146
Reputation: 43298
The join table for a habtm relationship should not have created_at
and updated_at
columns. You also don't need the join model.
If you want to do something with the join tabel and/or add attributes to it you should change to has_many :through
.
Upvotes: 1
Reputation: 4654
A join model is a good pattern if you want to have any information other than the user_id and timeslot_id as part of the relation ship. For example, if you have groups
and users
and you have a many-to-many relationship, but sometimes a user is an admin
of a group, you might put the is_admin
attribute on the join model.
To keep your join model, a better Rails patter is as follows...
class TimeSlot < ActiveRecord::Base
has_many :time_slot_users
has_many :users, through: :time_slot_users
end
class User < ActiveRecord::Base
has_many :time_slot_users
has_many :time_slots, through: :time_slot_users
end
class TimeSlotsUsers < ActiveRecord::Base
belongs_to :users
belongs_to :time_slots
end
I disagree with one of the other answers that advocates no primary key on the join table.
To have the unique id of a relationship is important when you want to delete or edit that relationship using a REST API, for example. Whether to have an updated_at
or created_at
depends on whether they are useful data in your problem domain. It might be useful information, for example, to know when a user was added to a group (or it might not be).
It is important to have a unique index on the join table on (user_id, time_slot_id) to ensure data integrity. Rails models can validate uniqueness reliably in 99.999% of instances, but not 100% of the time.
Upvotes: 2