I have two models Physician and Patient, like below :
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
p = patient obj.
so, p.appointments.append (physican_obj) is the proper way.
But, if I run the same command twice, it is adding the same thing twice. So, is it good to check if it already exists before appending ? Whats best way to do it ?
My requirement is, I get a list of objects to add it, so I need to loop over each object and append each object. If I need to check before appending, I need to check in every loop which is a costly process.
An approach is to use scope.
class Appointment < ActiveRecord::Base
belongs_to :physician
belongs_to :patient
validate_uniqueness_of :physician_id, scope: :patient_id
end
This will make sure a record which duplicates both two ids won't be allowed.
Related
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.
Happy New Year to everyone!
I have classic has_many through association:
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
However now I need to add has_many association from class Appointment to some class Example, which is in belongs_to association with another model and would be in belongs_to association with class Example.
If possible, how to to set this kind of assosiation? Thank you.
Update
I don't understand, why this question is downvoted.
Here is what I need in class Example :
class Example < ApplicationRecord
belongs_to :appointment
belongs_to :model_bbb
end
Update 2
Ok, I figured out I can use solution from this answer. Basically I can drop "Appointment" model and have class Example like this:
class Example < ApplicationRecord
belongs_to :physician
belongs_to :patient
belongs_to :model_bbb
end
Then in Physician and Patient I can do has_many :examples and another through relationship. I did wanted to do some strange belongs_to through thing as I could have relatively small table of class Appointment, but class Example table is expected to be quite big. So my initial thinking was not to create extra column which will be duplicated for so many times.
You could just add a has_many or has_many through to your Appointment model class.
Keep in mind that belongs_to association is always on the table that has the foreign key. So if you're right at your modeling you should have an appointment_id, for instance, on the examples table.
There's no problem using the associative table in relationship with another. Actually the idea of using an intermediate table is to be able to store other information on it (otherwhise you would be doing HABTM).
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
I have a table called vital_sign which belongs to a patient (the patient has multiple vital signs) and to a physician (the physician captured this vital sign), but I don't care about getting physician.vital_signs, how do I express it in rails models?
I suspect something like this:
vital_signs (belongs_to :patient, belongs_to :physician) with patient_id, physician_id
patient (has_many :vital_signs)
physician (nil)
Is this correct?
You can try this :
class Physician < ActiveRecord::Base
has_many :appointments
has_many :patients, through: :vital_signs
end
class VitalSign < ActiveRecord::Base
belongs_to :physician
belongs_to :patient
end
class Patient < ActiveRecord::Base
has_many :appointments
has_many :physicians, through: :vital_signs
end
I have 3 models:
Lending
Equipment
Category
Lending belongs_to equipment
Equipment belongs_to :category
Equipment has_many :lendings
Category has_many :equipments
I want to show a selectbox in lending's form with the categories.But there's not any association between Lending and Category models.I can't see an association between these two models(Lending and Category) but with Equipment and Category yes.
How do I do that? Ah I'm using simple form!
Excuse my english!
you have generated a textbook example of has_many :through:
http://guides.rubyonrails.org/association_basics.html#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 < 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
You should be using delegation in this case. Add this line to your lending.rb file.
delegate :category, to: :equipment
This will return the concerned category.