how to do ruby on rails relationship dependent destroy - ruby-on-rails

http://guides.rubyonrails.org/association_basics.html
Based on the above example, I created:
class Physician < ActiveRecord::Base
has_many :appointments
has_many :patients, through: :appointments
end
class Appointment < ActiveRecord::Base
belongs_to :physician
belongs_to :patient
end
class Patient < ActiveRecord::Base
has_many :appointments
has_many :physicians, through: :appointments
end
Can someone guide me how can I perform a cascading delete action.
if I delete a Patient, I want all appointments for the patient deleted. Do I need to use dependent keyword somewhere ? Can someone demonstrate how to solve this.
How do I delete all appointments for a particular patient ?
Thanks in advance!

class Patient < ActiveRecord::Base
has_many :appointments, dependent: :destroy
has_many :physicians, through: :appointments
end
Patient.find(id).destroy
This should work for you. Make sure you use destroy and not delete because if you use delete you won't have the cascading effect you expect.
Update 2:
If you want to destroy all appointments but not the patient you can do this:
Patient.find(id).appointments.destroy_all

Related

adding a model to a joining table and calling it from a different model in rails

Let's say the has_many through is defined like this for a rails model.
class Physician < ApplicationRecord
has_many :appointments
has_many :patients, through: :appointments
has_many :tickets, through: :appointments #For calling **physicion.tickets**. Is this possible???
end
class Appointment < ApplicationRecord
belongs_to :physician
belongs_to :patient
has_many :tickets, as: ticketable
end
class Patient < ApplicationRecord
has_many :appointments
has_many :physicians, through: :appointments
end
This works fine. But let's add a ticket model to the appointment so each appointment can keep tickets belonging to that appointment.
class Ticket < ApplicationRecord
belongs_to :ticketable, polymorphic: true #so it can be used in other models other than appointments
end
appointment.tickets works fine. But how can we fetch all tickets for a particular physician/patient like physicion.tickets or patient.tickets?

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
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:
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
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

usage of "has_many" vs "has_many, through" relation in rails

i'm new to both rails and web-dev.
currently i'm studding "active record Associations" in rails 4
and i got confused on usage of "has_many" vs "has_many, through" relation.
for example, if i have Physician, Appointment, and Patient model in my schema.(As rails guide provides)
and rails tutorial suggests me to do 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
but what if i make relation like this
class Physician < ApplicationRecord
has_many :appointments
end
class Appointment < ApplicationRecord
belongs_to :physician
has_many :patients
end
class Patient < ApplicationRecord
belongs_to :appointment
end
i think both will work fine.
but i want to know whats the differences and why they made "has_many, through" relations.
thank you for reading my question.
has_many through is a way to join two unrelated, independent models/tables and to reduce duplicates/redundancy in tables, where has_many states more directive relation.
Maybe example with appointments and physicians isn't clear. I'll give a different one.
class Artist
has_many :paintings
has_many :purchases
has_many :buyers, through: :purchases
end
class Painting
belongs_to :artist
end
class Purchase
belongs_to :painting
belongs_to :buyer
end
class Buyer
has_many :paintings_buyers
has_many :painting, through: :purchases
end
Talking about your example.
First, there is no convenient way for you to get physician's patents. The only way is:
physician.appoitments.map(&:patient).uniq
Which will result in
poor performance
inability to filter entities with sql, only with ruby(again poor performance)
Also, did you notice I used uniq? That's because patient's table will have lots of duplicates when the same patients will be appointed multiple times to the same physician.

Active record query to get the count for nested associations in rails

How to write an ActiveRecord query to get the number of patients that share an appointment (physician can have more than one appointments)
class Hospital < ActiveRecord::Base
has_many :appointments
has_many :patients
has_many :physicians
end
class Physician < ActiveRecord::Base
has_many :appointments
has_many :patients, through: :appointments
belongs_to :hospital
end
class Appointment < ActiveRecord::Base
belongs_to :physician
belongs_to :patient
belongs_to :hospital
end
class Patient < ActiveRecord::Base
has_many :appointments
has_many :physicians, through: :appointments
belongs_to :hospital
end
I can get it like Patient.first.hospital.appointments. But really need to write a clean activerecord query and also where hospital_id is not null
Thanks
From what I understand, you want to do multiple nested joins with some conditions. This is how it is done cleanly:-
Patient.joins(:appointments => [:physician,:hospital]).where(patients:{<condition_hash_for_patient>},physicians:{<condition_hash_for_physician>},hospitals:{<condition_hash_for_hospital>})

Creating has_many :through Association conditionally

I have the following classes:
class Physician < ActiveRecord::Base
has_many :appointments
has_many :patients, through: :appointments
end
class Appointment < ActiveRecord::Base
belongs_to :physician
belongs_to :patient
end
class Patient < ActiveRecord::Base
has_many :appointments
has_many :physicians, through: :appointments
end
I want only a Physician to be able to create an Appointment, but not a Patient. Please let me know how I can have this restriction at the Model level.
Thanks!
You don't need to use the association to retrieve patients appointmets. Just create a getter method for them:
class Patient < ActiveRecord::Base
def appointments
Appointment.where(patient_id: self.id)
end
end

Resources