Adding and removing from a has_many :through relation - ruby-on-rails

From the Rails associations guide, they demonstrate a many-to-many relationship using has_many :through like so:
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
How would I create and remove appointments?
If I've got a #physician, do I write something like the following for creating an appointment?
#patient = #physician.patients.new params[:patient]
#physician.patients << #patient
#patient.save # Is this line needed?
What about code for deleting or destroying? Also, if a Patient no longer existed in the Appointment table will it get destroyed?

In your code of creating an appointment, the second line is not needed, and using #build method instead of #new:
#patient = #physician.patients.build params[:patient]
#patient.save # yes, it worked
For destroying an appointment record you could simply find it out and destroy:
#appo = #physician.appointments.find(1)
#appo.destroy
If you want to destroy the appointment records along with destroying a patient, you need to add the :dependency setting to has_many:
class Patient < ActiveRecord::Base
has_many :appointments
has_many :physicians, :through => :appointments, :dependency => :destroy
end

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?

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

How to use build method with a has_many :through association

My Models:
class Vip < ActiveRecord::Base
belongs_to :organization
has_many :events
has_many :organizations, :through => :events
end
class Organization < ActiveRecord::Base
belongs_to :user
has_many :events
has_many :vips, :through => :events
end
class Event < ActiveRecord::Base
belongs_to :organization
belongs_to :vip
end
My vips Controller:
def create
#organization = Organization.find(params[:organization_id])
#vip = #organization.vips.build(vip_params)
if #vip.save
redirect_to organization_path(#organization)
else
render 'new'
end
end
def vip_params
params.require(:vip).permit(:name, :about, :organization_id)
end
Before I started using the has_many :through associations, the build method would automatically add the foreign key to the new vip. So my vips table would have the organization_id column populated. Since using the has_many associations, the organization_id column is being left NULL on 'vip#create'.
Is there a reason that build wouldn't work the same way anymore with my new associations?

how to do ruby on rails relationship dependent destroy

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

How can I insert value in a extra column in the relationship table in rails?

Consider these as my table structure
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
My Appointments table has an extra column called relationship. Everytime when i associate the Physician and the patient, I would like to add a relationship [my example sounds weird at so many levels] , how can i insert value into that column?
Why not just this?
patient = Patient.create(:name => 'Humpty Dumpty')
physician = Physician.create(:name => "All the King's horses and all the King's men")
appointment = Appointment.create(:patient => patient, :physician => physician, :relationship => 'surgeon')

Resources