Damian Rivas
Damian Rivas

Reputation: 319

Is has_many still necessary when has_many through exists?

I have what I feel like is a super simple question, but I can't find an answer anywhere!

Question:

If I previously had a has_many relationship like this: has_many :wikis, do I keep this relationship if later on I create a has_many through relationship like the following?

has_many :collaborators
has_many :wikis, through: :collaborators

This is all in my User model.

Background:

In my rails app, I have a User model and a Wiki model. I just gave users the ability to collaborate on private wikis so I migrated a Collaborator model and then came the step to create the has_many through relationships. I wasn't sure if I still needed has_many :wikis after putting has_many :wikis, through: :collaborators.

The reason I am confused is because Users should still be able to create wikis without collaborators and I'm not sure how the has_many through relationship works under the hood.

Originally I had only User and Wiki with a one-to-many relationship.

# User model
class User < ApplicationRecord
  ...    
  has_many :wikis # should I delete this?
  has_many :collaborators
  has_many :wikis, through: :collaborators
  ...
end

# Collaborator model
class Collaborator < ApplicationRecord
  belongs_to :user
  belongs_to :wiki
end

# Wiki model
class Wiki < ApplicationRecord
  belongs_to :user

  has_many :collaborators, dependent: :destroy
  has_many :users, through: :collaborators
  ...
end

Upvotes: 0

Views: 263

Answers (1)

fool-dev
fool-dev

Reputation: 7777

Is has_many still necessary when has_many through exists?

has_many not necessary when presence has_many through like your model

has_many :wikis # should I delete this?
has_many :collaborators
has_many :wikis, through: :collaborators

should I delete this?

Yes, you can delete this one, you don't need this as the same belongs_to

From The has_many Association

A has_many association indicates a one-to-many connection with another model. You'll often find this association on the "other side" of a belongs_to association. This association indicates that each instance of the model has zero or more instances of another model. For example, in an application containing authors and books, the author model could be declared like this:

enter image description here

From The has_many :through Association:

A has_many :through association is often used to set up a many-to-many connection with another model. This association indicates that the declaring model can be matched with zero or more instances of another model by proceeding through a third model. For example, consider a medical practice where patients make appointments to see physicians. The relevant association declarations could look like this:

class Physician < ApplicationRecord
    has_many :appointments
    has_many :patients, through: :appointments
    end
    
    class Appointment < ApplicationRecord
    belongs_to :physician
    belongs_to :patient
    end
    
    class Patient < ApplicationRecord
    has_many :appointments
    has_many :physicians, through: :appointments
    end

enter image description here

You can work with only has_many association without has_many :through, but this is one-to-many, this not many-to-many

  • The has_many Association (without has_many :through) is one-to-many connection with another model
  • The has_many :through Association is up a many-to-many connection with another model

Update

Look, one physician may have many patients, on the other hand, one patient may have many physicians if you use has_many association without through for patient then this called one-to-many association, that means one physician has many patients, on the other hand, one patient belongs to one physician, and now association looks like this

class Physician < ApplicationRecord
  has_many :patients
end
 
class Patient < ApplicationRecord
  belongs_to :physician
end

Update 2

The has_many through the standard format your models after edited

# User model
class User < ApplicationRecord
  ...    
  has_many :collaborators
  has_many :wikis, through: :collaborators
  ...
end

# Collaborator model
class Collaborator < ApplicationRecord
  belongs_to :user
  belongs_to :wiki
end

# Wiki model
class Wiki < ApplicationRecord
  has_many :collaborators, dependent: :destroy
  has_many :users, through: :collaborators
  ...
end

Upvotes: 0

Related Questions