stevec
stevec

Reputation: 52268

has_one model association not enforcing 'one' in associated model?

I have the following

class User < ApplicationRecord

  has_one :physician

end

and

class Physician < ApplicationRecord

  belongs_to :user

end

Since a user can only have one physician, I was surprised that multiple physician records can be created with the same user id.

Why is this? And how to I prevent it?

Upvotes: 1

Views: 511

Answers (2)

max
max

Reputation: 102036

A belongs_to association does not in any way guarantee that the values are unique. It only stipulates that the association is stored in a foreign key on this models table and thus can only have a single value.

has_one doesn't actually provide any guarantees either. It just specifies that this table is referred to on the other table. If there are multiple matching rows on the other table it will chose the last.

If you want to enforce uniqueness per table you need a validation:

class Physician < ApplicationRecord
  belongs_to :user
  validates_uniqueness_of :user_id
end

And a database index to actually guarantee uniqueness on the database level:

class AddUniqueIndexToPhysicians < ActiveRecord::Migration[6.0]
  def change
    add_index :physicians, :user_id, unique: true
  end
end

Upvotes: 1

Josh Brody
Josh Brody

Reputation: 5363

Physician probably shouldn't have a user_id associated to it:

class User
  belongs_to :physician # has a physician_id column
end

class Physician
  has_many :users # has no mention of user_id in its schema
end

belongs_to is required by default for Rails 5 and later. If users can onboard without a physician and you need to disable this:

class User
  belongs_to :physician, optional: true 
end 

And then later, validate the presence of physician only after some condition.

Upvotes: 0

Related Questions